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

Last change on this file since 748 was 727, checked in by garnier, 16 years ago

correction du ticket #65. Pb sur autorotation et reouverture partielle du ticket #120

  • Property svn:mime-type set to text/cpp
File size: 26.9 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
726GLdouble G4OpenGLViewer::getSceneNearWidth()
727{
728  const G4Point3D targetPoint
729    = fSceneHandler.GetScene()->GetStandardTargetPoint()
730    + fVP.GetCurrentTargetPoint ();
731  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
732  if(radius<=0.) radius = 1.;
733  const G4double cameraDistance = fVP.GetCameraDistance (radius);
734  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
735  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
736}
737
738GLdouble G4OpenGLViewer::getSceneFarWidth()
739{
740  const G4Point3D targetPoint
741    = fSceneHandler.GetScene()->GetStandardTargetPoint()
742    + fVP.GetCurrentTargetPoint ();
743  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
744  if(radius<=0.) radius = 1.;
745  const G4double cameraDistance = fVP.GetCameraDistance (radius);
746  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
747  const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
748  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
749}
750
751
752GLdouble G4OpenGLViewer::getSceneDepth()
753{
754  const G4Point3D targetPoint
755    = fSceneHandler.GetScene()->GetStandardTargetPoint()
756    + fVP.GetCurrentTargetPoint ();
757  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
758  if(radius<=0.) radius = 1.;
759  const G4double cameraDistance = fVP.GetCameraDistance (radius);
760  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
761  return fVP.GetFarDistance  (cameraDistance, pnear, radius)- pnear;
762}
763
764
765void G4OpenGLViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer)
766{
767  int token;
768  GLfloat *loc, *end;
769  Feedback3Dcolor *vertex;
770  GLfloat depthSum;
771  int nprimitives, item;
772  DepthIndex *prims;
773  int nvertices, i;
774
775  end = buffer + size;
776
777  /* Count how many primitives there are. */
778  nprimitives = 0;
779  loc = buffer;
780  while (loc < end) {
781    token = int (*loc);
782    loc++;
783    switch (token) {
784    case GL_LINE_TOKEN:
785    case GL_LINE_RESET_TOKEN:
786      loc += 14;
787      nprimitives++;
788      break;
789    case GL_POLYGON_TOKEN:
790      nvertices = int (*loc);
791      loc++;
792      loc += (7 * nvertices);
793      nprimitives++;
794      break;
795    case GL_POINT_TOKEN:
796      loc += 7;
797      nprimitives++;
798      break;
799    default:
800      /* XXX Left as an excersie to the reader. */
801      static G4bool spewSortedFeedbackWarned = false;
802      if (!spewSortedFeedbackWarned) {
803        std::ostringstream oss;
804        oss <<
805          "Incomplete implementation.  Unexpected token (" << token << ")."
806          "\n  (Seems to be caused by text.)";
807        G4Exception("G4OpenGLViewer::spewSortedFeedback",
808                    "Unexpected token",
809                    JustWarning,
810                    oss.str().c_str());
811        spewSortedFeedbackWarned = true;
812      }
813      nprimitives++;
814    }
815  }
816
817  /* Allocate an array of pointers that will point back at
818     primitives in the feedback buffer.  There will be one
819     entry per primitive.  This array is also where we keep the
820     primitive's average depth.  There is one entry per
821     primitive  in the feedback buffer. */
822  prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives);
823
824  item = 0;
825  loc = buffer;
826  while (loc < end) {
827    prims[item].ptr = loc;  /* Save this primitive's location. */
828    token = int (*loc);
829    loc++;
830    switch (token) {
831    case GL_LINE_TOKEN:
832    case GL_LINE_RESET_TOKEN:
833      vertex = (Feedback3Dcolor *) loc;
834      depthSum = vertex[0].z + vertex[1].z;
835      prims[item].depth = depthSum / 2.0;
836      loc += 14;
837      break;
838    case GL_POLYGON_TOKEN:
839      nvertices = int (*loc);
840      loc++;
841      vertex = (Feedback3Dcolor *) loc;
842      depthSum = vertex[0].z;
843      for (i = 1; i < nvertices; i++) {
844        depthSum += vertex[i].z;
845      }
846      prims[item].depth = depthSum / nvertices;
847      loc += (7 * nvertices);
848      break;
849    case GL_POINT_TOKEN:
850      vertex = (Feedback3Dcolor *) loc;
851      prims[item].depth = vertex[0].z;
852      loc += 7;
853      break;
854    default:
855      /* XXX Left as an excersie to the reader. */
856      assert(1);
857    }
858    item++;
859  }
860  assert(item == nprimitives);
861
862  /* Sort the primitives back to front. */
863  qsort(prims, nprimitives, sizeof(DepthIndex), G4OpenGLViewercompare);
864
865  /* Understand that sorting by a primitives average depth
866     doesn't allow us to disambiguate some cases like self
867     intersecting polygons.  Handling these cases would require
868     breaking up the primitives.  That's too involved for this
869     example.  Sorting by depth is good enough for lots of
870     applications. */
871
872  /* Emit the Encapsulated PostScript for the primitives in
873     back to front order. */
874  for (item = 0; item < nprimitives; item++) {
875    (void) spewPrimitiveEPS(file, prims[item].ptr);
876  }
877
878  free(prims);
879}
880
881#endif
Note: See TracBrowser for help on using the repository browser.