00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifdef G4VIS_BUILD_OPENGLX_DRIVER
00035
00036 #include "G4OpenGLXViewer.hh"
00037 #include "G4VViewer.hh"
00038 #include "G4OpenGLSceneHandler.hh"
00039
00040 #include "G4OpenGLFontBaseStore.hh"
00041
00042 #include <sstream>
00043
00044 #include "G4VisExtent.hh"
00045 #include "G4LogicalVolume.hh"
00046 #include "G4VSolid.hh"
00047 #include "G4Point3D.hh"
00048 #include "G4Normal3D.hh"
00049 #include "G4StateManager.hh"
00050 #include "G4VisManager.hh"
00051 #include "G4Text.hh"
00052
00053 #include <X11/Xatom.h>
00054 #include <X11/Xutil.h>
00055 #include <X11/Xmu/StdCmap.h>
00056
00057 #include <assert.h>
00058
00059 int G4OpenGLXViewer::snglBuf_RGBA[12] =
00060 { GLX_RGBA,
00061 GLX_RED_SIZE, 1,
00062 GLX_GREEN_SIZE, 1,
00063 GLX_BLUE_SIZE, 1,
00064 GLX_DEPTH_SIZE, 1,
00065 GLX_STENCIL_SIZE, 1,
00066 None };
00067
00068 int G4OpenGLXViewer::dblBuf_RGBA[13] =
00069 { GLX_RGBA,
00070 GLX_RED_SIZE, 1,
00071 GLX_GREEN_SIZE, 1,
00072 GLX_BLUE_SIZE, 1,
00073 GLX_DOUBLEBUFFER,
00074 GLX_DEPTH_SIZE, 1,
00075 GLX_STENCIL_SIZE, 1,
00076 None };
00077
00078 #define NewString(str) \
00079 ((str) != 0 ? (strncpy((char*)malloc((unsigned)strlen(str) + 1), str, (unsigned)strlen(str) + 1)) : (char*)0)
00080
00081 #define USE_DEFAULT_COLORMAP 1
00082 #define USE_STANDARD_COLORMAP 0
00083
00084 XVisualInfo* G4OpenGLXViewer::vi_single_buffer = 0;
00085 XVisualInfo* G4OpenGLXViewer::vi_double_buffer = 0;
00086
00087 extern "C" {
00088 static Bool G4OpenGLXViewerWaitForNotify (Display*, XEvent* e, char* arg) {
00089 return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
00090 }
00091 }
00092
00093 void G4OpenGLXViewer::SetView () {
00094 Bool success = glXMakeCurrent (dpy, win, cx);
00095 if (!success) {
00096 fViewId = -1;
00097 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
00098 << G4endl;
00099 GLint error = GL_NO_ERROR;
00100 while ((error = glGetError()) != GL_NO_ERROR) {
00101 G4cout << "GL Error: " << gluErrorString(error) << G4endl;
00102 }
00103 return;
00104 }
00105 G4OpenGLViewer::SetView ();
00106 }
00107
00108 void G4OpenGLXViewer::ShowView () {
00109 glXWaitGL ();
00110
00111 glFlush ();
00112
00113 if (fVP.IsPicking()) {
00114 G4cout <<
00115 "Window activated for picking (left-mouse), exit (middle-mouse)."
00116 << G4endl;
00117 while (true) {
00118 if (XPending(dpy)) {
00119 XNextEvent(dpy, &event);
00120 if (event.type == ButtonPress && event.xbutton.button == 1) {
00121 Pick(event.xbutton.x, event.xbutton.y);
00122 }
00123 else if (event.type == ButtonPress && event.xbutton.button == 2) break;
00124 }
00125 }
00126 }
00127 }
00128
00129 void G4OpenGLXViewer::GetXConnection () {
00130
00131 dpy = XOpenDisplay (0);
00132 if (!dpy) {
00133 fViewId = -1;
00134 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't open display." << G4endl;
00135 return;
00136 }
00137
00138
00139 if (!glXQueryExtension (dpy, &errorBase, &eventBase)) {
00140 fViewId = -1;
00141 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer X Server has no GLX extension."
00142 << G4endl;
00143 return;
00144 }
00145
00146 }
00147
00148 void G4OpenGLXViewer::CreateGLXContext (XVisualInfo* v) {
00149
00150 vi = v;
00151
00152 if (!XGetWindowAttributes(dpy, XRootWindow (dpy, vi -> screen), &xwa)) {
00153 fViewId = -1;
00154 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't return window attributes"
00155 << G4endl;
00156 return;
00157 }
00158
00159
00160 cx = glXCreateContext (dpy, vi, 0, true);
00161 if (!cx) {
00162 fViewId = -1;
00163 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't create context."
00164 << G4endl;
00165 return;
00166 }
00167
00168
00169
00170 Status status;
00171 XStandardColormap *standardCmaps = XAllocStandardColormap ();
00172 int i, numCmaps;
00173
00174 status = XmuLookupStandardColormap (dpy,
00175 vi -> screen,
00176 vi -> visualid,
00177 vi -> depth,
00178 XA_RGB_DEFAULT_MAP,
00179 False,
00180 True);
00181
00182 if (status == 1) {
00183 cmap = 0;
00184 status = XGetRGBColormaps (dpy,
00185 XRootWindow (dpy, vi -> screen),
00186 &standardCmaps,
00187 &numCmaps,
00188 XA_RGB_DEFAULT_MAP);
00189 if (status == 1)
00190 for (i = 0; i < numCmaps; i++) {
00191 if (standardCmaps[i].visualid == vi -> visualid) {
00192 cmap = standardCmaps[i].colormap;
00193 XFree (standardCmaps);
00194 break;
00195 }
00196 }
00197 if (!cmap) {
00198 fViewId = -1;
00199 if (G4VisManager::GetVerbosity() >= G4VisManager::errors)
00200 G4cerr <<
00201 "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a standard colormap."
00202 << G4endl;
00203 return;
00204 }
00205 if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00206 G4cout << "Got standard cmap" << G4endl;
00207 } else {
00208 cmap = XCreateColormap (dpy,
00209 XRootWindow(dpy, vi -> screen),
00210 vi -> visual,
00211 AllocNone);
00212 if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00213 G4cout << "Created own cmap" << G4endl;
00214 }
00215
00216 if (!cmap) {
00217 fViewId = -1;
00218 if (G4VisManager::GetVerbosity() >= G4VisManager::errors)
00219 G4cout << "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a Colormap."
00220 << G4endl;
00221 return;
00222 }
00223
00224 }
00225
00226 void G4OpenGLXViewer::CreateMainWindow () {
00227
00228
00229 swa.colormap = cmap;
00230 swa.border_pixel = 0;
00231 swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
00232 swa.backing_store = WhenMapped;
00233
00234
00235 size_hints = XAllocSizeHints();
00236
00237 ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
00238
00239 G4int x_origin = fVP.GetWindowAbsoluteLocationHintX(DisplayWidth(dpy, vi -> screen));
00240
00241
00242
00243 G4int y_origin = fVP.GetWindowAbsoluteLocationHintY(DisplayHeight(dpy, vi -> screen));
00244
00245 size_hints->base_width = getWinWidth();
00246 size_hints->base_height = getWinHeight();
00247 size_hints->x = x_origin;
00248 size_hints->y = y_origin;
00249 if (fVP.IsWindowSizeHintX () && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
00250 size_hints->flags |= PSize | PPosition;
00251 } else if (fVP.IsWindowSizeHintX () && !(fVP.IsWindowLocationHintX () || fVP.IsWindowLocationHintY ())) {
00252 size_hints->flags |= PSize;
00253 } else if ((!fVP.IsWindowSizeHintX ()) && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
00254 size_hints->flags |= PPosition;
00255 }
00256 if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00257 G4cout << "Window name: " << fName << G4endl;
00258 strncpy (charViewName, fName, 99); charViewName[99] = '\0';
00259 char *window_name = charViewName;
00260 char *icon_name = charViewName;
00261
00262 wm_hints = XAllocWMHints();
00263 class_hints = XAllocClassHint();
00264
00265 XStringListToTextProperty (&window_name, 1, &windowName);
00266 XStringListToTextProperty (&icon_name, 1, &iconName);
00267
00268 wm_hints -> initial_state = NormalState;
00269 wm_hints -> input = True;
00270 wm_hints -> icon_pixmap = icon_pixmap;
00271 wm_hints -> flags = StateHint | IconPixmapHint | InputHint;
00272
00273 class_hints -> res_name = NewString("G4OpenGL");
00274 class_hints -> res_class = NewString("G4OpenGL");
00275
00276 win = XCreateWindow (dpy, XRootWindow (dpy, vi -> screen), x_origin,
00277 y_origin, getWinWidth(), getWinHeight(), 0, vi -> depth,
00278 InputOutput, vi -> visual,
00279 CWBorderPixel | CWColormap |
00280 CWEventMask | CWBackingStore,
00281 &swa);
00282
00283 XSetWMProperties (dpy, win, &windowName, &iconName, 0, 0,
00284 size_hints, wm_hints, class_hints);
00285
00286
00287 XMapWindow (dpy, win);
00288
00289
00290 XIfEvent (dpy, &event, G4OpenGLXViewerWaitForNotify, (char*) win);
00291
00292
00293 Bool success = glXMakeCurrent (dpy, win, cx);
00294 if (!success) {
00295 fViewId = -1;
00296 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
00297 << G4endl;
00298 GLint error = GL_NO_ERROR;
00299 while ((error = glGetError()) != GL_NO_ERROR) {
00300 G4cout << "GL Error: " << gluErrorString(error) << G4endl;
00301 }
00302 return;
00303 }
00304
00305 }
00306
00307 void G4OpenGLXViewer::CreateFontLists()
00308 {
00309 std::map<G4double,G4String> fonts;
00310 fonts[10.] = "-adobe-courier-bold-r-normal--10-100-75-75-m-60-iso8859-1";
00311 fonts[11.] = "-adobe-courier-bold-r-normal--11-80-100-100-m-60-iso8859-1";
00312 fonts[12.] = "-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1";
00313 fonts[13.] = "fixed";
00314 fonts[14.] = "-adobe-courier-bold-r-normal--14-100-100-100-m-90-iso8859-1";
00315 fonts[17.] = "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1";
00316 fonts[18.] = "-adobe-courier-bold-r-normal--18-180-75-75-m-110-iso8859-1";
00317 fonts[20.] = "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1";
00318 fonts[24.] = "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1";
00319 fonts[25.] = "-adobe-courier-bold-r-normal--25-180-100-100-m-150-iso8859-1";
00320 fonts[34.] = "-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1";
00321 std::map<G4double,G4String>::const_iterator i;
00322 for (i = fonts.begin(); i != fonts.end(); ++i) {
00323 XFontStruct* font_info = XLoadQueryFont(dpy, i->second);
00324 if (!font_info) {
00325 G4cerr <<
00326 "G4OpenGLXViewer::CreateFontLists XLoadQueryFont failed for font\n "
00327 << i->second
00328 << G4endl;
00329 continue;
00330 }
00331 G4int font_base = glGenLists(256);
00332 if (!font_base) {
00333 G4cerr <<
00334 "G4OpenGLXViewer::CreateFontLists out of display lists for fonts."
00335 << G4endl;
00336 continue;
00337 }
00338 G4int first = font_info->min_char_or_byte2;
00339 G4int last = font_info->max_char_or_byte2;
00340 glXUseXFont(font_info->fid, first, last-first+1, font_base + first);
00341 G4int width = font_info->max_bounds.width;
00342 G4OpenGLFontBaseStore::AddFontBase
00343 (this, font_base, i->first, i->second, width);
00344 }
00345 }
00346
00347 void G4OpenGLXViewer::DrawText(const G4Text& g4text)
00348 {
00349 if (isGl2psWriting()) {
00350
00351 G4OpenGLViewer::DrawText(g4text);
00352
00353 } else {
00354
00355 G4VSceneHandler::MarkerSizeType sizeType;
00356 G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
00357
00358 const G4OpenGLFontBaseStore::FontInfo& fontInfo =
00359 G4OpenGLFontBaseStore::GetFontInfo(this,(int)size);
00360 if (fontInfo.fFontBase < 0) {
00361 static G4int callCount = 0;
00362 ++callCount;
00363
00364 if (callCount <= 1) {
00365 G4cout <<
00366 "G4OpenGLXViewer::DrawText: No fonts available for \""
00367 << fName <<
00368 "\"\n Called with "
00369 << g4text
00370 << G4endl;
00371 }
00372 return;
00373 }
00374
00375 const G4Colour& c = fSceneHandler.GetTextColour(g4text);
00376 glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
00377
00378 G4Point3D position = g4text.GetPosition();
00379
00380 G4String textString = g4text.GetText();
00381 const char* textCString = textString.c_str();
00382
00383
00384 glRasterPos3d(position.x(),position.y(),position.z());
00385
00386 glPushAttrib(GL_LIST_BIT);
00387
00388
00389 G4double span = textString.size() * fontInfo.fWidth;
00390 G4double xmove = 0., ymove = 0.;
00391 switch (g4text.GetLayout()) {
00392 case G4Text::left: break;
00393 case G4Text::centre: xmove -= span / 2.; break;
00394 case G4Text::right: xmove -= span;
00395 }
00396
00397
00398 xmove += g4text.GetXOffset();
00399 ymove += g4text.GetYOffset();
00400
00401
00402 glBitmap(0,0,0,0,xmove,ymove,0);
00403
00404
00405 glListBase(fontInfo.fFontBase);
00406 glCallLists(strlen(textCString),GL_UNSIGNED_BYTE,(GLubyte*)textCString);
00407 glPopAttrib();
00408 }
00409 }
00410
00411
00412 G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLSceneHandler& scene):
00413 G4VViewer (scene, -1),
00414 G4OpenGLViewer (scene),
00415 vi_immediate (0),
00416 vi_stored (0),
00417 vi (0),
00418 cmap (0)
00419 {
00420
00421 xwa.visual = 0;
00422 iconName.value = 0;
00423 xwa.screen = 0;
00424 windowName.value = 0;
00425
00426 GetXConnection ();
00427 if (fViewId < 0) return;
00428
00429
00430
00431 if (!vi_single_buffer) {
00432 vi_single_buffer =
00433 glXChooseVisual (dpy, XDefaultScreen (dpy), snglBuf_RGBA);
00434 }
00435 if (!vi_double_buffer) {
00436 vi_double_buffer =
00437 glXChooseVisual (dpy, XDefaultScreen (dpy), dblBuf_RGBA);
00438 }
00439
00440 if (vi_single_buffer || vi_double_buffer) {
00441 if (!vi_double_buffer) {
00442 G4cout <<
00443 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
00444 "\n Working with a single buffer."
00445 << G4endl;
00446 }
00447 } else {
00448 if (!vi_single_buffer) {
00449 G4cout <<
00450 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a single buffer visual."
00451 << G4endl;
00452 }
00453 if (!vi_double_buffer) {
00454 G4cout <<
00455 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
00456 << G4endl;
00457 }
00458 }
00459
00460 if (vi_single_buffer) {
00461 vi_immediate = vi_single_buffer;
00462 attributeList = snglBuf_RGBA;
00463 }
00464
00465 if (!vi_immediate){
00466
00467 if (vi_double_buffer) {
00468 vi_immediate = vi_double_buffer;
00469 attributeList = dblBuf_RGBA;
00470 }
00471 }
00472
00473
00474
00475 if (vi_double_buffer) {
00476 vi_stored = vi_double_buffer;
00477 attributeList = dblBuf_RGBA;
00478 }
00479
00480 if (!vi_immediate || !vi_stored) {
00481 G4cout <<
00482 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get required visuals."
00483 << G4endl;
00484 fViewId = -1;
00485 }
00486
00487
00488
00489 }
00490
00491 G4OpenGLXViewer::~G4OpenGLXViewer () {
00492 if (fViewId >= 0) {
00493
00494 glXMakeCurrent (dpy, None, NULL);
00495 glXDestroyContext (dpy, cx);
00496 if (win) XDestroyWindow (dpy, win);
00497
00498 XFlush (dpy);
00499 }
00500 }
00501
00502
00503 #endif