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