source: tags/before-XString-Modif/OpenGL/src/G4OpenGLViewer.cc @ 1329

Last change on this file since 1329 was 873, checked in by garnier, 16 years ago

Update in code, try to mutualise everything between Stored and immediate Qt Viewers

  • Property svn:mime-type set to text/cpp
File size: 29.3 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.41 2008/10/24 13:49:19 lgarnier 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(-DBL_MAX),
93fEndTime(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  if (!fSceneHandler.GetScene()) {
152    G4cerr << "G4OpenGLStoredQtViewer: Creating a Viewer without a scene is not allowed. \nPlease use /vis/scene/create before /vis/open/.... "
153           << G4endl;
154    return;
155  }
156  // Calculates view representation based on extent of object being
157  // viewed and (initial) viewpoint.  (Note: it can change later due
158  // to user interaction via visualization system's GUI.)
159 
160  // Lighting.
161  GLfloat lightPosition [4];
162  lightPosition [0] = fVP.GetActualLightpointDirection().x();
163  lightPosition [1] = fVP.GetActualLightpointDirection().y();
164  lightPosition [2] = fVP.GetActualLightpointDirection().z();
165  lightPosition [3] = 0.;
166  // Light position is "true" light direction, so must come after gluLookAt.
167  GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
168  GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
169  glEnable (GL_LIGHT0);
170  glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
171  glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
172 
173  // Get radius of scene, etc.
174  // Note that this procedure properly takes into account zoom, dolly and pan.
175  const G4Point3D targetPoint
176    = fSceneHandler.GetScene()->GetStandardTargetPoint()
177    + fVP.GetCurrentTargetPoint ();
178  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
179  if(radius<=0.) radius = 1.;
180  const G4double cameraDistance = fVP.GetCameraDistance (radius);
181  const G4Point3D cameraPosition =
182    targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
183  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
184  const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
185  const GLdouble right  = fVP.GetFrontHalfHeight (pnear, radius);
186  const GLdouble left   = -right;
187  const GLdouble bottom = left;
188  const GLdouble top    = right;
189 
190  glMatrixMode (GL_PROJECTION); // set up Frustum.
191  glLoadIdentity();
192
193  const G4Vector3D scale = fVP.GetScaleFactor();
194  glScaled(scale.x(),scale.y(),scale.z());
195 
196  if (fVP.GetFieldHalfAngle() == 0.) {
197    glOrtho (left, right, bottom, top, pnear, pfar);
198  }
199  else {
200    glFrustum (left, right, bottom, top, pnear, pfar);
201  }
202 
203  glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
204  glLoadIdentity();
205 
206  const G4Normal3D& upVector = fVP.GetUpVector (); 
207  G4Point3D gltarget;
208  if (cameraDistance > 1.e-6 * radius) {
209    gltarget = targetPoint;
210  }
211  else {
212    gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
213  }
214
215  const G4Point3D& pCamera = cameraPosition;  // An alias for brevity.
216  gluLookAt (pCamera.x(),  pCamera.y(),  pCamera.z(),       // Viewpoint.
217             gltarget.x(), gltarget.y(), gltarget.z(),      // Target point.
218             upVector.x(), upVector.y(), upVector.z());     // Up vector.
219 
220  // Light position is "true" light direction, so must come after gluLookAt.
221  glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
222
223  // OpenGL no longer seems to reconstruct clipped edges, so, when the
224  // BooleanProcessor is up to it, abandon this and use generic
225  // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron.  Also,
226  // force kernel visit on change of clipping plane in
227  // G4OpenGLStoredViewer::CompareForKernelVisit.
228  if (fVP.IsSection () ) {  // pair of back to back clip planes.
229    const G4Plane3D& s = fVP.GetSectionPlane ();
230    double sArray[4];
231    sArray[0] = s.a();
232    sArray[1] = s.b();
233    sArray[2] = s.c();
234    sArray[3] = s.d() + radius * 1.e-05;
235    glClipPlane (GL_CLIP_PLANE0, sArray);
236    glEnable (GL_CLIP_PLANE0);
237    sArray[0] = -s.a();
238    sArray[1] = -s.b();
239    sArray[2] = -s.c();
240    sArray[3] = -s.d() + radius * 1.e-05;
241    glClipPlane (GL_CLIP_PLANE1, sArray);
242    glEnable (GL_CLIP_PLANE1);
243  } else {
244    glDisable (GL_CLIP_PLANE0);
245    glDisable (GL_CLIP_PLANE1);
246  }
247
248  const G4Planes& cutaways = fVP.GetCutawayPlanes();
249  size_t nPlanes = cutaways.size();
250  if (fVP.IsCutaway() &&
251      fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
252      nPlanes > 0) {
253    double a[4];
254    a[0] = cutaways[0].a();
255    a[1] = cutaways[0].b();
256    a[2] = cutaways[0].c();
257    a[3] = cutaways[0].d();
258    glClipPlane (GL_CLIP_PLANE2, a);
259    glEnable (GL_CLIP_PLANE2);
260    if (nPlanes > 1) {
261      a[0] = cutaways[1].a();
262      a[1] = cutaways[1].b();
263      a[2] = cutaways[1].c();
264      a[3] = cutaways[1].d();
265      glClipPlane (GL_CLIP_PLANE3, a);
266      glEnable (GL_CLIP_PLANE3);
267    }
268    if (nPlanes > 2) {
269      a[0] = cutaways[2].a();
270      a[1] = cutaways[2].b();
271      a[2] = cutaways[2].c();
272      a[3] = cutaways[2].d();
273      glClipPlane (GL_CLIP_PLANE4, a);
274      glEnable (GL_CLIP_PLANE4);
275    }
276  } else {
277    glDisable (GL_CLIP_PLANE2);
278    glDisable (GL_CLIP_PLANE3);
279    glDisable (GL_CLIP_PLANE4);
280  }
281
282  // Background.
283  background = fVP.GetBackgroundColour ();
284
285}
286
287void G4OpenGLViewer::HaloingFirstPass () {
288 
289  //To perform haloing, first Draw all information to the depth buffer
290  //alone, using a chunky line width, and then Draw all info again, to
291  //the colour buffer, setting a thinner line width an the depth testing
292  //function to less than or equal, so if two lines cross, the one
293  //passing behind the other will not pass the depth test, and so not
294  //get rendered either side of the infront line for a short distance.
295
296  //First, disable writing to the colo(u)r buffer...
297  glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
298
299  //Now enable writing to the depth buffer...
300  glDepthMask (GL_TRUE);
301  glDepthFunc (GL_LESS);
302  glClearDepth (1.0);
303
304  //Finally, set the line width to something wide...
305  glLineWidth (3.0);
306
307}
308
309void G4OpenGLViewer::HaloingSecondPass () {
310
311  //And finally, turn the colour buffer back on with a sesible line width...
312  glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
313  glDepthFunc (GL_LEQUAL);
314  glLineWidth (1.0);
315
316}
317
318void G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
319{
320  //G4cout << "X: " << x << ", Y: " << y << G4endl;
321  const G4int BUFSIZE = 512;
322  GLuint selectBuffer[BUFSIZE];
323  glSelectBuffer(BUFSIZE, selectBuffer);
324  glRenderMode(GL_SELECT);
325  glInitNames();
326  glPushName(0);
327  glMatrixMode(GL_PROJECTION);
328  G4double currentProjectionMatrix[16];
329  glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
330  glPushMatrix();
331  glLoadIdentity();
332  GLint viewport[4];
333  glGetIntegerv(GL_VIEWPORT, viewport);
334  // Define 5x5 pixel pick area
335  gluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
336  glMultMatrixd(currentProjectionMatrix);
337  glMatrixMode(GL_MODELVIEW);
338  DrawView();
339  GLint hits = glRenderMode(GL_RENDER);
340  if (hits < 0)
341    G4cout << "Too many hits.  Zoom in to reduce overlaps." << G4cout;
342  else if (hits > 0) {
343    //G4cout << hits << " hit(s)" << G4endl;
344    GLuint* p = selectBuffer;
345    for (GLint i = 0; i < hits; ++i) {
346      GLuint nnames = *p++;
347      *p++; //OR GLuint zmin = *p++;
348      *p++; //OR GLuint zmax = *p++;
349      //G4cout << "Hit " << i << ": " << nnames << " names"
350      //     << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
351      for (GLuint j = 0; j < nnames; ++j) {
352        GLuint name = *p++;
353        //G4cout << "Name " << j << ": PickName: " << name << G4endl;
354        std::map<GLuint, G4AttHolder*>::iterator iter =
355          fOpenGLSceneHandler.fPickMap.find(name);
356        if (iter != fOpenGLSceneHandler.fPickMap.end()) {
357          G4AttHolder* attHolder = iter->second;
358          if(attHolder && attHolder->GetAttDefs().size()) {
359            for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
360              G4cout << G4AttCheck(attHolder->GetAttValues()[i],
361                                   attHolder->GetAttDefs()[i]);
362            }
363          }
364        }
365      }
366      G4cout << G4endl;
367    }
368  }
369  glMatrixMode(GL_PROJECTION);
370  glPopMatrix();
371  glMatrixMode(GL_MODELVIEW);
372}
373
374void G4OpenGLViewer::print() {
375
376  // Print vectored PostScript
377 
378  G4int size = 5000000;
379  GLfloat* feedback_buffer = new GLfloat[size];
380  glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
381  glRenderMode (GL_FEEDBACK);
382 
383  DrawView();
384
385  GLint returned;
386  returned = glRenderMode (GL_RENDER);
387 
388  FILE* file;
389  if (print_string) {
390    file = fopen (print_string, "w");
391    if (file) {
392      spewWireframeEPS (file, returned, feedback_buffer, "rendereps");
393    } else {
394      printf("Could not open %s\n", print_string);
395    }
396  } else {
397    printBuffer (returned, feedback_buffer);
398  }
399
400  delete[] feedback_buffer;
401}
402
403void G4OpenGLViewer::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer)
404{
405  G4int i;
406
407  printf("  ");
408  for (i = 0; i < 7; i++) {
409    printf("%4.2f ", buffer[size - (*count)]);
410    *count = *count - 1;
411  }
412  printf("\n");
413}
414
415void G4OpenGLViewer::spewWireframeEPS (FILE* file, GLint size, GLfloat* buffer, const char* cr) {
416
417  GLfloat EPS_GOURAUD_THRESHOLD=0.1;
418
419  GLfloat clearColor[4], viewport[4];
420  GLfloat lineWidth;
421  G4int i;
422
423  glGetFloatv (GL_VIEWPORT, viewport);
424  glGetFloatv (GL_COLOR_CLEAR_VALUE, clearColor);
425  glGetFloatv (GL_LINE_WIDTH, &lineWidth);
426  glGetFloatv (GL_POINT_SIZE, &pointSize);
427
428  fputs ("%!PS-Adobe-2.0 EPSF-2.0\n", file);
429  fprintf (file, "%%%%Creator: %s (using OpenGL feedback)\n", cr);
430  fprintf (file, "%%%%BoundingBox: %g %g %g %g\n", viewport[0], viewport[1], viewport[2], viewport[3]);
431  fputs ("%%EndComments\n", file);
432  fputs ("\n", file);
433  fputs ("gsave\n", file);
434  fputs ("\n", file);
435
436  fputs ("% the gouraudtriangle PostScript fragment below is free\n", file);
437  fputs ("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file);
438  fprintf (file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD);
439  for (i=0; gouraudtriangleEPS[i]; i++) {
440    fprintf (file, "%s\n", gouraudtriangleEPS[i]);
441  }
442
443  fprintf(file, "\n%g setlinewidth\n", lineWidth);
444 
445  fprintf (file, "%g %g %g setrgbcolor\n", clearColor[0], clearColor[1], clearColor[2]);
446  fprintf (file, "%g %g %g %g rectfill\n\n", viewport[0], viewport[1], viewport[2], viewport[3]);
447
448  spewSortedFeedback (file, size, buffer);
449
450  fputs ("grestore\n\n", file);
451  fputs ("showpage\n", file);
452
453  fclose(file);
454}
455
456void G4OpenGLViewer::printBuffer (GLint size, GLfloat* buffer) {
457
458  GLint count;
459  G4int token, nvertices;
460
461  count=size;
462  while(count) {
463    token=G4int (buffer[size-count]);
464    count--;
465    switch (token) {
466
467    case GL_PASS_THROUGH_TOKEN:
468      printf ("GL_PASS_THROUGH_TOKEN\n");
469      printf ("  %4.2f\n", buffer[size-count]);
470      count--;
471      break;
472
473    case GL_POINT_TOKEN:
474      printf ("GL_POINT_TOKEN\n");
475      print3DcolorVertex (size, &count, buffer);
476      break;
477
478    case GL_LINE_TOKEN:
479      printf ("GL_LINE_TOKEN\n");
480      print3DcolorVertex (size, &count, buffer);
481      print3DcolorVertex (size, &count, buffer);
482      break;
483     
484    case GL_LINE_RESET_TOKEN:
485      printf ("GL_LINE_RESET_TOKEN\n");
486      print3DcolorVertex (size, &count, buffer);
487      print3DcolorVertex (size, &count, buffer);
488      break;
489
490    case GL_POLYGON_TOKEN:
491      printf ("GL_POLYGON_TOKEN\n");
492      nvertices=G4int (buffer[size-count]);
493      count--;
494      for (; nvertices>0; nvertices--) {
495        print3DcolorVertex (size, &count, buffer);
496      }
497    }
498  }
499}
500
501G4float* G4OpenGLViewer::spewPrimitiveEPS (FILE* file, GLfloat* loc) {
502 
503  G4int token;
504  G4int nvertices, i;
505  GLfloat red, green, blue, intensity;
506  G4int smooth;
507  GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax;
508  G4int steps;
509  Feedback3Dcolor *vertex;
510  GLfloat xstep(0.), ystep(0.), rstep(0.), gstep(0.), bstep(0.);
511  GLfloat xnext(0.), ynext(0.), rnext(0.), gnext(0.), bnext(0.), distance(0.);
512
513  token=G4int (*loc);
514  loc++;
515  switch (token) {
516  case GL_LINE_RESET_TOKEN:
517  case GL_LINE_TOKEN:
518    vertex=(Feedback3Dcolor*)loc;
519    dr=vertex[1].red - vertex[0].red;
520    dg=vertex[1].green - vertex[0].green;
521    db=vertex[1].blue - vertex[0].blue;
522
523    if (!print_colour) {
524      dr+=(dg+db);
525      dr/=3.0;
526      dg=dr;
527      db=dr;
528    }
529
530    if (dr!=0 || dg!=0 || db!=0) {
531      dx=vertex[1].x - vertex[0].x;
532      dy=vertex[1].y - vertex[0].y;
533      distance=std::sqrt(dx*dx + dy*dy);
534
535      absR=std::fabs(dr);
536      absG=std::fabs(dg);
537      absB=std::fabs(db);
538
539      #define Max(a, b) (((a)>(b))?(a):(b))
540
541      #define EPS_SMOOTH_LINE_FACTOR 0.06
542
543      colormax=Max(absR, Max(absG, absB));
544      steps=Max(1, G4int (colormax*distance*EPS_SMOOTH_LINE_FACTOR));
545     
546      xstep=dx/steps;
547      ystep=dy/steps;
548
549      rstep=dr/steps;
550      gstep=dg/steps;
551      bstep=db/steps;
552
553      xnext=vertex[0].x;
554      ynext=vertex[0].y;
555      rnext=vertex[0].red;
556      gnext=vertex[0].green;
557      bnext=vertex[0].blue;
558
559      if (!print_colour) {
560        rnext+=(gnext+bnext);
561        rnext/=3.0;
562        gnext=rnext;
563        bnext=rnext;
564      }
565
566      xnext -= xstep/2.0;
567      ynext -= ystep/2.0;
568      rnext -= rstep/2.0;
569      gnext -= gstep/2.0;
570      bnext -= bstep/2.0;
571    } else {
572      steps=0;
573    }
574    if (print_colour) {
575      fprintf (file, "%g %g %g setrgbcolor\n",
576               vertex[0].red, vertex[0].green, vertex[0].blue);
577    } else {
578      intensity = (vertex[0].red + vertex[0].green + vertex[0].blue) / 3.0;
579      fprintf (file, "%g %g %g setrgbcolor\n",
580               intensity, intensity, intensity);
581    }     
582    fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
583
584    for (i=0; i<steps; i++) {
585
586      xnext += xstep;
587      ynext += ystep;
588      rnext += rstep;
589      gnext += gstep;
590      bnext += bstep;
591
592      fprintf (file, "%g %g lineto stroke\n", xnext, ynext);
593      fprintf (file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext);
594      fprintf (file, "%g %g moveto\n", xnext, ynext);
595    }
596    fprintf (file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y);
597
598    loc += 14;
599    break;
600
601  case GL_POLYGON_TOKEN:
602    nvertices = G4int (*loc);
603    loc++;
604    vertex=(Feedback3Dcolor*)loc;
605    if (nvertices>0) {
606      red=vertex[0].red;
607      green=vertex[0].green;
608      blue=vertex[0].blue;
609      smooth=0;
610     
611      if (!print_colour) {
612        red+=(green+blue);
613        red/=3.0;
614        green=red;
615        blue=red;
616      }
617     
618      if (print_colour) {
619        for (i=1; i<nvertices; i++) {
620          if (red!=vertex[i].red || green!=vertex[i].green || blue!=vertex[i].blue) {
621            smooth=1;
622            break;
623          }
624        }
625      } else {
626        for (i=1; i<nvertices; i++) {
627          intensity = vertex[i].red + vertex[i].green + vertex[i].blue;
628          intensity/=3.0;
629          if (red!=intensity) {
630            smooth=1;
631            break;
632          }
633        }
634      }
635
636      if (smooth) {
637        G4int triOffset;
638        for (i=0; i<nvertices-2; i++) {
639          triOffset = i*7;
640          fprintf (file, "[%g %g %g %g %g %g]",
641                   vertex[0].x, vertex[i+1].x, vertex[i+2].x,
642                   vertex[0].y, vertex[i+1].y, vertex[i+2].y);
643          if (print_colour) {
644            fprintf (file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n",
645                     vertex[0].red, vertex[0].green, vertex[0].blue,
646                     vertex[i+1].red, vertex[i+1].green, vertex[i+1].blue,
647                     vertex[i+2].red, vertex[i+2].green, vertex[i+2].blue);
648          } else {
649
650            intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
651            intensity/=3.0;
652            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
653
654            intensity = vertex[1].red + vertex[1].green + vertex[1].blue;
655            intensity/=3.0;
656            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
657
658            intensity = vertex[2].red + vertex[2].green + vertex[2].blue;
659            intensity/=3.0;
660            fprintf (file, " [%g %g %g] gouraudtriangle\n", intensity, intensity, intensity);
661          }
662        }
663      } else {
664        fprintf (file, "newpath\n");
665        fprintf (file, "%g %g %g setrgbcolor\n", red, green, blue);
666        fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
667        for (i=1; i<nvertices; i++) {
668          fprintf (file, "%g %g lineto\n", vertex[i].x, vertex[i].y);
669        }
670        fprintf (file, "closepath fill\n\n");
671      }
672    }
673    loc += nvertices*7;
674    break;
675
676  case GL_POINT_TOKEN:
677    vertex=(Feedback3Dcolor*)loc;
678    if (print_colour) {
679      fprintf (file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue);
680    } else {
681      intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
682      intensity/=3.0;
683      fprintf (file, "%g %g %g setrgbcolor\n", intensity, intensity, intensity);
684    }     
685    fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, pointSize / 2.0);
686    loc += 7;           /* Each vertex element in the feedback
687                           buffer is 7 GLfloats. */
688    break;
689  default:
690    /* XXX Left as an excersie to the reader. */
691    static G4bool spewPrimitiveEPSWarned = false;
692    if (!spewPrimitiveEPSWarned) {
693      std::ostringstream oss;
694      oss <<
695        "Incomplete implementation.  Unexpected token (" << token << ")."
696        "\n  (Seems to be caused by text.)";
697      G4Exception("G4OpenGLViewer::spewPrimitiveEPS",
698                  "Unexpected token",
699                  JustWarning,
700                  oss.str().c_str());
701      spewPrimitiveEPSWarned = true;
702    }
703  }
704  return loc;
705}
706
707typedef struct G4OpenGLViewerDepthIndex {
708  GLfloat *ptr;
709  GLfloat depth;
710} DepthIndex;
711
712extern "C" {
713  int G4OpenGLViewercompare(const void *a, const void *b)
714  {
715    const DepthIndex *p1 = (DepthIndex *) a;
716    const DepthIndex *p2 = (DepthIndex *) b;
717    GLfloat diff = p2->depth - p1->depth;
718   
719    if (diff > 0.0) {
720      return 1;
721    } else if (diff < 0.0) {
722      return -1;
723    } else {
724      return 0;
725    }
726  }
727}
728
729GLdouble G4OpenGLViewer::getSceneNearWidth()
730{
731  const G4Point3D targetPoint
732    = fSceneHandler.GetScene()->GetStandardTargetPoint()
733    + fVP.GetCurrentTargetPoint ();
734  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
735  if(radius<=0.) radius = 1.;
736  const G4double cameraDistance = fVP.GetCameraDistance (radius);
737  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
738  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
739}
740
741GLdouble G4OpenGLViewer::getSceneFarWidth()
742{
743  const G4Point3D targetPoint
744    = fSceneHandler.GetScene()->GetStandardTargetPoint()
745    + fVP.GetCurrentTargetPoint ();
746  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
747  if(radius<=0.) radius = 1.;
748  const G4double cameraDistance = fVP.GetCameraDistance (radius);
749  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
750  const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
751  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
752}
753
754
755GLdouble G4OpenGLViewer::getSceneDepth()
756{
757  const G4Point3D targetPoint
758    = fSceneHandler.GetScene()->GetStandardTargetPoint()
759    + fVP.GetCurrentTargetPoint ();
760  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
761  if(radius<=0.) radius = 1.;
762  const G4double cameraDistance = fVP.GetCameraDistance (radius);
763  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
764  return fVP.GetFarDistance  (cameraDistance, pnear, radius)- pnear;
765}
766
767
768void G4OpenGLViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer)
769{
770  int token;
771  GLfloat *loc, *end;
772  Feedback3Dcolor *vertex;
773  GLfloat depthSum;
774  int nprimitives, item;
775  DepthIndex *prims;
776  int nvertices, i;
777
778  end = buffer + size;
779
780  /* Count how many primitives there are. */
781  nprimitives = 0;
782  loc = buffer;
783  while (loc < end) {
784    token = int (*loc);
785    loc++;
786    switch (token) {
787    case GL_LINE_TOKEN:
788    case GL_LINE_RESET_TOKEN:
789      loc += 14;
790      nprimitives++;
791      break;
792    case GL_POLYGON_TOKEN:
793      nvertices = int (*loc);
794      loc++;
795      loc += (7 * nvertices);
796      nprimitives++;
797      break;
798    case GL_POINT_TOKEN:
799      loc += 7;
800      nprimitives++;
801      break;
802    default:
803      /* XXX Left as an excersie to the reader. */
804      static G4bool spewSortedFeedbackWarned = false;
805      if (!spewSortedFeedbackWarned) {
806        std::ostringstream oss;
807        oss <<
808          "Incomplete implementation.  Unexpected token (" << token << ")."
809          "\n  (Seems to be caused by text.)";
810        G4Exception("G4OpenGLViewer::spewSortedFeedback",
811                    "Unexpected token",
812                    JustWarning,
813                    oss.str().c_str());
814        spewSortedFeedbackWarned = true;
815      }
816      nprimitives++;
817    }
818  }
819
820  /* Allocate an array of pointers that will point back at
821     primitives in the feedback buffer.  There will be one
822     entry per primitive.  This array is also where we keep the
823     primitive's average depth.  There is one entry per
824     primitive  in the feedback buffer. */
825  prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives);
826
827  item = 0;
828  loc = buffer;
829  while (loc < end) {
830    prims[item].ptr = loc;  /* Save this primitive's location. */
831    token = int (*loc);
832    loc++;
833    switch (token) {
834    case GL_LINE_TOKEN:
835    case GL_LINE_RESET_TOKEN:
836      vertex = (Feedback3Dcolor *) loc;
837      depthSum = vertex[0].z + vertex[1].z;
838      prims[item].depth = depthSum / 2.0;
839      loc += 14;
840      break;
841    case GL_POLYGON_TOKEN:
842      nvertices = int (*loc);
843      loc++;
844      vertex = (Feedback3Dcolor *) loc;
845      depthSum = vertex[0].z;
846      for (i = 1; i < nvertices; i++) {
847        depthSum += vertex[i].z;
848      }
849      prims[item].depth = depthSum / nvertices;
850      loc += (7 * nvertices);
851      break;
852    case GL_POINT_TOKEN:
853      vertex = (Feedback3Dcolor *) loc;
854      prims[item].depth = vertex[0].z;
855      loc += 7;
856      break;
857    default:
858      /* XXX Left as an excersie to the reader. */
859      assert(1);
860    }
861    item++;
862  }
863  assert(item == nprimitives);
864
865  /* Sort the primitives back to front. */
866  qsort(prims, nprimitives, sizeof(DepthIndex), G4OpenGLViewercompare);
867
868  /* Understand that sorting by a primitives average depth
869     doesn't allow us to disambiguate some cases like self
870     intersecting polygons.  Handling these cases would require
871     breaking up the primitives.  That's too involved for this
872     example.  Sorting by depth is good enough for lots of
873     applications. */
874
875  /* Emit the Encapsulated PostScript for the primitives in
876     back to front order. */
877  for (item = 0; item < nprimitives; item++) {
878    (void) spewPrimitiveEPS(file, prims[item].ptr);
879  }
880
881  free(prims);
882}
883
884void G4OpenGLViewer::rotateScene(G4double dx, G4double dy,G4double deltaRotation)
885{
886
887  G4Vector3D vp;
888  G4Vector3D up;
889 
890  G4Vector3D xprime;
891  G4Vector3D yprime;
892  G4Vector3D zprime;
893 
894  G4double delta_alpha;
895  G4double delta_theta;
896 
897  G4Vector3D new_vp;
898  G4Vector3D new_up;
899 
900  G4double cosalpha;
901  G4double sinalpha;
902 
903  G4Vector3D a1;
904  G4Vector3D a2;
905  G4Vector3D delta;
906  G4Vector3D viewPoint;
907
908   
909  //phi spin stuff here
910 
911  vp = fVP.GetViewpointDirection ().unit ();
912  up = fVP.GetUpVector ().unit ();
913 
914  yprime = (up.cross(vp)).unit();
915  zprime = (vp.cross(yprime)).unit();
916 
917  if (fVP.GetLightsMoveWithCamera()) {
918    delta_alpha = dy * deltaRotation;
919    delta_theta = -dx * deltaRotation;
920  } else {
921    delta_alpha = -dy * deltaRotation;
922    delta_theta = dx * deltaRotation;
923  }   
924 
925  delta_alpha *= deg;
926  delta_theta *= deg;
927 
928  new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
929 
930  // to avoid z rotation flipping
931  // to allow more than 360° rotation
932
933  const G4Point3D targetPoint
934    = fSceneHandler.GetScene()->GetStandardTargetPoint()
935    + fVP.GetCurrentTargetPoint ();
936  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
937  if(radius<=0.) radius = 1.;
938  const G4double cameraDistance = fVP.GetCameraDistance (radius);
939  const G4Point3D cameraPosition =
940    targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
941
942  if (fVP.GetLightsMoveWithCamera()) {
943    new_up = (new_vp.cross(yprime)).unit();
944    if (new_vp.z()*vp.z() <0) {
945      new_up.set(new_up.x(),-new_up.y(),new_up.z());
946    }
947  } else {
948    new_up = up;
949    if (new_vp.z()*vp.z() <0) {
950      new_up.set(new_up.x(),-new_up.y(),new_up.z());
951    }
952  }
953  fVP.SetUpVector(new_up);
954  ////////////////
955  // Rotates by fixed azimuthal angle delta_theta.
956 
957  cosalpha = new_up.dot (new_vp.unit());
958  sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
959  yprime = (new_up.cross (new_vp.unit())).unit ();
960  xprime = yprime.cross (new_up);
961  // Projection of vp on plane perpendicular to up...
962  a1 = sinalpha * xprime;
963  // Required new projection...
964  a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
965  // Required Increment vector...
966  delta = a2 - a1;
967  // So new viewpoint is...
968  viewPoint = new_vp.unit() + delta;
969 
970  fVP.SetViewAndLights (viewPoint);
971}
972
973#endif
Note: See TracBrowser for help on using the repository browser.