source: trunk/source/visualization/OpenGL/src/G4OpenGLViewer.cc @ 908

Last change on this file since 908 was 908, checked in by garnier, 15 years ago

update with CVS

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