source: trunk/geant4/visualization/OpenGL/src/G4OpenGLViewer.cc@ 701

Last change on this file since 701 was 688, checked in by garnier, 18 years ago

mise a jour par rapport au commit sur cvs de geant4

  • Property svn:mime-type set to text/cpp
File size: 25.4 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: G4OpenGLViewer.cc,v 1.34 2007/05/24 18:27:13 allison Exp $
28// GEANT4 tag $Name: HEAD $
29//
30//
31// Andrew Walkden 27th March 1996
32// OpenGL view - opens window, hard copy, etc.
33
34#ifdef G4VIS_BUILD_OPENGL_DRIVER
35
36#include "G4ios.hh"
37#include "G4OpenGLViewer.hh"
38#include "G4OpenGLSceneHandler.hh"
39#include "G4OpenGLTransform3D.hh"
40
41#include "G4Scene.hh"
42#include "G4VisExtent.hh"
43#include "G4LogicalVolume.hh"
44#include "G4VSolid.hh"
45#include "G4Point3D.hh"
46#include "G4Normal3D.hh"
47#include "G4Plane3D.hh"
48#include "G4AttHolder.hh"
49#include "G4AttCheck.hh"
50#include <sstream>
51
52static const char* gouraudtriangleEPS[] =
53{
54 "/bd{bind def}bind def /triangle { aload pop setrgbcolor aload pop 5 3",
55 "roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd",
56 "/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2",
57 "index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse",
58 "} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get",
59 "computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get",
60 "computediff1 {true} { 3 copy 2 get 3 1 roll 2 get 3 1 roll 2 get",
61 "computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll",
62 "aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2",
63 "div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4",
64 "-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add",
65 "2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1",
66 "roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3",
67 "1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll",
68 "2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll",
69 "aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array",
70 "astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17",
71 "index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index",
72 "gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6",
73 "array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index",
74 "15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14",
75 "index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3",
76 "roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7",
77 "index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add",
78 "add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd",
79 NULL
80};
81
82G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
83G4VViewer (scene, -1),
84pointSize (0),
85print_colour (true),
86vectored_ps (true),
87fOpenGLSceneHandler(scene),
88background (G4Colour(0.,0.,0.)),
89transparency_enabled (true),
90antialiasing_enabled (false),
91haloing_enabled (false),
92fStartTime(-G4OPENGL_DBL_MAX),
93fEndTime(G4OPENGL_DBL_MAX),
94fFadeFactor(0.),
95fDisplayHeadTime(false),
96fDisplayHeadTimeX(-0.9),
97fDisplayHeadTimeY(-0.9),
98fDisplayHeadTimeSize(24.),
99fDisplayHeadTimeRed(0.),
100fDisplayHeadTimeGreen(1.),
101fDisplayHeadTimeBlue(1.),
102fDisplayLightFront(false),
103fDisplayLightFrontX(0.),
104fDisplayLightFrontY(0.),
105fDisplayLightFrontZ(0.),
106fDisplayLightFrontT(0.),
107fDisplayLightFrontRed(0.),
108fDisplayLightFrontGreen(1.),
109fDisplayLightFrontBlue(0.)
110{
111 // Make changes to view parameters for OpenGL...
112 fVP.SetAutoRefresh(true);
113 fDefaultVP.SetAutoRefresh(true);
114
115 // glClearColor (0.0, 0.0, 0.0, 0.0);
116 // glClearDepth (1.0);
117 // glDisable (GL_BLEND);
118 // glDisable (GL_LINE_SMOOTH);
119 // glDisable (GL_POLYGON_SMOOTH);
120
121 strcpy (print_string, "G4OpenGL.eps");
122}
123
124G4OpenGLViewer::~G4OpenGLViewer () {}
125
126void G4OpenGLViewer::InitializeGLView ()
127{
128 glClearColor (0.0, 0.0, 0.0, 0.0);
129 glClearDepth (1.0);
130 glDisable (GL_BLEND);
131 glDisable (GL_LINE_SMOOTH);
132 glDisable (GL_POLYGON_SMOOTH);
133}
134
135void G4OpenGLViewer::ClearView () {
136 glClearColor (background.GetRed(),
137 background.GetGreen(),
138 background.GetBlue(),
139 1.);
140 glClearDepth (1.0);
141 //Below line does not compile with Mesa includes.
142 //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
143 glClear (GL_COLOR_BUFFER_BIT);
144 glClear (GL_DEPTH_BUFFER_BIT);
145 glClear (GL_STENCIL_BUFFER_BIT);
146 glFlush ();
147}
148
149void G4OpenGLViewer::SetView () {
150
151 // Calculates view representation based on extent of object being
152 // viewed and (initial) viewpoint. (Note: it can change later due
153 // to user interaction via visualization system's GUI.)
154
155 // Lighting.
156 GLfloat lightPosition [4];
157 lightPosition [0] = fVP.GetActualLightpointDirection().x();
158 lightPosition [1] = fVP.GetActualLightpointDirection().y();
159 lightPosition [2] = fVP.GetActualLightpointDirection().z();
160 lightPosition [3] = 0.;
161 // Light position is "true" light direction, so must come after gluLookAt.
162 GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
163 GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
164 glEnable (GL_LIGHT0);
165 glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
166 glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
167
168 // Get radius of scene, etc.
169 // Note that this procedure properly takes into account zoom, dolly and pan.
170 const G4Point3D targetPoint
171 = fSceneHandler.GetScene()->GetStandardTargetPoint()
172 + fVP.GetCurrentTargetPoint ();
173 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
174 if(radius<=0.) radius = 1.;
175 const G4double cameraDistance = fVP.GetCameraDistance (radius);
176 const G4Point3D cameraPosition =
177 targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
178 const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
179 const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
180 const GLdouble right = fVP.GetFrontHalfHeight (pnear, radius);
181 const GLdouble left = -right;
182 const GLdouble bottom = left;
183 const GLdouble top = right;
184
185 glMatrixMode (GL_PROJECTION); // set up Frustum.
186 glLoadIdentity();
187
188 const G4Vector3D scale = fVP.GetScaleFactor();
189 glScaled(scale.x(),scale.y(),scale.z());
190
191 if (fVP.GetFieldHalfAngle() == 0.) {
192 glOrtho (left, right, bottom, top, pnear, pfar);
193 }
194 else {
195 glFrustum (left, right, bottom, top, pnear, pfar);
196 }
197
198 glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
199 glLoadIdentity();
200
201 const G4Normal3D& upVector = fVP.GetUpVector ();
202 G4Point3D gltarget;
203 if (cameraDistance > 1.e-6 * radius) {
204 gltarget = targetPoint;
205 }
206 else {
207 gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
208 }
209
210 const G4Point3D& pCamera = cameraPosition; // An alias for brevity.
211 gluLookAt (pCamera.x(), pCamera.y(), pCamera.z(), // Viewpoint.
212 gltarget.x(), gltarget.y(), gltarget.z(), // Target point.
213 upVector.x(), upVector.y(), upVector.z()); // Up vector.
214
215 // Light position is "true" light direction, so must come after gluLookAt.
216 glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
217
218 // OpenGL no longer seems to reconstruct clipped edges, so, when the
219 // BooleanProcessor is up to it, abandon this and use generic
220 // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron. Also,
221 // force kernel visit on change of clipping plane in
222 // G4OpenGLStoredViewer::CompareForKernelVisit.
223 if (fVP.IsSection () ) { // pair of back to back clip planes.
224 const G4Plane3D& s = fVP.GetSectionPlane ();
225 double sArray[4];
226 sArray[0] = s.a();
227 sArray[1] = s.b();
228 sArray[2] = s.c();
229 sArray[3] = s.d() + radius * 1.e-05;
230 glClipPlane (GL_CLIP_PLANE0, sArray);
231 glEnable (GL_CLIP_PLANE0);
232 sArray[0] = -s.a();
233 sArray[1] = -s.b();
234 sArray[2] = -s.c();
235 sArray[3] = -s.d() + radius * 1.e-05;
236 glClipPlane (GL_CLIP_PLANE1, sArray);
237 glEnable (GL_CLIP_PLANE1);
238 } else {
239 glDisable (GL_CLIP_PLANE0);
240 glDisable (GL_CLIP_PLANE1);
241 }
242
243 const G4Planes& cutaways = fVP.GetCutawayPlanes();
244 size_t nPlanes = cutaways.size();
245 if (fVP.IsCutaway() &&
246 fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
247 nPlanes > 0) {
248 double a[4];
249 a[0] = cutaways[0].a();
250 a[1] = cutaways[0].b();
251 a[2] = cutaways[0].c();
252 a[3] = cutaways[0].d();
253 glClipPlane (GL_CLIP_PLANE2, a);
254 glEnable (GL_CLIP_PLANE2);
255 if (nPlanes > 1) {
256 a[0] = cutaways[1].a();
257 a[1] = cutaways[1].b();
258 a[2] = cutaways[1].c();
259 a[3] = cutaways[1].d();
260 glClipPlane (GL_CLIP_PLANE3, a);
261 glEnable (GL_CLIP_PLANE3);
262 }
263 if (nPlanes > 2) {
264 a[0] = cutaways[2].a();
265 a[1] = cutaways[2].b();
266 a[2] = cutaways[2].c();
267 a[3] = cutaways[2].d();
268 glClipPlane (GL_CLIP_PLANE4, a);
269 glEnable (GL_CLIP_PLANE4);
270 }
271 } else {
272 glDisable (GL_CLIP_PLANE2);
273 glDisable (GL_CLIP_PLANE3);
274 glDisable (GL_CLIP_PLANE4);
275 }
276
277 // Background.
278 background = fVP.GetBackgroundColour ();
279
280}
281
282void G4OpenGLViewer::HaloingFirstPass () {
283
284 //To perform haloing, first Draw all information to the depth buffer
285 //alone, using a chunky line width, and then Draw all info again, to
286 //the colour buffer, setting a thinner line width an the depth testing
287 //function to less than or equal, so if two lines cross, the one
288 //passing behind the other will not pass the depth test, and so not
289 //get rendered either side of the infront line for a short distance.
290
291 //First, disable writing to the colo(u)r buffer...
292 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
293
294 //Now enable writing to the depth buffer...
295 glDepthMask (GL_TRUE);
296 glDepthFunc (GL_LESS);
297 glClearDepth (1.0);
298
299 //Finally, set the line width to something wide...
300 glLineWidth (3.0);
301
302}
303
304void G4OpenGLViewer::HaloingSecondPass () {
305
306 //And finally, turn the colour buffer back on with a sesible line width...
307 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
308 glDepthFunc (GL_LEQUAL);
309 glLineWidth (1.0);
310
311}
312
313void G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
314{
315 //G4cout << "X: " << x << ", Y: " << y << G4endl;
316 const G4int BUFSIZE = 512;
317 GLuint selectBuffer[BUFSIZE];
318 glSelectBuffer(BUFSIZE, selectBuffer);
319 glRenderMode(GL_SELECT);
320 glInitNames();
321 glPushName(0);
322 glMatrixMode(GL_PROJECTION);
323 G4double currentProjectionMatrix[16];
324 glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
325 glPushMatrix();
326 glLoadIdentity();
327 GLint viewport[4];
328 glGetIntegerv(GL_VIEWPORT, viewport);
329 // Define 5x5 pixel pick area
330 gluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
331 glMultMatrixd(currentProjectionMatrix);
332 glMatrixMode(GL_MODELVIEW);
333 DrawView();
334 GLint hits = glRenderMode(GL_RENDER);
335 if (hits < 0)
336 G4cout << "Too many hits. Zoom in to reduce overlaps." << G4cout;
337 else if (hits > 0) {
338 //G4cout << hits << " hit(s)" << G4endl;
339 GLuint* p = selectBuffer;
340 for (GLint i = 0; i < hits; ++i) {
341 GLuint nnames = *p++;
342 *p++; //OR GLuint zmin = *p++;
343 *p++; //OR GLuint zmax = *p++;
344 //G4cout << "Hit " << i << ": " << nnames << " names"
345 // << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
346 for (GLuint j = 0; j < nnames; ++j) {
347 GLuint name = *p++;
348 //G4cout << "Name " << j << ": PickName: " << name << G4endl;
349 std::map<GLuint, G4AttHolder*>::iterator iter =
350 fOpenGLSceneHandler.fPickMap.find(name);
351 if (iter != fOpenGLSceneHandler.fPickMap.end()) {
352 G4AttHolder* attHolder = iter->second;
353 if(attHolder && attHolder->GetAttDefs().size()) {
354 for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
355 G4cout << G4AttCheck(attHolder->GetAttValues()[i],
356 attHolder->GetAttDefs()[i]);
357 }
358 }
359 }
360 }
361 G4cout << G4endl;
362 }
363 }
364 glMatrixMode(GL_PROJECTION);
365 glPopMatrix();
366 glMatrixMode(GL_MODELVIEW);
367}
368
369void G4OpenGLViewer::print() {
370
371 // Print vectored PostScript
372
373 G4int size = 5000000;
374
375 GLfloat* feedback_buffer;
376 GLint returned;
377 FILE* file;
378
379 feedback_buffer = new GLfloat[size];
380 glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
381 glRenderMode (GL_FEEDBACK);
382
383 DrawView();
384 returned = glRenderMode (GL_RENDER);
385
386 if (print_string) {
387 file = fopen (print_string, "w");
388 if (file) {
389 spewWireframeEPS (file, returned, feedback_buffer, "rendereps");
390 } else {
391 printf("Could not open %s\n", print_string);
392 }
393 } else {
394 printBuffer (returned, feedback_buffer);
395 }
396
397 delete[] feedback_buffer;
398}
399
400void G4OpenGLViewer::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer)
401{
402 G4int i;
403
404 printf(" ");
405 for (i = 0; i < 7; i++) {
406 printf("%4.2f ", buffer[size - (*count)]);
407 *count = *count - 1;
408 }
409 printf("\n");
410}
411
412void G4OpenGLViewer::spewWireframeEPS (FILE* file, GLint size, GLfloat* buffer, const char* cr) {
413
414 GLfloat EPS_GOURAUD_THRESHOLD=0.1;
415
416 GLfloat clearColor[4], viewport[4];
417 GLfloat lineWidth;
418 G4int i;
419
420 glGetFloatv (GL_VIEWPORT, viewport);
421 glGetFloatv (GL_COLOR_CLEAR_VALUE, clearColor);
422 glGetFloatv (GL_LINE_WIDTH, &lineWidth);
423 glGetFloatv (GL_POINT_SIZE, &pointSize);
424
425 fputs ("%!PS-Adobe-2.0 EPSF-2.0\n", file);
426 fprintf (file, "%%%%Creator: %s (using OpenGL feedback)\n", cr);
427 fprintf (file, "%%%%BoundingBox: %g %g %g %g\n", viewport[0], viewport[1], viewport[2], viewport[3]);
428 fputs ("%%EndComments\n", file);
429 fputs ("\n", file);
430 fputs ("gsave\n", file);
431 fputs ("\n", file);
432
433 fputs ("% the gouraudtriangle PostScript fragment below is free\n", file);
434 fputs ("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file);
435 fprintf (file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD);
436 for (i=0; gouraudtriangleEPS[i]; i++) {
437 fprintf (file, "%s\n", gouraudtriangleEPS[i]);
438 }
439
440 fprintf(file, "\n%g setlinewidth\n", lineWidth);
441
442 fprintf (file, "%g %g %g setrgbcolor\n", clearColor[0], clearColor[1], clearColor[2]);
443 fprintf (file, "%g %g %g %g rectfill\n\n", viewport[0], viewport[1], viewport[2], viewport[3]);
444
445 spewSortedFeedback (file, size, buffer);
446
447 fputs ("grestore\n\n", file);
448 fputs ("showpage\n", file);
449
450 fclose(file);
451}
452
453void G4OpenGLViewer::printBuffer (GLint size, GLfloat* buffer) {
454
455 GLint count;
456 G4int token, nvertices;
457
458 count=size;
459 while(count) {
460 token=G4int (buffer[size-count]);
461 count--;
462 switch (token) {
463
464 case GL_PASS_THROUGH_TOKEN:
465 printf ("GL_PASS_THROUGH_TOKEN\n");
466 printf (" %4.2f\n", buffer[size-count]);
467 count--;
468 break;
469
470 case GL_POINT_TOKEN:
471 printf ("GL_POINT_TOKEN\n");
472 print3DcolorVertex (size, &count, buffer);
473 break;
474
475 case GL_LINE_TOKEN:
476 printf ("GL_LINE_TOKEN\n");
477 print3DcolorVertex (size, &count, buffer);
478 print3DcolorVertex (size, &count, buffer);
479 break;
480
481 case GL_LINE_RESET_TOKEN:
482 printf ("GL_LINE_RESET_TOKEN\n");
483 print3DcolorVertex (size, &count, buffer);
484 print3DcolorVertex (size, &count, buffer);
485 break;
486
487 case GL_POLYGON_TOKEN:
488 printf ("GL_POLYGON_TOKEN\n");
489 nvertices=G4int (buffer[size-count]);
490 count--;
491 for (; nvertices>0; nvertices--) {
492 print3DcolorVertex (size, &count, buffer);
493 }
494 }
495 }
496}
497
498G4float* G4OpenGLViewer::spewPrimitiveEPS (FILE* file, GLfloat* loc) {
499
500 G4int token;
501 G4int nvertices, i;
502 GLfloat red, green, blue, intensity;
503 G4int smooth;
504 GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax;
505 G4int steps;
506 Feedback3Dcolor *vertex;
507 GLfloat xstep(0.), ystep(0.), rstep(0.), gstep(0.), bstep(0.);
508 GLfloat xnext(0.), ynext(0.), rnext(0.), gnext(0.), bnext(0.), distance(0.);
509
510 token=G4int (*loc);
511 loc++;
512 switch (token) {
513 case GL_LINE_RESET_TOKEN:
514 case GL_LINE_TOKEN:
515 vertex=(Feedback3Dcolor*)loc;
516 dr=vertex[1].red - vertex[0].red;
517 dg=vertex[1].green - vertex[0].green;
518 db=vertex[1].blue - vertex[0].blue;
519
520 if (!print_colour) {
521 dr+=(dg+db);
522 dr/=3.0;
523 dg=dr;
524 db=dr;
525 }
526
527 if (dr!=0 || dg!=0 || db!=0) {
528 dx=vertex[1].x - vertex[0].x;
529 dy=vertex[1].y - vertex[0].y;
530 distance=std::sqrt(dx*dx + dy*dy);
531
532 absR=std::fabs(dr);
533 absG=std::fabs(dg);
534 absB=std::fabs(db);
535
536 #define Max(a, b) (((a)>(b))?(a):(b))
537
538 #define EPS_SMOOTH_LINE_FACTOR 0.06
539
540 colormax=Max(absR, Max(absG, absB));
541 steps=Max(1, G4int (colormax*distance*EPS_SMOOTH_LINE_FACTOR));
542
543 xstep=dx/steps;
544 ystep=dy/steps;
545
546 rstep=dr/steps;
547 gstep=dg/steps;
548 bstep=db/steps;
549
550 xnext=vertex[0].x;
551 ynext=vertex[0].y;
552 rnext=vertex[0].red;
553 gnext=vertex[0].green;
554 bnext=vertex[0].blue;
555
556 if (!print_colour) {
557 rnext+=(gnext+bnext);
558 rnext/=3.0;
559 gnext=rnext;
560 bnext=rnext;
561 }
562
563 xnext -= xstep/2.0;
564 ynext -= ystep/2.0;
565 rnext -= rstep/2.0;
566 gnext -= gstep/2.0;
567 bnext -= bstep/2.0;
568 } else {
569 steps=0;
570 }
571 if (print_colour) {
572 fprintf (file, "%g %g %g setrgbcolor\n",
573 vertex[0].red, vertex[0].green, vertex[0].blue);
574 } else {
575 intensity = (vertex[0].red + vertex[0].green + vertex[0].blue) / 3.0;
576 fprintf (file, "%g %g %g setrgbcolor\n",
577 intensity, intensity, intensity);
578 }
579 fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
580
581 for (i=0; i<steps; i++) {
582
583 xnext += xstep;
584 ynext += ystep;
585 rnext += rstep;
586 gnext += gstep;
587 bnext += bstep;
588
589 fprintf (file, "%g %g lineto stroke\n", xnext, ynext);
590 fprintf (file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext);
591 fprintf (file, "%g %g moveto\n", xnext, ynext);
592 }
593 fprintf (file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y);
594
595 loc += 14;
596 break;
597
598 case GL_POLYGON_TOKEN:
599 nvertices = G4int (*loc);
600 loc++;
601 vertex=(Feedback3Dcolor*)loc;
602 if (nvertices>0) {
603 red=vertex[0].red;
604 green=vertex[0].green;
605 blue=vertex[0].blue;
606 smooth=0;
607
608 if (!print_colour) {
609 red+=(green+blue);
610 red/=3.0;
611 green=red;
612 blue=red;
613 }
614
615 if (print_colour) {
616 for (i=1; i<nvertices; i++) {
617 if (red!=vertex[i].red || green!=vertex[i].green || blue!=vertex[i].blue) {
618 smooth=1;
619 break;
620 }
621 }
622 } else {
623 for (i=1; i<nvertices; i++) {
624 intensity = vertex[i].red + vertex[i].green + vertex[i].blue;
625 intensity/=3.0;
626 if (red!=intensity) {
627 smooth=1;
628 break;
629 }
630 }
631 }
632
633 if (smooth) {
634 G4int triOffset;
635 for (i=0; i<nvertices-2; i++) {
636 triOffset = i*7;
637 fprintf (file, "[%g %g %g %g %g %g]",
638 vertex[0].x, vertex[i+1].x, vertex[i+2].x,
639 vertex[0].y, vertex[i+1].y, vertex[i+2].y);
640 if (print_colour) {
641 fprintf (file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n",
642 vertex[0].red, vertex[0].green, vertex[0].blue,
643 vertex[i+1].red, vertex[i+1].green, vertex[i+1].blue,
644 vertex[i+2].red, vertex[i+2].green, vertex[i+2].blue);
645 } else {
646
647 intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
648 intensity/=3.0;
649 fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
650
651 intensity = vertex[1].red + vertex[1].green + vertex[1].blue;
652 intensity/=3.0;
653 fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
654
655 intensity = vertex[2].red + vertex[2].green + vertex[2].blue;
656 intensity/=3.0;
657 fprintf (file, " [%g %g %g] gouraudtriangle\n", intensity, intensity, intensity);
658 }
659 }
660 } else {
661 fprintf (file, "newpath\n");
662 fprintf (file, "%g %g %g setrgbcolor\n", red, green, blue);
663 fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
664 for (i=1; i<nvertices; i++) {
665 fprintf (file, "%g %g lineto\n", vertex[i].x, vertex[i].y);
666 }
667 fprintf (file, "closepath fill\n\n");
668 }
669 }
670 loc += nvertices*7;
671 break;
672
673 case GL_POINT_TOKEN:
674 vertex=(Feedback3Dcolor*)loc;
675 if (print_colour) {
676 fprintf (file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue);
677 } else {
678 intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
679 intensity/=3.0;
680 fprintf (file, "%g %g %g setrgbcolor\n", intensity, intensity, intensity);
681 }
682 fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, pointSize / 2.0);
683 loc += 7; /* Each vertex element in the feedback
684 buffer is 7 GLfloats. */
685 break;
686 default:
687 /* XXX Left as an excersie to the reader. */
688 static G4bool spewPrimitiveEPSWarned = false;
689 if (!spewPrimitiveEPSWarned) {
690 std::ostringstream oss;
691 oss <<
692 "Incomplete implementation. Unexpected token (" << token << ")."
693 "\n (Seems to be caused by text.)";
694 G4Exception("G4OpenGLViewer::spewPrimitiveEPS",
695 "Unexpected token",
696 JustWarning,
697 oss.str().c_str());
698 spewPrimitiveEPSWarned = true;
699 }
700 }
701 return loc;
702}
703
704typedef struct G4OpenGLViewerDepthIndex {
705 GLfloat *ptr;
706 GLfloat depth;
707} DepthIndex;
708
709extern "C" {
710 int G4OpenGLViewercompare(const void *a, const void *b)
711 {
712 const DepthIndex *p1 = (DepthIndex *) a;
713 const DepthIndex *p2 = (DepthIndex *) b;
714 GLfloat diff = p2->depth - p1->depth;
715
716 if (diff > 0.0) {
717 return 1;
718 } else if (diff < 0.0) {
719 return -1;
720 } else {
721 return 0;
722 }
723 }
724}
725
726void G4OpenGLViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer)
727{
728 int token;
729 GLfloat *loc, *end;
730 Feedback3Dcolor *vertex;
731 GLfloat depthSum;
732 int nprimitives, item;
733 DepthIndex *prims;
734 int nvertices, i;
735
736 end = buffer + size;
737
738 /* Count how many primitives there are. */
739 nprimitives = 0;
740 loc = buffer;
741 while (loc < end) {
742 token = int (*loc);
743 loc++;
744 switch (token) {
745 case GL_LINE_TOKEN:
746 case GL_LINE_RESET_TOKEN:
747 loc += 14;
748 nprimitives++;
749 break;
750 case GL_POLYGON_TOKEN:
751 nvertices = int (*loc);
752 loc++;
753 loc += (7 * nvertices);
754 nprimitives++;
755 break;
756 case GL_POINT_TOKEN:
757 loc += 7;
758 nprimitives++;
759 break;
760 default:
761 /* XXX Left as an excersie to the reader. */
762 static G4bool spewSortedFeedbackWarned = false;
763 if (!spewSortedFeedbackWarned) {
764 std::ostringstream oss;
765 oss <<
766 "Incomplete implementation. Unexpected token (" << token << ")."
767 "\n (Seems to be caused by text.)";
768 G4Exception("G4OpenGLViewer::spewSortedFeedback",
769 "Unexpected token",
770 JustWarning,
771 oss.str().c_str());
772 spewSortedFeedbackWarned = true;
773 }
774 nprimitives++;
775 }
776 }
777
778 /* Allocate an array of pointers that will point back at
779 primitives in the feedback buffer. There will be one
780 entry per primitive. This array is also where we keep the
781 primitive's average depth. There is one entry per
782 primitive in the feedback buffer. */
783 prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives);
784
785 item = 0;
786 loc = buffer;
787 while (loc < end) {
788 prims[item].ptr = loc; /* Save this primitive's location. */
789 token = int (*loc);
790 loc++;
791 switch (token) {
792 case GL_LINE_TOKEN:
793 case GL_LINE_RESET_TOKEN:
794 vertex = (Feedback3Dcolor *) loc;
795 depthSum = vertex[0].z + vertex[1].z;
796 prims[item].depth = depthSum / 2.0;
797 loc += 14;
798 break;
799 case GL_POLYGON_TOKEN:
800 nvertices = int (*loc);
801 loc++;
802 vertex = (Feedback3Dcolor *) loc;
803 depthSum = vertex[0].z;
804 for (i = 1; i < nvertices; i++) {
805 depthSum += vertex[i].z;
806 }
807 prims[item].depth = depthSum / nvertices;
808 loc += (7 * nvertices);
809 break;
810 case GL_POINT_TOKEN:
811 vertex = (Feedback3Dcolor *) loc;
812 prims[item].depth = vertex[0].z;
813 loc += 7;
814 break;
815 default:
816 /* XXX Left as an excersie to the reader. */
817 assert(1);
818 }
819 item++;
820 }
821 assert(item == nprimitives);
822
823 /* Sort the primitives back to front. */
824 qsort(prims, nprimitives, sizeof(DepthIndex), G4OpenGLViewercompare);
825
826 /* Understand that sorting by a primitives average depth
827 doesn't allow us to disambiguate some cases like self
828 intersecting polygons. Handling these cases would require
829 breaking up the primitives. That's too involved for this
830 example. Sorting by depth is good enough for lots of
831 applications. */
832
833 /* Emit the Encapsulated PostScript for the primitives in
834 back to front order. */
835 for (item = 0; item < nprimitives; item++) {
836 (void) spewPrimitiveEPS(file, prims[item].ptr);
837 }
838
839 free(prims);
840}
841
842#endif
Note: See TracBrowser for help on using the repository browser.