Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // 26 // 23 // >> 24 // $Id: G4OpenGLXViewer.cc,v 1.13 2001/11/29 12:14:01 johna Exp $ >> 25 // GEANT4 tag $Name: geant4-04-00 $ 27 // 26 // 28 // 27 // 29 // Andrew Walkden 7th February 1997 28 // Andrew Walkden 7th February 1997 30 // G4OpenGLXViewer : Class to provide XWindows 29 // G4OpenGLXViewer : Class to provide XWindows specific 31 // functionality for OpenGL in 30 // functionality for OpenGL in GEANT4 32 31 >> 32 #ifdef G4VIS_BUILD_OPENGL_DRIVER >> 33 33 #include "G4OpenGLXViewer.hh" 34 #include "G4OpenGLXViewer.hh" 34 35 35 #include "G4OpenGLSceneHandler.hh" << 36 #include <GL/gl.h> 36 #include "G4OpenGLFontBaseStore.hh" << 37 #include <GL/glx.h> >> 38 #include <GL/glu.h> >> 39 >> 40 #include "G4ios.hh" >> 41 #include <assert.h> >> 42 #include <unistd.h> >> 43 #include <string.h> 37 44 38 #include "G4VisExtent.hh" 45 #include "G4VisExtent.hh" 39 #include "G4LogicalVolume.hh" 46 #include "G4LogicalVolume.hh" 40 #include "G4VSolid.hh" 47 #include "G4VSolid.hh" 41 #include "G4Point3D.hh" 48 #include "G4Point3D.hh" 42 #include "G4Normal3D.hh" 49 #include "G4Normal3D.hh" 43 #include "G4StateManager.hh" << 44 #include "G4VisManager.hh" << 45 #include "G4Text.hh" << 46 #include "G4Threading.hh" << 47 50 48 #include <X11/Xatom.h> 51 #include <X11/Xatom.h> 49 #include <X11/Xutil.h> 52 #include <X11/Xutil.h> 50 #include <X11/Xmu/StdCmap.h> << 51 53 52 #include <assert.h> << 54 #include <stdlib.h> 53 #include <sstream> << 55 #include <string.h> 54 #include <chrono> << 55 #include <thread> << 56 << 57 int G4OpenGLXViewer::snglBuf_RGBA[12] = << 58 { GLX_RGBA, << 59 GLX_RED_SIZE, 1, << 60 GLX_GREEN_SIZE, 1, << 61 GLX_BLUE_SIZE, 1, << 62 GLX_DEPTH_SIZE, 1, << 63 GLX_STENCIL_SIZE, 1, << 64 None }; << 65 << 66 int G4OpenGLXViewer::dblBuf_RGBA[13] = << 67 { GLX_RGBA, << 68 GLX_RED_SIZE, 1, << 69 GLX_GREEN_SIZE, 1, << 70 GLX_BLUE_SIZE, 1, << 71 GLX_DOUBLEBUFFER, << 72 GLX_DEPTH_SIZE, 1, << 73 GLX_STENCIL_SIZE, 1, << 74 None }; << 75 56 76 #define NewString(str) \ 57 #define NewString(str) \ 77 ((str) != 0 ? (strncpy((char*)malloc((unsign << 58 ((str) != NULL ? (strcpy((char*)malloc((unsigned)strlen(str) + 1), str)) : (char*)NULL) 78 59 79 #define USE_DEFAULT_COLORMAP 1 60 #define USE_DEFAULT_COLORMAP 1 80 #define USE_STANDARD_COLORMAP 0 61 #define USE_STANDARD_COLORMAP 0 81 62 >> 63 static const char* gouraudtriangleEPS[] = >> 64 { >> 65 "/bd{bind def}bind def /triangle { aload pop setrgbcolor aload pop 5 3", >> 66 "roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd", >> 67 "/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2", >> 68 "index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse", >> 69 "} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get", >> 70 "computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get", >> 71 "computediff1 {true} { 3 copy 2 get 3 1 roll 2 get 3 1 roll 2 get", >> 72 "computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll", >> 73 "aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2", >> 74 "div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4", >> 75 "-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add", >> 76 "2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1", >> 77 "roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3", >> 78 "1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll", >> 79 "2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll", >> 80 "aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array", >> 81 "astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17", >> 82 "index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index", >> 83 "gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6", >> 84 "array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index", >> 85 "15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14", >> 86 "index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3", >> 87 "roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7", >> 88 "index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add", >> 89 "add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd", >> 90 NULL >> 91 }; >> 92 82 XVisualInfo* G4OpenGLXViewer::vi_single_buffe 93 XVisualInfo* G4OpenGLXViewer::vi_single_buffer = 0; 83 XVisualInfo* G4OpenGLXViewer::vi_double_buffe 94 XVisualInfo* G4OpenGLXViewer::vi_double_buffer = 0; 84 95 85 extern "C" { << 96 extern "C" 86 static Bool G4OpenGLXViewerWaitForNotify (Di << 97 { >> 98 static Bool WaitForNotify (Display*, XEvent* e, char* arg) { 87 return (e->type == MapNotify) && (e->xmap. 99 return (e->type == MapNotify) && (e->xmap.window == (Window) arg); 88 } 100 } 89 } 101 } 90 102 91 void G4OpenGLXViewer::SetView () { 103 void G4OpenGLXViewer::SetView () { 92 if (G4Threading::IsMasterThread()) { << 104 glXMakeCurrent (dpy, win, cx); 93 glXMakeCurrent (dpy, win, cxMaster); << 105 G4OpenGLViewer::SetView (); 94 } else { << 95 glXMakeCurrent (dpy, win, cxVisSubThread); << 96 } << 97 G4OpenGLViewer::SetView (); << 98 } 106 } 99 107 100 void G4OpenGLXViewer::ShowView () { 108 void G4OpenGLXViewer::ShowView () { 101 // glXWaitGL (); //Wait for effects of all pr << 109 glXWaitGL (); //Wait for effects of all previous OpenGL commands to 102 //be propagated before progres << 110 //be propogated before progressing. 103 // JA: Commented out July 2021 - slows renderi << 104 // don't see any adverse effects. << 105 << 106 glFlush (); 111 glFlush (); 107 << 108 if (fVP.IsPicking()) { << 109 G4cout << << 110 "Window activated for picking (left-mous << 111 << G4endl; << 112 while (true) { << 113 if (XPending(dpy)) { << 114 XNextEvent(dpy, &event); << 115 if (event.type == ButtonPress && event.xbutt << 116 G4cout << Pick(event.xbutton.x, event.xbut << 117 } << 118 else if (event.type == ButtonPress && event. << 119 } << 120 std::this_thread::sleep_for(std::chrono: << 121 } << 122 } << 123 } << 124 << 125 void G4OpenGLXViewer::SwitchToVisSubThread() << 126 { << 127 #ifdef G4MULTITHREADED << 128 cxVisSubThread = glXCreateContext (dpy, vi, << 129 glXMakeCurrent (dpy, win, cxVisSubThread); << 130 #endif << 131 } 112 } 132 113 133 void G4OpenGLXViewer::SwitchToMasterThread() << 114 void G4OpenGLXViewer::FinishView () { 134 { << 115 glXWaitGL (); //Wait for effects of all previous OpenGL commands to 135 #ifdef G4MULTITHREADED << 116 //be propogated before progressing. 136 glXMakeCurrent (dpy, win, cxMaster); << 117 if (doublebuffer == true) { 137 // and destroy sub-thread context << 118 glXSwapBuffers (dpy, win); 138 glXDestroyContext (dpy, cxVisSubThread); << 119 } 139 #endif << 120 else glFlush (); 140 } 121 } 141 122 142 void G4OpenGLXViewer::GetXConnection () { 123 void G4OpenGLXViewer::GetXConnection () { 143 // get a connection. 124 // get a connection. 144 dpy = XOpenDisplay (0); // Uses DISPLAY env << 125 dpy = XOpenDisplay (0); 145 if (!dpy) { 126 if (!dpy) { 146 fViewId = -1; // This flags an error. 127 fViewId = -1; // This flags an error. 147 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewe << 128 G4cerr << "G4OpenGLViewer::G4OpenGLViewer couldn't open display." << G4endl; 148 return; 129 return; 149 } 130 } 150 131 151 // make sure OpenGL is supported and installed 132 // make sure OpenGL is supported and installed properly. 152 if (!glXQueryExtension (dpy, &errorBase, &ev 133 if (!glXQueryExtension (dpy, &errorBase, &eventBase)) { 153 fViewId = -1; // This flags an error. 134 fViewId = -1; // This flags an error. 154 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewe << 135 G4cerr << "G4OpenGLViewer::G4OpenGLViewer X Server has no GLX extension." 155 << G4endl; 136 << G4endl; 156 return; 137 return; 157 } 138 } 158 << 159 } 139 } 160 140 161 void G4OpenGLXViewer::CreateGLXContext (XVisua 141 void G4OpenGLXViewer::CreateGLXContext (XVisualInfo* v) { 162 142 163 vi = v; 143 vi = v; 164 // get window's attributes 144 // get window's attributes 165 if (!XGetWindowAttributes(dpy, XRootWindow ( 145 if (!XGetWindowAttributes(dpy, XRootWindow (dpy, vi -> screen), &xwa)) { 166 fViewId = -1; // This flags an error. 146 fViewId = -1; // This flags an error. 167 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewe << 147 G4cerr << "G4OpenGLViewer::G4OpenGLViewer couldn't return window attributes" 168 << G4endl; 148 << G4endl; 169 return; 149 return; 170 } 150 } 171 151 172 // create the master GLX context << 152 // create a GLX context 173 cxMaster = glXCreateContext (dpy, vi, 0, tru << 153 cx = glXCreateContext (dpy, vi, 0, true); 174 if (!cxMaster) { << 154 if (!cx) { 175 fViewId = -1; // This flags an error. 155 fViewId = -1; // This flags an error. 176 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewe << 156 G4cerr << "G4OpenGLViewer::G4OpenGLViewer couldn't create context." 177 << G4endl; 157 << G4endl; 178 return; 158 return; 179 } 159 } 180 160 181 // New stab at getting a colormap 161 // New stab at getting a colormap 182 162 183 Status status; 163 Status status; >> 164 XStandardColormap *standardCmaps = XAllocStandardColormap (); 184 int i, numCmaps; 165 int i, numCmaps; 185 166 186 status = XmuLookupStandardColormap (dpy, 167 status = XmuLookupStandardColormap (dpy, 187 vi -> screen, 168 vi -> screen, 188 vi -> visualid, 169 vi -> visualid, 189 vi -> depth, 170 vi -> depth, 190 XA_RGB_BEST_MAP, << 171 XA_RGB_DEFAULT_MAP, 191 False, 172 False, 192 True); 173 True); 193 << 174 194 if (status == 1) { 175 if (status == 1) { 195 cmap = 0; << 196 XStandardColormap* standardCmaps = XAllocS << 197 status = XGetRGBColormaps (dpy, 176 status = XGetRGBColormaps (dpy, 198 XRootWindow (dpy, vi -> screen), << 177 XRootWindow (dpy, vi -> screen), 199 &standardCmaps, 178 &standardCmaps, 200 &numCmaps, 179 &numCmaps, 201 XA_RGB_BEST_MAP); << 180 XA_RGB_DEFAULT_MAP); 202 if (status == 1) { << 181 if (status == 1) 203 for (i = 0; i < numCmaps; i++) { << 182 for (i = 0; i < numCmaps; i++) 204 if (standardCmaps[i].visualid == vi -> visua 183 if (standardCmaps[i].visualid == vi -> visualid) { 205 cmap = standardCmaps[i].colormap; 184 cmap = standardCmaps[i].colormap; 206 break; << 185 XFree (standardCmaps); 207 } 186 } 208 } << 187 G4cout << "Got standard cmap" << G4endl; 209 } << 210 XFree (standardCmaps); << 211 if(cmap) { << 212 if (G4VisManager::GetVerbosity() >= G4Vi << 213 G4cout << "Got standard cmap" << G4end << 214 } else { << 215 //if (G4VisManager::GetVerbosity() >= G4 << 216 // G4cerr << "G4OpenGLXViewer::G4OpenGL << 217 // << G4endl; << 218 cmap = XCreateColormap (dpy, << 219 XRootWindow(dpy, << 220 vi -> visual, << 221 AllocNone); << 222 if(cmap) { << 223 if (G4VisManager::GetVerbosity() >= G4 << 224 G4cout << "Created own cmap" << G4en << 225 } << 226 //G.Barrand : at end, we should do a XFr << 227 } << 228 } else { 188 } else { 229 cmap = XCreateColormap (dpy, 189 cmap = XCreateColormap (dpy, 230 XRootWindow(dpy, vi -> screen), 190 XRootWindow(dpy, vi -> screen), 231 vi -> visual, 191 vi -> visual, 232 AllocNone); 192 AllocNone); 233 if(cmap) { << 193 G4cout << "Created own cmap" << G4endl; 234 if (G4VisManager::GetVerbosity() >= G4Vi << 235 G4cout << "Created own cmap" << G4endl << 236 } << 237 //G.Barrand : at end, we should do a XFree << 238 } 194 } 239 195 240 if (!cmap) { 196 if (!cmap) { 241 fViewId = -1; // This flags an error. 197 fViewId = -1; // This flags an error. 242 if (G4VisManager::GetVerbosity() >= G4VisM << 198 G4cerr << "G4OpenGLViewer::G4OpenGLViewer failed to allocate a Colormap." 243 G4cout << "G4OpenGLXViewer::G4OpenGLXVie << 199 << G4endl; 244 << G4endl; << 245 return; 200 return; 246 } 201 } 247 202 248 } 203 } 249 204 250 void G4OpenGLXViewer::CreateMainWindow () { 205 void G4OpenGLXViewer::CreateMainWindow () { 251 206 252 // create a window 207 // create a window 253 swa.colormap = cmap; 208 swa.colormap = cmap; 254 swa.border_pixel = 0; 209 swa.border_pixel = 0; 255 swa.event_mask = ExposureMask | ButtonPressM 210 swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask; 256 swa.backing_store = WhenMapped; 211 swa.backing_store = WhenMapped; 257 212 258 // Window size and position... << 213 // G4int WinSize_x; 259 size_hints = XAllocSizeHints(); << 214 // G4int WinSize_y; 260 << 215 if (xwa.width > xwa.height) { 261 ResizeWindow(fVP.GetWindowSizeHintX(),fVP.Ge << 216 WinSize_x = (xwa.height)/2; 262 << 217 WinSize_y = (xwa.height)/2; 263 G4int x_origin = fVP.GetWindowAbsoluteLocati << 218 } 264 << 219 else { 265 // FIXME, screen size != window size on MAC << 220 WinSize_x = (xwa.width)/2; 266 // size on MAC. L.Garnier 01/2009 << 221 WinSize_y = (xwa.width)/2; 267 G4int y_origin = fVP.GetWindowAbsoluteLocati << 222 } 268 << 223 if (WinSize_x < fVP.GetWindowSizeHintX ()) 269 size_hints->base_width = getWinWidth(); << 224 WinSize_x = fVP.GetWindowSizeHintX (); 270 size_hints->base_height = getWinHeight(); << 225 if (WinSize_y < fVP.GetWindowSizeHintY ()) 271 size_hints->x = x_origin; << 226 WinSize_y = fVP.GetWindowSizeHintY (); 272 size_hints->y = y_origin; << 227 x_origin = xwa.x; 273 if (fVP.IsWindowSizeHintX () && fVP.IsWindow << 228 y_origin = xwa.y; 274 size_hints->flags |= PSize | PPosition; << 229 G4cout << "Window name: " << fName << G4endl; 275 } else if (fVP.IsWindowSizeHintX () && !(fVP << 230 strncpy (charViewName, fName, 100); 276 size_hints->flags |= PSize; << 277 } else if ((!fVP.IsWindowSizeHintX ()) && fV << 278 size_hints->flags |= PPosition; << 279 } << 280 if (G4VisManager::GetVerbosity() >= G4VisMan << 281 G4cout << "Window name: " << fName << G4en << 282 strncpy (charViewName, fName, 99); charViewN << 283 char *window_name = charViewName; 231 char *window_name = charViewName; 284 char *icon_name = charViewName; 232 char *icon_name = charViewName; 285 //char tmpatom[] = "XA_WM_NORMAL_HINTS"; 233 //char tmpatom[] = "XA_WM_NORMAL_HINTS"; >> 234 size_hints = XAllocSizeHints(); 286 wm_hints = XAllocWMHints(); 235 wm_hints = XAllocWMHints(); 287 class_hints = XAllocClassHint(); 236 class_hints = XAllocClassHint(); 288 237 >> 238 size_hints -> flags = PPosition | PSize | PMinSize; >> 239 size_hints -> min_width = 300; >> 240 size_hints -> min_height = 200; >> 241 289 XStringListToTextProperty (&window_name, 1, 242 XStringListToTextProperty (&window_name, 1, &windowName); 290 XStringListToTextProperty (&icon_name, 1, &i 243 XStringListToTextProperty (&icon_name, 1, &iconName); 291 244 292 wm_hints -> initial_state = NormalState; 245 wm_hints -> initial_state = NormalState; 293 wm_hints -> input = True; 246 wm_hints -> input = True; 294 wm_hints -> icon_pixmap = icon_pixmap; 247 wm_hints -> icon_pixmap = icon_pixmap; 295 wm_hints -> flags = StateHint | IconPixmapHi 248 wm_hints -> flags = StateHint | IconPixmapHint | InputHint; 296 249 297 class_hints -> res_name = NewString("G4Open 250 class_hints -> res_name = NewString("G4OpenGL"); 298 class_hints -> res_class = NewString("G4Open 251 class_hints -> res_class = NewString("G4OpenGL"); 299 252 300 win = XCreateWindow (dpy, XRootWindow (dpy, << 253 win = XCreateWindow (dpy, XRootWindow (dpy, vi -> screen), x_origin, 301 y_origin, getWinWidth( << 254 y_origin, WinSize_x, WinSize_y, 0, vi -> depth, 302 InputOutput, vi -> vis << 255 InputOutput, vi -> visual, 303 CWBorderPixel | CWColo << 256 CWBorderPixel | CWColormap | 304 CWEventMask | CWBackin << 257 CWEventMask | CWBackingStore, 305 &swa); << 258 &swa); 306 259 307 XSetWMProperties (dpy, win, &windowName, &i << 260 XSetWMProperties (dpy, win, &windowName, &iconName, 0, 0, 308 size_hints, wm_hints, cla << 261 size_hints, wm_hints, class_hints); 309 262 310 // request X to Draw window on screen. 263 // request X to Draw window on screen. 311 XMapWindow (dpy, win); 264 XMapWindow (dpy, win); 312 265 313 // Wait for window to appear (wait for an "exp 266 // Wait for window to appear (wait for an "expose" event). 314 XIfEvent (dpy, &event, G4OpenGLXViewerWaitFo << 267 XIfEvent (dpy, &event, WaitForNotify, (char*) win); 315 268 316 // connect the context to a window 269 // connect the context to a window 317 Bool success = glXMakeCurrent (dpy, win, cxM << 270 glXMakeCurrent (dpy, win, cx); 318 if (!success) { << 319 fViewId = -1; // This flags an error. << 320 G4cerr << "G4OpenGLXViewer::G4OpenGLXViewe << 321 << G4endl; << 322 GLint error = GL_NO_ERROR; << 323 while ((error = glGetError()) != GL_NO_ERR << 324 switch (error) { << 325 case GL_INVALID_ENUM : << 326 G4cout << "GL Error: GL_INVALID_ENUM" << G4e << 327 case GL_INVALID_VALUE : << 328 G4cout << "GL Error: GL_INVALID_VALUE" << G4 << 329 case GL_INVALID_OPERATION : << 330 G4cout << "GL Error: GL_INVALID_OPERATION" < << 331 case GL_OUT_OF_MEMORY : << 332 G4cout << "GL Error: GL_OUT_OF_MEMORY" << G4 << 333 case GL_STACK_UNDERFLOW : << 334 G4cout << "GL Error: GL_STACK_UNDERFLOW" << << 335 case GL_STACK_OVERFLOW : << 336 G4cout << "GL Error: GL_STACK_OVERFLOW" << G << 337 default : << 338 G4cout << "GL Error: " << error << G4endl;br << 339 } << 340 } << 341 return; << 342 } << 343 } << 344 << 345 void G4OpenGLXViewer::CreateFontLists() << 346 { << 347 std::map<G4double,G4String> fonts; // G4VMa << 348 fonts[10.] = "-adobe-courier-bold-r-normal-- << 349 fonts[11.] = "-adobe-courier-bold-r-normal-- << 350 fonts[12.] = "-adobe-courier-bold-r-normal-- << 351 fonts[13.] = "fixed"; << 352 fonts[14.] = "-adobe-courier-bold-r-normal-- << 353 fonts[17.] = "-adobe-courier-bold-r-normal-- << 354 fonts[18.] = "-adobe-courier-bold-r-normal-- << 355 fonts[20.] = "-adobe-courier-bold-r-normal-- << 356 fonts[24.] = "-adobe-courier-bold-r-normal-- << 357 fonts[25.] = "-adobe-courier-bold-r-normal-- << 358 fonts[34.] = "-adobe-courier-bold-r-normal-- << 359 std::map<G4double,G4String>::const_iterator << 360 for (i = fonts.begin(); i != fonts.end(); ++ << 361 XFontStruct* font_info = XLoadQueryFont(dp << 362 if (!font_info) { << 363 G4cerr << << 364 "G4OpenGLXViewer::CreateFontLists XLoadQuery << 365 << i->second << 366 << G4endl; << 367 continue; << 368 } << 369 G4int font_base = glGenLists(256); << 370 if (!font_base) { << 371 G4cerr << << 372 "G4OpenGLXViewer::CreateFontLists out of dis << 373 << G4endl; << 374 continue; << 375 } << 376 G4int first = font_info->min_char_or_byte2 << 377 G4int last = font_info->max_char_or_byte2 << 378 glXUseXFont(font_info->fid, first, last-fi << 379 G4int width = font_info->max_bounds.width; << 380 G4OpenGLFontBaseStore::AddFontBase << 381 (this, font_base, i->first, i->second, w << 382 } << 383 } 271 } 384 272 385 void G4OpenGLXViewer::DrawText(const G4Text& g << 386 { << 387 if (isGl2psWriting()) { << 388 << 389 G4OpenGLViewer::DrawText(g4text); << 390 << 391 } else { << 392 << 393 G4VSceneHandler::MarkerSizeType sizeType; << 394 G4double size = fSceneHandler.GetMarkerSiz << 395 << 396 const G4OpenGLFontBaseStore::FontInfo& fon << 397 G4OpenGLFontBaseStore::GetFontInfo(this, << 398 if (fontInfo.fFontBase < 0) { << 399 static G4int callCount = 0; << 400 ++callCount; << 401 //if (callCount <= 10 || callCount%100 = << 402 if (callCount <= 1) { << 403 G4cout << << 404 "G4OpenGLXViewer::DrawText: No fonts avail << 405 << fName << << 406 "\"\n Called with " << 407 << g4text << 408 << G4endl; << 409 } << 410 return; << 411 } << 412 << 413 const G4Colour& c = fSceneHandler.GetTextC << 414 glColor4d(c.GetRed(),c.GetGreen(),c.GetBlu << 415 << 416 G4Point3D position = g4text.GetPosition(); << 417 << 418 G4String textString = g4text.GetText(); << 419 const char* textCString = textString.c_str << 420 << 421 // Set position for raster-style drawers ( << 422 glRasterPos3d(position.x(),position.y(),po << 423 << 424 glPushAttrib(GL_LIST_BIT); << 425 << 426 // Calculate move for centre and right adj << 427 G4double span = textString.size() * fontIn << 428 G4double xmove = 0., ymove = 0.; << 429 switch (g4text.GetLayout()) { << 430 case G4Text::left: break; << 431 case G4Text::centre: xmove -= span / 2.; b << 432 case G4Text::right: xmove -= span; << 433 } << 434 << 435 //Add offsets << 436 xmove += g4text.GetXOffset(); << 437 ymove += g4text.GetYOffset(); << 438 << 439 // Do move << 440 glBitmap(0,0,0,0,xmove,ymove,0); << 441 << 442 // Write characters << 443 glListBase(fontInfo.fFontBase); << 444 glCallLists((G4int)strlen(textCString),GL_ << 445 glPopAttrib(); << 446 } << 447 } << 448 << 449 << 450 G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLScen 273 G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLSceneHandler& scene): 451 G4VViewer (scene, -1), 274 G4VViewer (scene, -1), 452 G4OpenGLViewer (scene), 275 G4OpenGLViewer (scene), >> 276 print_colour (true), >> 277 vectored_ps (true), 453 vi_immediate (0), 278 vi_immediate (0), 454 vi_stored (0), << 279 vi_stored (0) 455 vi (0), << 456 cmap (0) << 457 { 280 { 458 // To satisfy Coverity << 281 459 xwa.visual = 0; << 282 strcpy (print_string, "G4OpenGL.eps"); 460 iconName.value = 0; << 461 xwa.screen = 0; << 462 windowName.value = 0; << 463 283 464 GetXConnection (); 284 GetXConnection (); 465 if (fViewId < 0) return; 285 if (fViewId < 0) return; 466 286 467 // Try for a visual suitable for OpenGLImmed 287 // Try for a visual suitable for OpenGLImmediate.. 468 // first try for a single buffered RGB windo 288 // first try for a single buffered RGB window 469 if (!vi_single_buffer) { 289 if (!vi_single_buffer) { 470 vi_single_buffer = 290 vi_single_buffer = 471 glXChooseVisual (dpy, XDefaultScreen (dp 291 glXChooseVisual (dpy, XDefaultScreen (dpy), snglBuf_RGBA); 472 //G.Barrand : we should do a XFree(vi_sing << 473 } 292 } >> 293 if (!vi_single_buffer) { >> 294 G4cout << >> 295 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a single buffer visual." >> 296 << G4endl; >> 297 } >> 298 474 if (!vi_double_buffer) { 299 if (!vi_double_buffer) { 475 vi_double_buffer = 300 vi_double_buffer = 476 glXChooseVisual (dpy, XDefaultScreen (dp 301 glXChooseVisual (dpy, XDefaultScreen (dpy), dblBuf_RGBA); 477 //G.Barrand : we should do a XFree(vi_doub << 478 } 302 } 479 << 303 if (!vi_double_buffer) { 480 if (vi_single_buffer || vi_double_buffer) { << 304 G4cout << 481 if (!vi_double_buffer) { << 305 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual." 482 G4cout << << 306 << G4endl; 483 "G4OpenGLXViewer::G4OpenGLXViewer: unable to << 484 "\n Working with a single buffer." << 485 << G4endl; << 486 } << 487 } else { << 488 if (!vi_single_buffer) { << 489 G4cout << << 490 "G4OpenGLXViewer::G4OpenGLXViewer: unable to << 491 << G4endl; << 492 } << 493 if (!vi_double_buffer) { << 494 G4cout << << 495 "G4OpenGLXViewer::G4OpenGLXViewer: unable to << 496 << G4endl; << 497 } << 498 } 307 } 499 308 500 if (vi_single_buffer) { 309 if (vi_single_buffer) { 501 vi_immediate = vi_single_buffer; 310 vi_immediate = vi_single_buffer; 502 attributeList = snglBuf_RGBA; 311 attributeList = snglBuf_RGBA; >> 312 doublebuffer = false; 503 } 313 } 504 314 505 if (!vi_immediate){ 315 if (!vi_immediate){ 506 // next try for a double buffered RGB, but 316 // next try for a double buffered RGB, but Draw to top buffer 507 if (vi_double_buffer) { 317 if (vi_double_buffer) { 508 vi_immediate = vi_double_buffer; 318 vi_immediate = vi_double_buffer; 509 attributeList = dblBuf_RGBA; 319 attributeList = dblBuf_RGBA; >> 320 doublebuffer = true; 510 } 321 } 511 } 322 } 512 323 513 // Now try for a visual suitable for OpenGLS 324 // Now try for a visual suitable for OpenGLStored... 514 // Try for a double buffered RGB window 325 // Try for a double buffered RGB window 515 if (vi_double_buffer) { 326 if (vi_double_buffer) { 516 vi_stored = vi_double_buffer; 327 vi_stored = vi_double_buffer; 517 attributeList = dblBuf_RGBA; 328 attributeList = dblBuf_RGBA; >> 329 doublebuffer = true; 518 } 330 } 519 331 520 if (!vi_immediate || !vi_stored) { 332 if (!vi_immediate || !vi_stored) { 521 G4cout << 333 G4cout << 522 "G4OpenGLXViewer::G4OpenGLXViewer: unable 334 "G4OpenGLXViewer::G4OpenGLXViewer: unable to get required visuals." 523 << G4endl; 335 << G4endl; 524 fViewId = -1; // This flags an error. 336 fViewId = -1; // This flags an error. 525 } 337 } 526 338 527 // glClearColor (0., 0., 0., 0.); 339 // glClearColor (0., 0., 0., 0.); 528 // glClearDepth (1.); 340 // glClearDepth (1.); >> 341 529 } 342 } 530 343 531 G4OpenGLXViewer::~G4OpenGLXViewer () { 344 G4OpenGLXViewer::~G4OpenGLXViewer () { 532 if (fViewId >= 0) { 345 if (fViewId >= 0) { 533 //Close a window from here 346 //Close a window from here >> 347 glXDestroyContext (dpy, cx); 534 glXMakeCurrent (dpy, None, NULL); 348 glXMakeCurrent (dpy, None, NULL); 535 glXDestroyContext (dpy, cxMaster); << 536 if (win) XDestroyWindow (dpy, win); // ... 349 if (win) XDestroyWindow (dpy, win); // ...if already deleted in 537 // sub-class G4OpenGLXmViewer. 350 // sub-class G4OpenGLXmViewer. 538 // We should do a XFreeColormap(dpy,cmap); << 539 XFlush (dpy); 351 XFlush (dpy); 540 } 352 } 541 } 353 } 542 << 354 >> 355 void G4OpenGLXViewer::print() { >> 356 >> 357 //cout << "print_col_callback requested with file name: " << print_string << G4endl; >> 358 >> 359 if (vectored_ps) { >> 360 G4int size = 5000000; >> 361 >> 362 GLfloat* feedback_buffer; >> 363 GLint returned; >> 364 FILE* file; >> 365 >> 366 feedback_buffer = new GLfloat[size]; >> 367 glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer); >> 368 glRenderMode (GL_FEEDBACK); >> 369 >> 370 DrawView(); >> 371 returned = glRenderMode (GL_RENDER); >> 372 >> 373 if (print_string) { >> 374 file = fopen (print_string, "w"); >> 375 if (file) { >> 376 spewWireframeEPS (file, returned, feedback_buffer, "rendereps"); >> 377 } else { >> 378 printf("Could not open %s\n", print_string); >> 379 } >> 380 } else { >> 381 printBuffer (returned, feedback_buffer); >> 382 } >> 383 // free (feedback_buffer); >> 384 delete[] feedback_buffer; >> 385 >> 386 } else { >> 387 >> 388 XVisualInfo* pvi; >> 389 G4bool new_db; >> 390 G4bool last_db; >> 391 GLXContext pcx = create_GL_print_context(pvi, new_db); >> 392 GLXContext tmp_cx; >> 393 tmp_cx = cx; >> 394 cx=pcx; >> 395 last_db=doublebuffer; >> 396 doublebuffer=new_db; >> 397 >> 398 Pixmap pmap = XCreatePixmap (dpy, >> 399 XRootWindow (dpy, pvi->screen), >> 400 WinSize_x, WinSize_y, >> 401 pvi->depth); >> 402 >> 403 GLXPixmap glxpmap = glXCreateGLXPixmap (dpy, >> 404 pvi, >> 405 pmap); >> 406 >> 407 GLXDrawable tmp_win; >> 408 tmp_win=win; >> 409 win=glxpmap; >> 410 >> 411 glXMakeCurrent (dpy, >> 412 glxpmap, >> 413 cx); >> 414 >> 415 glViewport (0, 0, WinSize_x, WinSize_y); >> 416 >> 417 ClearView (); >> 418 DrawView (); >> 419 >> 420 generateEPS (print_string, >> 421 print_colour, >> 422 WinSize_x, WinSize_y); >> 423 >> 424 win=tmp_win; >> 425 cx=tmp_cx; >> 426 doublebuffer=last_db; >> 427 >> 428 glXMakeCurrent (dpy, >> 429 glxpmap, >> 430 cx); >> 431 >> 432 } >> 433 >> 434 } >> 435 >> 436 void G4OpenGLXViewer::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer) >> 437 { >> 438 G4int i; >> 439 >> 440 printf(" "); >> 441 for (i = 0; i < 7; i++) { >> 442 printf("%4.2f ", buffer[size - (*count)]); >> 443 *count = *count - 1; >> 444 } >> 445 printf("\n"); >> 446 } >> 447 >> 448 void G4OpenGLXViewer::spewWireframeEPS (FILE* file, GLint size, GLfloat* buffer, const char* cr) { >> 449 >> 450 GLfloat EPS_GOURAUD_THRESHOLD=0.1; >> 451 >> 452 GLfloat clearColor[4], viewport[4]; >> 453 GLfloat lineWidth; >> 454 G4int i; >> 455 >> 456 glGetFloatv (GL_VIEWPORT, viewport); >> 457 glGetFloatv (GL_COLOR_CLEAR_VALUE, clearColor); >> 458 glGetFloatv (GL_LINE_WIDTH, &lineWidth); >> 459 glGetFloatv (GL_POINT_SIZE, &pointSize); >> 460 >> 461 fputs ("%!PS-Adobe-2.0 EPSF-2.0\n", file); >> 462 fprintf (file, "%%%%Creator: %s (using OpenGL feedback)\n", cr); >> 463 fprintf (file, "%%%%BoundingBox: %g %g %g %g\n", viewport[0], viewport[1], viewport[2], viewport[3]); >> 464 fputs ("%%EndComments\n", file); >> 465 fputs ("\n", file); >> 466 fputs ("gsave\n", file); >> 467 fputs ("\n", file); >> 468 >> 469 fputs ("% the gouraudtriangle PostScript fragment below is free\n", file); >> 470 fputs ("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file); >> 471 fprintf (file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD); >> 472 for (i=0; gouraudtriangleEPS[i]; i++) { >> 473 fprintf (file, "%s\n", gouraudtriangleEPS[i]); >> 474 } >> 475 >> 476 fprintf(file, "\n%g setlinewidth\n", lineWidth); >> 477 >> 478 fprintf (file, "%g %g %g setrgbcolor\n", clearColor[0], clearColor[1], clearColor[2]); >> 479 fprintf (file, "%g %g %g %g rectfill\n\n", viewport[0], viewport[1], viewport[2], viewport[3]); >> 480 >> 481 spewSortedFeedback (file, size, buffer); >> 482 >> 483 fputs ("grestore\n\n", file); >> 484 fputs ("showpage\n", file); >> 485 >> 486 fclose(file); >> 487 } >> 488 >> 489 void G4OpenGLXViewer::printBuffer (GLint size, GLfloat* buffer) { >> 490 >> 491 GLint count; >> 492 G4int token, nvertices; >> 493 >> 494 count=size; >> 495 while(count) { >> 496 token=G4int (buffer[size-count]); >> 497 count--; >> 498 switch (token) { >> 499 >> 500 case GL_PASS_THROUGH_TOKEN: >> 501 printf ("GL_PASS_THROUGH_TOKEN\n"); >> 502 printf (" %4.2f\n", buffer[size-count]); >> 503 count--; >> 504 break; >> 505 >> 506 case GL_POINT_TOKEN: >> 507 printf ("GL_POINT_TOKEN\n"); >> 508 print3DcolorVertex (size, &count, buffer); >> 509 break; >> 510 >> 511 case GL_LINE_TOKEN: >> 512 printf ("GL_LINE_TOKEN\n"); >> 513 print3DcolorVertex (size, &count, buffer); >> 514 print3DcolorVertex (size, &count, buffer); >> 515 break; >> 516 >> 517 case GL_LINE_RESET_TOKEN: >> 518 printf ("GL_LINE_RESET_TOKEN\n"); >> 519 print3DcolorVertex (size, &count, buffer); >> 520 print3DcolorVertex (size, &count, buffer); >> 521 break; >> 522 >> 523 case GL_POLYGON_TOKEN: >> 524 printf ("GL_POLYGON_TOKEN\n"); >> 525 nvertices=G4int (buffer[size-count]); >> 526 count--; >> 527 for (; nvertices>0; nvertices--) { >> 528 print3DcolorVertex (size, &count, buffer); >> 529 } >> 530 } >> 531 } >> 532 } >> 533 >> 534 G4float* G4OpenGLXViewer::spewPrimitiveEPS (FILE* file, GLfloat* loc) { >> 535 >> 536 G4int token; >> 537 G4int nvertices, i; >> 538 GLfloat red, green, blue, intensity; >> 539 G4int smooth; >> 540 GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax; >> 541 G4int steps; >> 542 Feedback3Dcolor *vertex; >> 543 GLfloat xstep(0.), ystep(0.), rstep(0.), gstep(0.), bstep(0.); >> 544 GLfloat xnext(0.), ynext(0.), rnext(0.), gnext(0.), bnext(0.), distance(0.); >> 545 >> 546 token=G4int (*loc); >> 547 loc++; >> 548 switch (token) { >> 549 case GL_LINE_RESET_TOKEN: >> 550 case GL_LINE_TOKEN: >> 551 vertex=(Feedback3Dcolor*)loc; >> 552 dr=vertex[1].red - vertex[0].red; >> 553 dg=vertex[1].green - vertex[0].green; >> 554 db=vertex[1].blue - vertex[0].blue; >> 555 >> 556 if (!print_colour) { >> 557 dr+=(dg+db); >> 558 dr/=3.0; >> 559 dg=dr; >> 560 db=dr; >> 561 } >> 562 >> 563 if (dr!=0 || dg!=0 || db!=0) { >> 564 dx=vertex[1].x - vertex[0].x; >> 565 dy=vertex[1].y - vertex[0].y; >> 566 distance=sqrt(dx*dx + dy*dy); >> 567 >> 568 absR=fabs(dr); >> 569 absG=fabs(dg); >> 570 absB=fabs(db); >> 571 >> 572 #define Max(a, b) (((a)>(b))?(a):(b)) >> 573 >> 574 #define EPS_SMOOTH_LINE_FACTOR 0.06 >> 575 >> 576 colormax=Max(absR, Max(absG, absB)); >> 577 steps=Max(1, G4int (colormax*distance*EPS_SMOOTH_LINE_FACTOR)); >> 578 >> 579 xstep=dx/steps; >> 580 ystep=dy/steps; >> 581 >> 582 rstep=dr/steps; >> 583 gstep=dg/steps; >> 584 bstep=db/steps; >> 585 >> 586 xnext=vertex[0].x; >> 587 ynext=vertex[0].y; >> 588 rnext=vertex[0].red; >> 589 gnext=vertex[0].green; >> 590 bnext=vertex[0].blue; >> 591 >> 592 if (!print_colour) { >> 593 rnext+=(gnext+bnext); >> 594 rnext/=3.0; >> 595 gnext=rnext; >> 596 bnext=rnext; >> 597 } >> 598 >> 599 xnext -= xstep/2.0; >> 600 ynext -= ystep/2.0; >> 601 rnext -= rstep/2.0; >> 602 gnext -= gstep/2.0; >> 603 bnext -= bstep/2.0; >> 604 } else { >> 605 steps=0; >> 606 } >> 607 if (print_colour) { >> 608 fprintf (file, "%g %g %g setrgbcolor\n", >> 609 vertex[0].red, vertex[0].green, vertex[0].blue); >> 610 } else { >> 611 intensity = (vertex[0].red + vertex[0].green + vertex[0].blue) / 3.0; >> 612 fprintf (file, "%g %g %g setrgbcolor\n", >> 613 intensity, intensity, intensity); >> 614 } >> 615 fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y); >> 616 >> 617 for (i=0; i<steps; i++) { >> 618 >> 619 xnext += xstep; >> 620 ynext += ystep; >> 621 rnext += rstep; >> 622 gnext += gstep; >> 623 bnext += bstep; >> 624 >> 625 fprintf (file, "%g %g lineto stroke\n", xnext, ynext); >> 626 fprintf (file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext); >> 627 fprintf (file, "%g %g moveto\n", xnext, ynext); >> 628 } >> 629 fprintf (file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y); >> 630 >> 631 loc += 14; >> 632 break; >> 633 >> 634 case GL_POLYGON_TOKEN: >> 635 nvertices = G4int (*loc); >> 636 loc++; >> 637 vertex=(Feedback3Dcolor*)loc; >> 638 if (nvertices>0) { >> 639 red=vertex[0].red; >> 640 green=vertex[0].green; >> 641 blue=vertex[0].blue; >> 642 smooth=0; >> 643 >> 644 if (!print_colour) { >> 645 red+=(green+blue); >> 646 red/=3.0; >> 647 green=red; >> 648 blue=red; >> 649 } >> 650 >> 651 if (print_colour) { >> 652 for (i=1; i<nvertices; i++) { >> 653 if (red!=vertex[i].red || green!=vertex[i].green || blue!=vertex[i].blue) { >> 654 smooth=1; >> 655 break; >> 656 } >> 657 } >> 658 } else { >> 659 for (i=1; i<nvertices; i++) { >> 660 intensity = vertex[i].red + vertex[i].green + vertex[i].blue; >> 661 intensity/=3.0; >> 662 if (red!=intensity) { >> 663 smooth=1; >> 664 break; >> 665 } >> 666 } >> 667 } >> 668 >> 669 if (smooth) { >> 670 G4int triOffset; >> 671 for (i=0; i<nvertices-2; i++) { >> 672 triOffset = i*7; >> 673 fprintf (file, "[%g %g %g %g %g %g]", >> 674 vertex[0].x, vertex[i+1].x, vertex[i+2].x, >> 675 vertex[0].y, vertex[i+1].y, vertex[i+2].y); >> 676 if (print_colour) { >> 677 fprintf (file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n", >> 678 vertex[0].red, vertex[0].green, vertex[0].blue, >> 679 vertex[i+1].red, vertex[i+1].green, vertex[i+1].blue, >> 680 vertex[i+2].red, vertex[i+2].green, vertex[i+2].blue); >> 681 } else { >> 682 >> 683 intensity = vertex[0].red + vertex[0].green + vertex[0].blue; >> 684 intensity/=3.0; >> 685 fprintf (file, " [%g %g %g]", intensity, intensity, intensity); >> 686 >> 687 intensity = vertex[1].red + vertex[1].green + vertex[1].blue; >> 688 intensity/=3.0; >> 689 fprintf (file, " [%g %g %g]", intensity, intensity, intensity); >> 690 >> 691 intensity = vertex[2].red + vertex[2].green + vertex[2].blue; >> 692 intensity/=3.0; >> 693 fprintf (file, " [%g %g %g] gouraudtriangle\n", intensity, intensity, intensity); >> 694 } >> 695 } >> 696 } else { >> 697 fprintf (file, "newpath\n"); >> 698 fprintf (file, "%g %g %g setrgbcolor\n", red, green, blue); >> 699 fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y); >> 700 for (i=1; i<nvertices; i++) { >> 701 fprintf (file, "%g %g lineto\n", vertex[i].x, vertex[i].y); >> 702 } >> 703 fprintf (file, "closepath fill\n\n"); >> 704 } >> 705 } >> 706 loc += nvertices*7; >> 707 break; >> 708 >> 709 case GL_POINT_TOKEN: >> 710 vertex=(Feedback3Dcolor*)loc; >> 711 if (print_colour) { >> 712 fprintf (file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue); >> 713 } else { >> 714 intensity = vertex[0].red + vertex[0].green + vertex[0].blue; >> 715 intensity/=3.0; >> 716 fprintf (file, "%g %g %g setrgbcolor\n", intensity, intensity, intensity); >> 717 } >> 718 fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, pointSize / 2.0); >> 719 loc += 7; /* Each vertex element in the feedback >> 720 buffer is 7 GLfloats. */ >> 721 break; >> 722 default: >> 723 /* XXX Left as an excersie to the reader. */ >> 724 printf("Incomplete implementation. Unexpected token (%d).\n", token); >> 725 exit(1); >> 726 } >> 727 return loc; >> 728 } >> 729 >> 730 typedef struct _DepthIndex { >> 731 GLfloat *ptr; >> 732 GLfloat depth; >> 733 } DepthIndex; >> 734 >> 735 extern "C" >> 736 { >> 737 static int >> 738 compare(const void *a, const void *b) >> 739 { >> 740 const DepthIndex *p1 = (DepthIndex *) a; >> 741 const DepthIndex *p2 = (DepthIndex *) b; >> 742 GLfloat diff = p2->depth - p1->depth; >> 743 >> 744 if (diff > 0.0) { >> 745 return 1; >> 746 } else if (diff < 0.0) { >> 747 return -1; >> 748 } else { >> 749 return 0; >> 750 } >> 751 } >> 752 } >> 753 >> 754 void G4OpenGLXViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer) >> 755 { >> 756 int token; >> 757 GLfloat *loc, *end; >> 758 Feedback3Dcolor *vertex; >> 759 GLfloat depthSum; >> 760 int nprimitives, item; >> 761 DepthIndex *prims; >> 762 int nvertices, i; >> 763 >> 764 end = buffer + size; >> 765 >> 766 /* Count how many primitives there are. */ >> 767 nprimitives = 0; >> 768 loc = buffer; >> 769 while (loc < end) { >> 770 token = int (*loc); >> 771 loc++; >> 772 switch (token) { >> 773 case GL_LINE_TOKEN: >> 774 case GL_LINE_RESET_TOKEN: >> 775 loc += 14; >> 776 nprimitives++; >> 777 break; >> 778 case GL_POLYGON_TOKEN: >> 779 nvertices = int (*loc); >> 780 loc++; >> 781 loc += (7 * nvertices); >> 782 nprimitives++; >> 783 break; >> 784 case GL_POINT_TOKEN: >> 785 loc += 7; >> 786 nprimitives++; >> 787 break; >> 788 default: >> 789 /* XXX Left as an excersie to the reader. */ >> 790 printf("Incomplete implementation. Unexpected token (%d).\n", >> 791 token); >> 792 exit(1); >> 793 } >> 794 } >> 795 >> 796 /* Allocate an array of pointers that will point back at >> 797 primitives in the feedback buffer. There will be one >> 798 entry per primitive. This array is also where we keep the >> 799 primitive's average depth. There is one entry per >> 800 primitive in the feedback buffer. */ >> 801 prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives); >> 802 >> 803 item = 0; >> 804 loc = buffer; >> 805 while (loc < end) { >> 806 prims[item].ptr = loc; /* Save this primitive's location. */ >> 807 token = int (*loc); >> 808 loc++; >> 809 switch (token) { >> 810 case GL_LINE_TOKEN: >> 811 case GL_LINE_RESET_TOKEN: >> 812 vertex = (Feedback3Dcolor *) loc; >> 813 depthSum = vertex[0].z + vertex[1].z; >> 814 prims[item].depth = depthSum / 2.0; >> 815 loc += 14; >> 816 break; >> 817 case GL_POLYGON_TOKEN: >> 818 nvertices = int (*loc); >> 819 loc++; >> 820 vertex = (Feedback3Dcolor *) loc; >> 821 depthSum = vertex[0].z; >> 822 for (i = 1; i < nvertices; i++) { >> 823 depthSum += vertex[i].z; >> 824 } >> 825 prims[item].depth = depthSum / nvertices; >> 826 loc += (7 * nvertices); >> 827 break; >> 828 case GL_POINT_TOKEN: >> 829 vertex = (Feedback3Dcolor *) loc; >> 830 prims[item].depth = vertex[0].z; >> 831 loc += 7; >> 832 break; >> 833 default: >> 834 /* XXX Left as an excersie to the reader. */ >> 835 assert(1); >> 836 } >> 837 item++; >> 838 } >> 839 assert(item == nprimitives); >> 840 >> 841 /* Sort the primitives back to front. */ >> 842 qsort(prims, nprimitives, sizeof(DepthIndex), compare); >> 843 >> 844 /* Understand that sorting by a primitives average depth >> 845 doesn't allow us to disambiguate some cases like self >> 846 intersecting polygons. Handling these cases would require >> 847 breaking up the primitives. That's too involved for this >> 848 example. Sorting by depth is good enough for lots of >> 849 applications. */ >> 850 >> 851 /* Emit the Encapsulated PostScript for the primitives in >> 852 back to front order. */ >> 853 for (item = 0; item < nprimitives; item++) { >> 854 (void) spewPrimitiveEPS(file, prims[item].ptr); >> 855 } >> 856 >> 857 free(prims); >> 858 } >> 859 >> 860 GLXContext G4OpenGLXViewer::create_GL_print_context(XVisualInfo*& pvi, G4bool& db) { >> 861 >> 862 pvi = glXChooseVisual (dpy, >> 863 XDefaultScreen (dpy), >> 864 snglBuf_RGBA); >> 865 >> 866 if (pvi) { >> 867 db=false; >> 868 } else { >> 869 pvi = glXChooseVisual (dpy, >> 870 XDefaultScreen (dpy), >> 871 dblBuf_RGBA); >> 872 if (!pvi) { >> 873 db=true; >> 874 } >> 875 } >> 876 >> 877 return glXCreateContext (dpy, >> 878 pvi, >> 879 NULL, >> 880 False); >> 881 } >> 882 >> 883 int G4OpenGLXViewer::generateEPS (char* filnam, >> 884 int inColour, >> 885 unsigned int width, >> 886 unsigned int height) { >> 887 >> 888 FILE* fp; >> 889 GLubyte* pixels; >> 890 GLubyte* curpix; >> 891 int components, pos, i; >> 892 >> 893 pixels = grabPixels (inColour, width, height); >> 894 >> 895 if (pixels == NULL) >> 896 return 1; >> 897 if (inColour) { >> 898 components = 3; >> 899 } else { >> 900 components = 1; >> 901 } >> 902 >> 903 fp = fopen (filnam, "w"); >> 904 if (fp == NULL) { >> 905 return 2; >> 906 } >> 907 >> 908 fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"); >> 909 fprintf (fp, "%%%%Title: %s\n", filnam); >> 910 fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n"); >> 911 fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height); >> 912 fprintf (fp, "%%%%EndComments\n"); >> 913 fprintf (fp, "gsave\n"); >> 914 fprintf (fp, "/bwproc {\n"); >> 915 fprintf (fp, " rgbproc\n"); >> 916 fprintf (fp, " dup length 3 idiv string 0 3 0 \n"); >> 917 fprintf (fp, " 5 -1 roll {\n"); >> 918 fprintf (fp, " add 2 1 roll 1 sub dup 0 eq\n"); >> 919 fprintf (fp, " { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n"); >> 920 fprintf (fp, " 3 1 roll 5 -1 roll } put 1 add 3 0 \n"); >> 921 fprintf (fp, " { 2 1 roll } ifelse\n"); >> 922 fprintf (fp, " }forall\n"); >> 923 fprintf (fp, " pop pop pop\n"); >> 924 fprintf (fp, "} def\n"); >> 925 fprintf (fp, "systemdict /colorimage known not {\n"); >> 926 fprintf (fp, " /colorimage {\n"); >> 927 fprintf (fp, " pop\n"); >> 928 fprintf (fp, " pop\n"); >> 929 fprintf (fp, " /rgbproc exch def\n"); >> 930 fprintf (fp, " { bwproc } image\n"); >> 931 fprintf (fp, " } def\n"); >> 932 fprintf (fp, "} if\n"); >> 933 fprintf (fp, "/picstr %d string def\n", width * components); >> 934 fprintf (fp, "%d %d scale\n", width, height); >> 935 fprintf (fp, "%d %d %d\n", width, height, 8); >> 936 fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height); >> 937 fprintf (fp, "{currentfile picstr readhexstring pop}\n"); >> 938 fprintf (fp, "false %d\n", components); >> 939 fprintf (fp, "colorimage\n"); >> 940 >> 941 curpix = (GLubyte*) pixels; >> 942 pos = 0; >> 943 for (i = width*height*components; i>0; i--) { >> 944 fprintf (fp, "%02hx ", *(curpix++)); >> 945 if (++pos >= 32) { >> 946 fprintf (fp, "\n"); >> 947 pos = 0; >> 948 } >> 949 } >> 950 if (pos) >> 951 fprintf (fp, "\n"); >> 952 >> 953 fprintf (fp, "grestore\n"); >> 954 fprintf (fp, "showpage\n"); >> 955 delete pixels; >> 956 fclose (fp); >> 957 return 0; >> 958 } >> 959 >> 960 GLubyte* G4OpenGLXViewer::grabPixels (int inColor, unsigned int width, unsigned int height) { >> 961 >> 962 GLubyte* buffer; >> 963 GLint swapbytes, lsbfirst, rowlength; >> 964 GLint skiprows, skippixels, alignment; >> 965 GLenum format; >> 966 int size; >> 967 >> 968 if (inColor) { >> 969 format = GL_RGB; >> 970 size = width*height*3; >> 971 } else { >> 972 format = GL_LUMINANCE; >> 973 size = width*height*1; >> 974 } >> 975 >> 976 buffer = new GLubyte[size]; >> 977 if (buffer == NULL) >> 978 return NULL; >> 979 >> 980 glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes); >> 981 glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst); >> 982 glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength); >> 983 >> 984 glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows); >> 985 glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels); >> 986 glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); >> 987 >> 988 glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); >> 989 glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); >> 990 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); >> 991 >> 992 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); >> 993 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); >> 994 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); >> 995 >> 996 glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer); >> 997 >> 998 glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes); >> 999 glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst); >> 1000 glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength); >> 1001 >> 1002 glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows); >> 1003 glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels); >> 1004 glPixelStorei (GL_UNPACK_ALIGNMENT, alignment); >> 1005 >> 1006 return buffer; >> 1007 } >> 1008 >> 1009 #endif 543 1010