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

Last change on this file since 632 was 632, checked in by garnier, 17 years ago

commit sur 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:  $
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.