source: trunk/geant4/visualization/OpenGL/src/G4OpenGLXViewer.cc@ 586

Last change on this file since 586 was 529, checked in by garnier, 18 years ago

r658@mac-90108: laurentgarnier | 2007-06-25 12:02:16 +0200
import de visualisation

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