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

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

test pour GL_POINTS au lieu de glBitmap

  • Property svn:mime-type set to text/cpp
File size: 36.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.48 2009/02/16 15:31:05 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#define G4DEBUG_VIS_OGL
37
38#include "G4ios.hh"
39#include "G4OpenGLViewer.hh"
40#include "G4OpenGLSceneHandler.hh"
41#include "G4OpenGLTransform3D.hh"
42#include "G4OpenGL2PSAction.hh"
43
44#include "G4Scene.hh"
45#include "G4VisExtent.hh"
46#include "G4LogicalVolume.hh"
47#include "G4VSolid.hh"
48#include "G4Point3D.hh"
49#include "G4Normal3D.hh"
50#include "G4Plane3D.hh"
51#include "G4AttHolder.hh"
52#include "G4AttCheck.hh"
53
54// GL2PS
55#include "Geant4_gl2ps.h"
56
57#include <sstream>
58
59static const char* gouraudtriangleEPS[] =
60{
61  "/bd{bind def}bind def /triangle { aload pop   setrgbcolor  aload pop 5 3",
62  "roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd",
63  "/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2",
64  "index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse",
65  "} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get",
66  "computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get",
67  "computediff1 {true} { 3 copy 2 get 3 1 roll  2 get 3 1 roll 2 get",
68  "computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll",
69  "aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2",
70  "div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4",
71  "-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add",
72  "2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1",
73  "roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3",
74  "1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll",
75  "2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll",
76  "aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array",
77  "astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17",
78  "index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index",
79  "gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6",
80  "array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index",
81  "15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14",
82  "index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3",
83  "roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7",
84  "index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add",
85  "add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd",
86  NULL
87};
88
89G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
90G4VViewer (scene, -1),
91fPrintFilename ("G4OpenGL.eps"),
92fPrintColour (true),
93fVectoredPs (true),
94fOpenGLSceneHandler(scene),
95background (G4Colour(0.,0.,0.)),
96transparency_enabled (true),
97antialiasing_enabled (false),
98haloing_enabled (false),
99fStartTime(-DBL_MAX),
100fEndTime(DBL_MAX),
101fFadeFactor(0.),
102fDisplayHeadTime(false),
103fDisplayHeadTimeX(-0.9),
104fDisplayHeadTimeY(-0.9),
105fDisplayHeadTimeSize(24.),
106fDisplayHeadTimeRed(0.),
107fDisplayHeadTimeGreen(1.),
108fDisplayHeadTimeBlue(1.),
109fDisplayLightFront(false),
110fDisplayLightFrontX(0.),
111fDisplayLightFrontY(0.),
112fDisplayLightFrontZ(0.),
113fDisplayLightFrontT(0.),
114fDisplayLightFrontRed(0.),
115fDisplayLightFrontGreen(1.),
116fDisplayLightFrontBlue(0.),
117fPointSize (0)
118{
119  // Make changes to view parameters for OpenGL...
120  fVP.SetAutoRefresh(true);
121  fDefaultVP.SetAutoRefresh(true);
122  fWinSize_x = fVP.GetWindowSizeHintX();
123  fWinSize_y = fVP.GetWindowSizeHintY();
124
125  fGL2PSAction = new G4OpenGL2PSAction();
126
127  //  glClearColor (0.0, 0.0, 0.0, 0.0);
128  //  glClearDepth (1.0);
129  //  glDisable (GL_BLEND);
130  //  glDisable (GL_LINE_SMOOTH);
131  //  glDisable (GL_POLYGON_SMOOTH);
132
133}
134
135G4OpenGLViewer::~G4OpenGLViewer () {}
136
137void G4OpenGLViewer::InitializeGLView ()
138{
139  glClearColor (0.0, 0.0, 0.0, 0.0);
140  glClearDepth (1.0);
141  glDisable (GL_BLEND);
142  glDisable (GL_LINE_SMOOTH);
143  glDisable (GL_POLYGON_SMOOTH);
144
145
146void G4OpenGLViewer::ClearView () {
147#ifdef G4DEBUG_VIS_OGL
148  printf("G4OpenGLViewer::ClearView VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV \n");
149#endif
150  glClearColor (background.GetRed(),
151                background.GetGreen(),
152                background.GetBlue(),
153                1.);
154  glClearDepth (1.0);
155  //Below line does not compile with Mesa includes.
156  //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
157  glClear (GL_COLOR_BUFFER_BIT);
158  glClear (GL_DEPTH_BUFFER_BIT);
159  glClear (GL_STENCIL_BUFFER_BIT);
160  glFlush ();
161#ifdef G4DEBUG_VIS_OGL
162  printf("G4OpenGLViewer::ClearView ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
163#endif
164}
165
166
167/**
168 * Set the viewport of the scene
169 */
170void G4OpenGLViewer::ResizeGLView()
171{
172  int side = fWinSize_x;
173  if (fWinSize_y < fWinSize_x) side = fWinSize_y;
174  glViewport((fWinSize_x - side) / 2, (fWinSize_y - side) / 2, side, side); 
175}
176
177
178void G4OpenGLViewer::SetView () {
179
180#ifdef G4DEBUG_VIS_OGL
181  printf("G4OpenGLViewer::SetView VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV \n");
182#endif
183
184  if (!fSceneHandler.GetScene()) {
185    G4cerr << "G4OpenGLStoredViewer: Creating a Viewer without a scene is not allowed. \nPlease use /vis/scene/create before /vis/open/.... "
186           << G4endl;
187    return;
188  }
189  // Calculates view representation based on extent of object being
190  // viewed and (initial) viewpoint.  (Note: it can change later due
191  // to user interaction via visualization system's GUI.)
192 
193  // Lighting.
194  GLfloat lightPosition [4];
195  lightPosition [0] = fVP.GetActualLightpointDirection().x();
196  lightPosition [1] = fVP.GetActualLightpointDirection().y();
197  lightPosition [2] = fVP.GetActualLightpointDirection().z();
198  lightPosition [3] = 0.;
199  // Light position is "true" light direction, so must come after gluLookAt.
200  GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
201  GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
202  glEnable (GL_LIGHT0);
203  glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
204  glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
205 
206  // Get radius of scene, etc.
207  // Note that this procedure properly takes into account zoom, dolly and pan.
208  const G4Point3D targetPoint
209    = fSceneHandler.GetScene()->GetStandardTargetPoint()
210    + fVP.GetCurrentTargetPoint ();
211  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
212  if(radius<=0.) radius = 1.;
213  const G4double cameraDistance = fVP.GetCameraDistance (radius);
214  const G4Point3D cameraPosition =
215    targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
216  const GLdouble pnear  = fVP.GetNearDistance (cameraDistance, radius);
217  const GLdouble pfar   = fVP.GetFarDistance  (cameraDistance, pnear, radius);
218  const GLdouble right  = fVP.GetFrontHalfHeight (pnear, radius);
219  const GLdouble left   = -right;
220  const GLdouble bottom = left;
221  const GLdouble top    = right;
222 
223  // FIXME
224  ResizeGLView();
225  //SHOULD SetWindowsSizeHint()...
226
227  glMatrixMode (GL_PROJECTION); // set up Frustum.
228  glLoadIdentity();
229
230  const G4Vector3D scaleFactor = fVP.GetScaleFactor();
231  glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
232 
233  if (fVP.GetFieldHalfAngle() == 0.) {
234    glOrtho (left, right, bottom, top, pnear, pfar);
235  }
236  else {
237    glFrustum (left, right, bottom, top, pnear, pfar);
238  } 
239
240  glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
241  glLoadIdentity();
242 
243  const G4Normal3D& upVector = fVP.GetUpVector (); 
244  G4Point3D gltarget;
245  if (cameraDistance > 1.e-6 * radius) {
246    gltarget = targetPoint;
247  }
248  else {
249    gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
250  }
251
252  const G4Point3D& pCamera = cameraPosition;  // An alias for brevity.
253  gluLookAt (pCamera.x(),  pCamera.y(),  pCamera.z(),       // Viewpoint.
254             gltarget.x(), gltarget.y(), gltarget.z(),      // Target point.
255             upVector.x(), upVector.y(), upVector.z());     // Up vector.
256
257  // Light position is "true" light direction, so must come after gluLookAt.
258  glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
259
260  // OpenGL no longer seems to reconstruct clipped edges, so, when the
261  // BooleanProcessor is up to it, abandon this and use generic
262  // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron.  Also,
263  // force kernel visit on change of clipping plane in
264  // G4OpenGLStoredViewer::CompareForKernelVisit.
265  if (fVP.IsSection () ) {  // pair of back to back clip planes.
266    const G4Plane3D& s = fVP.GetSectionPlane ();
267    double sArray[4];
268    sArray[0] = s.a();
269    sArray[1] = s.b();
270    sArray[2] = s.c();
271    sArray[3] = s.d() + radius * 1.e-05;
272    glClipPlane (GL_CLIP_PLANE0, sArray);
273    glEnable (GL_CLIP_PLANE0);
274    sArray[0] = -s.a();
275    sArray[1] = -s.b();
276    sArray[2] = -s.c();
277    sArray[3] = -s.d() + radius * 1.e-05;
278    glClipPlane (GL_CLIP_PLANE1, sArray);
279    glEnable (GL_CLIP_PLANE1);
280  } else {
281    glDisable (GL_CLIP_PLANE0);
282    glDisable (GL_CLIP_PLANE1);
283  }
284
285  const G4Planes& cutaways = fVP.GetCutawayPlanes();
286  size_t nPlanes = cutaways.size();
287  if (fVP.IsCutaway() &&
288      fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
289      nPlanes > 0) {
290    double a[4];
291    a[0] = cutaways[0].a();
292    a[1] = cutaways[0].b();
293    a[2] = cutaways[0].c();
294    a[3] = cutaways[0].d();
295    glClipPlane (GL_CLIP_PLANE2, a);
296    glEnable (GL_CLIP_PLANE2);
297    if (nPlanes > 1) {
298      a[0] = cutaways[1].a();
299      a[1] = cutaways[1].b();
300      a[2] = cutaways[1].c();
301      a[3] = cutaways[1].d();
302      glClipPlane (GL_CLIP_PLANE3, a);
303      glEnable (GL_CLIP_PLANE3);
304    }
305    if (nPlanes > 2) {
306      a[0] = cutaways[2].a();
307      a[1] = cutaways[2].b();
308      a[2] = cutaways[2].c();
309      a[3] = cutaways[2].d();
310      glClipPlane (GL_CLIP_PLANE4, a);
311      glEnable (GL_CLIP_PLANE4);
312    }
313  } else {
314    glDisable (GL_CLIP_PLANE2);
315    glDisable (GL_CLIP_PLANE3);
316    glDisable (GL_CLIP_PLANE4);
317  }
318
319  // Background.
320  background = fVP.GetBackgroundColour ();
321
322#ifdef G4DEBUG_VIS_OGL
323  printf("G4OpenGLViewer::SetView ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \n");
324#endif
325}
326
327void G4OpenGLViewer::HaloingFirstPass () {
328 
329#ifdef G4DEBUG_VIS_OGL
330  printf("G4OpenGLViewer::HaloingFirstPass VVVVVVVVVVVVVVVVVV \n");
331#endif
332  //To perform haloing, first Draw all information to the depth buffer
333  //alone, using a chunky line width, and then Draw all info again, to
334  //the colour buffer, setting a thinner line width an the depth testing
335  //function to less than or equal, so if two lines cross, the one
336  //passing behind the other will not pass the depth test, and so not
337  //get rendered either side of the infront line for a short distance.
338
339  //First, disable writing to the colo(u)r buffer...
340  glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
341
342  //Now enable writing to the depth buffer...
343  glDepthMask (GL_TRUE);
344  glDepthFunc (GL_LESS);
345  glClearDepth (1.0);
346
347  //Finally, set the line width to something wide...
348  glLineWidth (3.0);
349
350}
351
352void G4OpenGLViewer::HaloingSecondPass () {
353
354#ifdef G4DEBUG_VIS_OGL
355  printf("G4OpenGLViewer::HaloingSecondtPass VVVVVVVVVVVVVVVVVV \n");
356#endif
357  //And finally, turn the colour buffer back on with a sesible line width...
358  glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
359  glDepthFunc (GL_LEQUAL);
360  glLineWidth (1.0);
361
362}
363
364void G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
365{
366  //G4cout << "X: " << x << ", Y: " << y << G4endl;
367  const G4int BUFSIZE = 512;
368  GLuint selectBuffer[BUFSIZE];
369  glSelectBuffer(BUFSIZE, selectBuffer);
370  glRenderMode(GL_SELECT);
371  glInitNames();
372  glPushName(0);
373  glMatrixMode(GL_PROJECTION);
374  G4double currentProjectionMatrix[16];
375  glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
376  glPushMatrix();
377  glLoadIdentity();
378  GLint viewport[4];
379  glGetIntegerv(GL_VIEWPORT, viewport);
380  // Define 5x5 pixel pick area
381  gluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
382  glMultMatrixd(currentProjectionMatrix);
383  glMatrixMode(GL_MODELVIEW);
384  DrawView();
385  GLint hits = glRenderMode(GL_RENDER);
386  if (hits < 0)
387    G4cout << "Too many hits.  Zoom in to reduce overlaps." << G4cout;
388  else if (hits > 0) {
389    //G4cout << hits << " hit(s)" << G4endl;
390    GLuint* p = selectBuffer;
391    for (GLint i = 0; i < hits; ++i) {
392      GLuint nnames = *p++;
393      *p++; //OR GLuint zmin = *p++;
394      *p++; //OR GLuint zmax = *p++;
395      //G4cout << "Hit " << i << ": " << nnames << " names"
396      //     << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
397      for (GLuint j = 0; j < nnames; ++j) {
398        GLuint name = *p++;
399        //G4cout << "Name " << j << ": PickName: " << name << G4endl;
400        std::map<GLuint, G4AttHolder*>::iterator iter =
401          fOpenGLSceneHandler.fPickMap.find(name);
402        if (iter != fOpenGLSceneHandler.fPickMap.end()) {
403          G4AttHolder* attHolder = iter->second;
404          if(attHolder && attHolder->GetAttDefs().size()) {
405            for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
406              G4cout << G4AttCheck(attHolder->GetAttValues()[i],
407                                   attHolder->GetAttDefs()[i]);
408            }
409          }
410        }
411      }
412      G4cout << G4endl;
413    }
414  }
415  glMatrixMode(GL_PROJECTION);
416  glPopMatrix();
417  glMatrixMode(GL_MODELVIEW);
418}
419
420void G4OpenGLViewer::printVectoredEPS() {
421
422  // Print vectored PostScript
423 
424  G4int size = 5000000;
425  GLfloat* feedback_buffer = new GLfloat[size];
426  glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
427  glRenderMode (GL_FEEDBACK);
428 
429  DrawView();
430
431  GLint returned;
432  returned = glRenderMode (GL_RENDER);
433 
434  FILE* file;
435  if (!fPrintFilename.empty()) {
436    file = fopen (fPrintFilename.c_str(), "w");
437    if (file) {
438      spewWireframeEPS (file, returned, feedback_buffer, "rendereps");
439      fclose(file);
440    } else {
441      printf("Could not open %s\n", fPrintFilename.c_str());
442    }
443  } else {
444    printBuffer (returned, feedback_buffer);
445  }
446
447  delete[] feedback_buffer;
448}
449
450void G4OpenGLViewer::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer)
451{
452  G4int i;
453
454  printf("  ");
455  for (i = 0; i < 7; i++) {
456    printf("%4.2f ", buffer[size - (*count)]);
457    *count = *count - 1;
458  }
459  printf("\n");
460}
461
462void G4OpenGLViewer::spewWireframeEPS (FILE* file, GLint size, GLfloat* buffer, const char* cr) {
463
464  GLfloat EPS_GOURAUD_THRESHOLD=0.1;
465
466  GLfloat clearColor[4], viewport[4];
467  GLfloat lineWidth;
468  G4int i;
469
470  glGetFloatv (GL_VIEWPORT, viewport);
471  glGetFloatv (GL_COLOR_CLEAR_VALUE, clearColor);
472  glGetFloatv (GL_LINE_WIDTH, &lineWidth);
473  glGetFloatv (GL_POINT_SIZE, &fPointSize);
474
475  fputs ("%!PS-Adobe-2.0 EPSF-2.0\n", file);
476  fprintf (file, "%%%%Creator: %s (using OpenGL feedback)\n", cr);
477  fprintf (file, "%%%%BoundingBox: %g %g %g %g\n", viewport[0], viewport[1], viewport[2], viewport[3]);
478  fputs ("%%EndComments\n", file);
479  fputs ("\n", file);
480  fputs ("gsave\n", file);
481  fputs ("\n", file);
482
483  fputs ("% the gouraudtriangle PostScript fragment below is free\n", file);
484  fputs ("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file);
485  fprintf (file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD);
486  for (i=0; gouraudtriangleEPS[i]; i++) {
487    fprintf (file, "%s\n", gouraudtriangleEPS[i]);
488  }
489
490  fprintf(file, "\n%g setlinewidth\n", lineWidth);
491 
492  fprintf (file, "%g %g %g setrgbcolor\n", clearColor[0], clearColor[1], clearColor[2]);
493  fprintf (file, "%g %g %g %g rectfill\n\n", viewport[0], viewport[1], viewport[2], viewport[3]);
494
495  spewSortedFeedback (file, size, buffer);
496
497  fputs ("grestore\n\n", file);
498  fputs ("showpage\n", file);
499
500  fclose(file);
501}
502
503void G4OpenGLViewer::printBuffer (GLint size, GLfloat* buffer) {
504
505  GLint count;
506  G4int token, nvertices;
507
508  count=size;
509  while(count) {
510    token=G4int (buffer[size-count]);
511    count--;
512    switch (token) {
513
514    case GL_PASS_THROUGH_TOKEN:
515      printf ("GL_PASS_THROUGH_TOKEN\n");
516      printf ("  %4.2f\n", buffer[size-count]);
517      count--;
518      break;
519
520    case GL_POINT_TOKEN:
521      printf ("GL_POINT_TOKEN\n");
522      print3DcolorVertex (size, &count, buffer);
523      break;
524
525    case GL_LINE_TOKEN:
526      printf ("GL_LINE_TOKEN\n");
527      print3DcolorVertex (size, &count, buffer);
528      print3DcolorVertex (size, &count, buffer);
529      break;
530     
531    case GL_LINE_RESET_TOKEN:
532      printf ("GL_LINE_RESET_TOKEN\n");
533      print3DcolorVertex (size, &count, buffer);
534      print3DcolorVertex (size, &count, buffer);
535      break;
536
537    case GL_POLYGON_TOKEN:
538      printf ("GL_POLYGON_TOKEN\n");
539      nvertices=G4int (buffer[size-count]);
540      count--;
541      for (; nvertices>0; nvertices--) {
542        print3DcolorVertex (size, &count, buffer);
543      }
544    }
545  }
546}
547
548G4float* G4OpenGLViewer::spewPrimitiveEPS (FILE* file, GLfloat* loc) {
549 
550  G4int token;
551  G4int nvertices, i;
552  GLfloat red, green, blue, intensity;
553  G4int smooth;
554  GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax;
555  G4int steps;
556  Feedback3Dcolor *vertex;
557  GLfloat xstep(0.), ystep(0.), rstep(0.), gstep(0.), bstep(0.);
558  GLfloat xnext(0.), ynext(0.), rnext(0.), gnext(0.), bnext(0.), distance(0.);
559
560  token=G4int (*loc);
561  loc++;
562  switch (token) {
563  case GL_LINE_RESET_TOKEN:
564  case GL_LINE_TOKEN:
565    vertex=(Feedback3Dcolor*)loc;
566    dr=vertex[1].red - vertex[0].red;
567    dg=vertex[1].green - vertex[0].green;
568    db=vertex[1].blue - vertex[0].blue;
569
570    if (!fPrintColour) {
571      dr+=(dg+db);
572      dr/=3.0;
573      dg=dr;
574      db=dr;
575    }
576
577    if (dr!=0 || dg!=0 || db!=0) {
578      dx=vertex[1].x - vertex[0].x;
579      dy=vertex[1].y - vertex[0].y;
580      distance=std::sqrt(dx*dx + dy*dy);
581
582      absR=std::fabs(dr);
583      absG=std::fabs(dg);
584      absB=std::fabs(db);
585
586      #define Max(a, b) (((a)>(b))?(a):(b))
587
588      #define EPS_SMOOTH_LINE_FACTOR 0.06
589
590      colormax=Max(absR, Max(absG, absB));
591      steps=Max(1, G4int (colormax*distance*EPS_SMOOTH_LINE_FACTOR));
592     
593      xstep=dx/steps;
594      ystep=dy/steps;
595
596      rstep=dr/steps;
597      gstep=dg/steps;
598      bstep=db/steps;
599
600      xnext=vertex[0].x;
601      ynext=vertex[0].y;
602      rnext=vertex[0].red;
603      gnext=vertex[0].green;
604      bnext=vertex[0].blue;
605
606      if (!fPrintColour) {
607        rnext+=(gnext+bnext);
608        rnext/=3.0;
609        gnext=rnext;
610        bnext=rnext;
611      }
612
613      xnext -= xstep/2.0;
614      ynext -= ystep/2.0;
615      rnext -= rstep/2.0;
616      gnext -= gstep/2.0;
617      bnext -= bstep/2.0;
618    } else {
619      steps=0;
620    }
621    if (fPrintColour) {
622      fprintf (file, "%g %g %g setrgbcolor\n",
623               vertex[0].red, vertex[0].green, vertex[0].blue);
624    } else {
625      intensity = (vertex[0].red + vertex[0].green + vertex[0].blue) / 3.0;
626      fprintf (file, "%g %g %g setrgbcolor\n",
627               intensity, intensity, intensity);
628    }     
629    fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
630
631    for (i=0; i<steps; i++) {
632
633      xnext += xstep;
634      ynext += ystep;
635      rnext += rstep;
636      gnext += gstep;
637      bnext += bstep;
638
639      fprintf (file, "%g %g lineto stroke\n", xnext, ynext);
640      fprintf (file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext);
641      fprintf (file, "%g %g moveto\n", xnext, ynext);
642    }
643    fprintf (file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y);
644
645    loc += 14;
646    break;
647
648  case GL_POLYGON_TOKEN:
649    nvertices = G4int (*loc);
650    loc++;
651    vertex=(Feedback3Dcolor*)loc;
652    if (nvertices>0) {
653      red=vertex[0].red;
654      green=vertex[0].green;
655      blue=vertex[0].blue;
656      smooth=0;
657     
658      if (!fPrintColour) {
659        red+=(green+blue);
660        red/=3.0;
661        green=red;
662        blue=red;
663      }
664     
665      if (fPrintColour) {
666        for (i=1; i<nvertices; i++) {
667          if (red!=vertex[i].red || green!=vertex[i].green || blue!=vertex[i].blue) {
668            smooth=1;
669            break;
670          }
671        }
672      } else {
673        for (i=1; i<nvertices; i++) {
674          intensity = vertex[i].red + vertex[i].green + vertex[i].blue;
675          intensity/=3.0;
676          if (red!=intensity) {
677            smooth=1;
678            break;
679          }
680        }
681      }
682
683      if (smooth) {
684        G4int triOffset;
685        for (i=0; i<nvertices-2; i++) {
686          triOffset = i*7;
687          fprintf (file, "[%g %g %g %g %g %g]",
688                   vertex[0].x, vertex[i+1].x, vertex[i+2].x,
689                   vertex[0].y, vertex[i+1].y, vertex[i+2].y);
690          if (fPrintColour) {
691            fprintf (file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n",
692                     vertex[0].red, vertex[0].green, vertex[0].blue,
693                     vertex[i+1].red, vertex[i+1].green, vertex[i+1].blue,
694                     vertex[i+2].red, vertex[i+2].green, vertex[i+2].blue);
695          } else {
696
697            intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
698            intensity/=3.0;
699            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
700
701            intensity = vertex[1].red + vertex[1].green + vertex[1].blue;
702            intensity/=3.0;
703            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
704
705            intensity = vertex[2].red + vertex[2].green + vertex[2].blue;
706            intensity/=3.0;
707            fprintf (file, " [%g %g %g] gouraudtriangle\n", intensity, intensity, intensity);
708          }
709        }
710      } else {
711        fprintf (file, "newpath\n");
712        fprintf (file, "%g %g %g setrgbcolor\n", red, green, blue);
713        fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
714        for (i=1; i<nvertices; i++) {
715          fprintf (file, "%g %g lineto\n", vertex[i].x, vertex[i].y);
716        }
717        fprintf (file, "closepath fill\n\n");
718      }
719    }
720    loc += nvertices*7;
721    break;
722
723  case GL_POINT_TOKEN:
724    vertex=(Feedback3Dcolor*)loc;
725    if (fPrintColour) {
726      fprintf (file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue);
727    } else {
728      intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
729      intensity/=3.0;
730      fprintf (file, "%g %g %g setrgbcolor\n", intensity, intensity, intensity);
731    }     
732    fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, fPointSize / 2.0);
733    loc += 7;           /* Each vertex element in the feedback
734                           buffer is 7 GLfloats. */
735    break;
736  default:
737    /* XXX Left as an excersie to the reader. */
738    static G4bool spewPrimitiveEPSWarned = false;
739    if (!spewPrimitiveEPSWarned) {
740      std::ostringstream oss;
741      oss <<
742        "Incomplete implementation.  Unexpected token (" << token << ")."
743        "\n  (Seems to be caused by text.)";
744      G4Exception("G4OpenGLViewer::spewPrimitiveEPS",
745                  "Unexpected token",
746                  JustWarning,
747                  oss.str().c_str());
748      spewPrimitiveEPSWarned = true;
749    }
750  }
751  return loc;
752}
753
754typedef struct G4OpenGLViewerDepthIndex {
755  GLfloat *ptr;
756  GLfloat depth;
757} DepthIndex;
758
759extern "C" {
760  int G4OpenGLViewercompare(const void *a, const void *b)
761  {
762    const DepthIndex *p1 = (DepthIndex *) a;
763    const DepthIndex *p2 = (DepthIndex *) b;
764    GLfloat diff = p2->depth - p1->depth;
765   
766    if (diff > 0.0) {
767      return 1;
768    } else if (diff < 0.0) {
769      return -1;
770    } else {
771      return 0;
772    }
773  }
774}
775
776GLubyte* G4OpenGLViewer::grabPixels (int inColor, unsigned int width, unsigned int height) {
777 
778  GLubyte* buffer;
779  GLint swapbytes, lsbfirst, rowlength;
780  GLint skiprows, skippixels, alignment;
781  GLenum format;
782  int size;
783
784  if (inColor) {
785    format = GL_RGB;
786    size = width*height*3;
787  } else {
788    format = GL_LUMINANCE;
789    size = width*height*1;
790  }
791
792  buffer = new GLubyte[size];
793  if (buffer == NULL)
794    return NULL;
795
796  glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
797  glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
798  glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
799
800  glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
801  glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
802  glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
803
804  glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
805  glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
806  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
807
808  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
809  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
810  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
811
812  glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
813
814  glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
815  glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
816  glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
817 
818  glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
819  glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
820  glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
821 
822  return buffer;
823}
824
825int G4OpenGLViewer::generateEPS (const char* filnam,
826                                int inColour,
827                                unsigned int width,
828                                unsigned int height) {
829
830  FILE* fp;
831  GLubyte* pixels;
832  GLubyte* curpix;
833  int components, pos, i;
834
835  WritePostScript("AAAAAAAAAAAAAAA.ps");
836
837  pixels = grabPixels (inColour, width, height);
838
839  if (pixels == NULL)
840    return 1;
841  if (inColour) {
842    components = 3;
843  } else {
844    components = 1;
845  }
846 
847  fp = fopen (filnam, "w");
848  if (fp == NULL) {
849    return 2;
850  }
851 
852  fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
853  fprintf (fp, "%%%%Title: %s\n", filnam);
854  fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
855  fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
856  fprintf (fp, "%%%%EndComments\n");
857  fprintf (fp, "gsave\n");
858  fprintf (fp, "/bwproc {\n");
859  fprintf (fp, "    rgbproc\n");
860  fprintf (fp, "    dup length 3 idiv string 0 3 0 \n");
861  fprintf (fp, "    5 -1 roll {\n");
862  fprintf (fp, "    add 2 1 roll 1 sub dup 0 eq\n");
863  fprintf (fp, "    { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
864  fprintf (fp, "       3 1 roll 5 -1 roll } put 1 add 3 0 \n");
865  fprintf (fp, "    { 2 1 roll } ifelse\n");
866  fprintf (fp, "    }forall\n");
867  fprintf (fp, "    pop pop pop\n");
868  fprintf (fp, "} def\n");
869  fprintf (fp, "systemdict /colorimage known not {\n");
870  fprintf (fp, "   /colorimage {\n");
871  fprintf (fp, "       pop\n");
872  fprintf (fp, "       pop\n");
873  fprintf (fp, "       /rgbproc exch def\n");
874  fprintf (fp, "       { bwproc } image\n");
875  fprintf (fp, "   }  def\n");
876  fprintf (fp, "} if\n");
877  fprintf (fp, "/picstr %d string def\n", width * components);
878  fprintf (fp, "%d %d scale\n", width, height);
879  fprintf (fp, "%d %d %d\n", width, height, 8);
880  fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height);
881  fprintf (fp, "{currentfile picstr readhexstring pop}\n");
882  fprintf (fp, "false %d\n", components);
883  fprintf (fp, "colorimage\n");
884 
885  curpix = (GLubyte*) pixels;
886  pos = 0;
887  for (i = width*height*components; i>0; i--) {
888    fprintf (fp, "%02hx ", *(curpix++));
889    if (++pos >= 32) {
890      fprintf (fp, "\n");
891      pos = 0;
892    }
893  }
894  if (pos)
895    fprintf (fp, "\n");
896
897  fprintf (fp, "grestore\n");
898  fprintf (fp, "showpage\n");
899  delete pixels;
900  fclose (fp);
901  return 0;
902}
903
904
905void G4OpenGLViewer::WritePostScript(const char *aFile) {
906
907
908  if (!fGL2PSAction) return;
909
910  // FIXME : TEST
911  printf("G4OpenGLViewer::WritePostScript world size:%f\n",GetViewParameters().GetDefaultMarker().GetWorldSize());
912  G4ViewParameters vp = GetViewParameters(); 
913  G4VMarker defaultMarker = vp.GetDefaultMarker();
914  G4VMarker myMarker = vp.GetDefaultMarker();
915
916  myMarker.SetScreenSize(0); // before SetWorldSize
917  myMarker.SetScreenDiameter(0); // before SetWorldSize
918  myMarker.SetScreenRadius(0); // before SetWorldSize
919
920  myMarker.SetWorldSize(6.);
921  myMarker.SetWorldDiameter(4.);
922  myMarker.SetWorldRadius(3.);
923//   myMarker.SetWorldSize(defaultMarker.GetScreenSize());
924//   myMarker.SetWorldDiameter(defaultMarker.GetScreenDiameter());
925//   myMarker.SetWorldRadius(defaultMarker.GetScreenRadius());
926
927  vp.SetDefaultMarker(myMarker);
928  SetViewParameters(vp);
929
930  fGL2PSAction->setFileName("PostScriptViaGL2PS.ps");
931  if (fGL2PSAction->enableFileWriting()) {
932    NeedKernelVisit ();
933    ProcessView();
934    SetView ();
935    ClearView ();
936    DrawView ();
937    fGL2PSAction->disableFileWriting();
938  }
939  vp.SetDefaultMarker(defaultMarker);
940  SetViewParameters(vp);
941  // FIXME : TEST
942
943
944
945  FILE *fFile = fopen(aFile,"w");
946  if(!fFile) {
947    G4cout << "G4OpenGLViewer::WritePostScript. Cannot open file " <<aFile << G4endl;
948    return;
949  }
950 
951  // Get the viewport
952  GLint viewport[4];
953  glGetIntegerv(GL_VIEWPORT, viewport);
954
955
956
957  int psformat;
958  //  psformat = GL2PS_PDF;
959  psformat = GL2PS_PS;
960  //  psformat = GL2PS_SVG;
961  //  psformat = GL2PS_EPS;
962 
963  //  int old_bg_gradient = CTX.bg_gradient;
964  //  if(!CTX.print.eps_background) CTX.bg_gradient = 0;
965 
966//   PixelBuffer buffer(width, height, GL_RGB, GL_FLOAT);
967 
968//   if(CTX.print.eps_quality == 0)
969//     buffer.Fill(CTX.batch);
970 
971  int pssort = GL2PS_SIMPLE_SORT;
972  //       int pssort =
973  //         (CTX.print.eps_quality == 3) ? GL2PS_NO_SORT :
974  //         (CTX.print.eps_quality == 2) ? GL2PS_BSP_SORT :
975  //         GL2PS_SIMPLE_SORT;
976  int psoptions = GL2PS_SIMPLE_LINE_OFFSET | GL2PS_DRAW_BACKGROUND;
977  //         GL2PS_SIMPLE_LINE_OFFSET | GL2PS_SILENT |
978  //         (CTX.print.eps_occlusion_culling ? GL2PS_OCCLUSION_CULL : 0) |
979  //         (CTX.print.eps_best_root ? GL2PS_BEST_ROOT : 0) |
980  //         (CTX.print.eps_background ? GL2PS_DRAW_BACKGROUND : 0) |
981  //         (CTX.print.eps_compress ? GL2PS_COMPRESS : 0) |
982  //         (CTX.print.eps_ps3shading ? 0 : GL2PS_NO_PS3_SHADING);
983 
984  GLint buffsize = 0;
985  int res = GL2PS_OVERFLOW;
986  while(res == GL2PS_OVERFLOW) {
987    buffsize += 2048 * 2048;
988    gl2psBeginPage("MyTitle", "Geant4", viewport,
989                   psformat, pssort, psoptions, GL_RGBA, 0, NULL,
990                   15, 20, 10, buffsize, fFile, aFile);
991    DrawView();
992    res = gl2psEndPage();
993  }
994 
995  //  CTX.bg_gradient = old_bg_gradient;
996  fclose(fFile);
997
998}
999
1000GLdouble G4OpenGLViewer::getSceneNearWidth()
1001{
1002  const G4Point3D targetPoint
1003    = fSceneHandler.GetScene()->GetStandardTargetPoint()
1004    + fVP.GetCurrentTargetPoint ();
1005  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1006  if(radius<=0.) radius = 1.;
1007  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1008  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
1009  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
1010}
1011
1012GLdouble G4OpenGLViewer::getSceneFarWidth()
1013{
1014  const G4Point3D targetPoint
1015    = fSceneHandler.GetScene()->GetStandardTargetPoint()
1016    + fVP.GetCurrentTargetPoint ();
1017  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1018  if(radius<=0.) radius = 1.;
1019  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1020  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
1021  const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
1022  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
1023}
1024
1025
1026GLdouble G4OpenGLViewer::getSceneDepth()
1027{
1028  const G4Point3D targetPoint
1029    = fSceneHandler.GetScene()->GetStandardTargetPoint()
1030    + fVP.GetCurrentTargetPoint ();
1031  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1032  if(radius<=0.) radius = 1.;
1033  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1034  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
1035  return fVP.GetFarDistance  (cameraDistance, pnear, radius)- pnear;
1036}
1037
1038
1039void G4OpenGLViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer)
1040{
1041  int token;
1042  GLfloat *loc, *end;
1043  Feedback3Dcolor *vertex;
1044  GLfloat depthSum;
1045  int nprimitives, item;
1046  DepthIndex *prims;
1047  int nvertices, i;
1048
1049  end = buffer + size;
1050
1051  /* Count how many primitives there are. */
1052  nprimitives = 0;
1053  loc = buffer;
1054  while (loc < end) {
1055    token = int (*loc);
1056    loc++;
1057    switch (token) {
1058    case GL_LINE_TOKEN:
1059    case GL_LINE_RESET_TOKEN:
1060      loc += 14;
1061      nprimitives++;
1062      break;
1063    case GL_POLYGON_TOKEN:
1064      nvertices = int (*loc);
1065      loc++;
1066      loc += (7 * nvertices);
1067      nprimitives++;
1068      break;
1069    case GL_POINT_TOKEN:
1070      loc += 7;
1071      nprimitives++;
1072      break;
1073    default:
1074      /* XXX Left as an excersie to the reader. */
1075      static G4bool spewSortedFeedbackWarned = false;
1076      if (!spewSortedFeedbackWarned) {
1077        std::ostringstream oss;
1078        oss <<
1079          "Incomplete implementation.  Unexpected token (" << token << ")."
1080          "\n  (Seems to be caused by text.)";
1081        G4Exception("G4OpenGLViewer::spewSortedFeedback",
1082                    "Unexpected token",
1083                    JustWarning,
1084                    oss.str().c_str());
1085        spewSortedFeedbackWarned = true;
1086      }
1087      nprimitives++;
1088    }
1089  }
1090
1091  /* Allocate an array of pointers that will point back at
1092     primitives in the feedback buffer.  There will be one
1093     entry per primitive.  This array is also where we keep the
1094     primitive's average depth.  There is one entry per
1095     primitive  in the feedback buffer. */
1096  prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives);
1097
1098  item = 0;
1099  loc = buffer;
1100  while (loc < end) {
1101    prims[item].ptr = loc;  /* Save this primitive's location. */
1102    token = int (*loc);
1103    loc++;
1104    switch (token) {
1105    case GL_LINE_TOKEN:
1106    case GL_LINE_RESET_TOKEN:
1107      vertex = (Feedback3Dcolor *) loc;
1108      depthSum = vertex[0].z + vertex[1].z;
1109      prims[item].depth = depthSum / 2.0;
1110      loc += 14;
1111      break;
1112    case GL_POLYGON_TOKEN:
1113      nvertices = int (*loc);
1114      loc++;
1115      vertex = (Feedback3Dcolor *) loc;
1116      depthSum = vertex[0].z;
1117      for (i = 1; i < nvertices; i++) {
1118        depthSum += vertex[i].z;
1119      }
1120      prims[item].depth = depthSum / nvertices;
1121      loc += (7 * nvertices);
1122      break;
1123    case GL_POINT_TOKEN:
1124      vertex = (Feedback3Dcolor *) loc;
1125      prims[item].depth = vertex[0].z;
1126      loc += 7;
1127      break;
1128    default:
1129      /* XXX Left as an excersie to the reader. */
1130      assert(1);
1131    }
1132    item++;
1133  }
1134  assert(item == nprimitives);
1135
1136  /* Sort the primitives back to front. */
1137  qsort(prims, nprimitives, sizeof(DepthIndex), G4OpenGLViewercompare);
1138
1139  /* Understand that sorting by a primitives average depth
1140     doesn't allow us to disambiguate some cases like self
1141     intersecting polygons.  Handling these cases would require
1142     breaking up the primitives.  That's too involved for this
1143     example.  Sorting by depth is good enough for lots of
1144     applications. */
1145
1146  /* Emit the Encapsulated PostScript for the primitives in
1147     back to front order. */
1148  for (item = 0; item < nprimitives; item++) {
1149    (void) spewPrimitiveEPS(file, prims[item].ptr);
1150  }
1151
1152  free(prims);
1153}
1154
1155void G4OpenGLViewer::rotateScene(G4double dx, G4double dy,G4double deltaRotation)
1156{
1157
1158  G4Vector3D vp;
1159  G4Vector3D up;
1160 
1161  G4Vector3D xprime;
1162  G4Vector3D yprime;
1163  G4Vector3D zprime;
1164 
1165  G4double delta_alpha;
1166  G4double delta_theta;
1167 
1168  G4Vector3D new_vp;
1169  G4Vector3D new_up;
1170 
1171  G4double cosalpha;
1172  G4double sinalpha;
1173 
1174  G4Vector3D a1;
1175  G4Vector3D a2;
1176  G4Vector3D delta;
1177  G4Vector3D viewPoint;
1178
1179   
1180  //phi spin stuff here
1181 
1182  vp = fVP.GetViewpointDirection ().unit ();
1183  up = fVP.GetUpVector ().unit ();
1184 
1185  yprime = (up.cross(vp)).unit();
1186  zprime = (vp.cross(yprime)).unit();
1187 
1188  if (fVP.GetLightsMoveWithCamera()) {
1189    delta_alpha = dy * deltaRotation;
1190    delta_theta = -dx * deltaRotation;
1191  } else {
1192    delta_alpha = -dy * deltaRotation;
1193    delta_theta = dx * deltaRotation;
1194  }   
1195 
1196  delta_alpha *= deg;
1197  delta_theta *= deg;
1198 
1199  new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
1200 
1201  // to avoid z rotation flipping
1202  // to allow more than 360° rotation
1203
1204  const G4Point3D targetPoint
1205    = fSceneHandler.GetScene()->GetStandardTargetPoint()
1206    + fVP.GetCurrentTargetPoint ();
1207  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1208  if(radius<=0.) radius = 1.;
1209  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1210  const G4Point3D cameraPosition =
1211    targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
1212
1213  if (fVP.GetLightsMoveWithCamera()) {
1214    new_up = (new_vp.cross(yprime)).unit();
1215    if (new_vp.z()*vp.z() <0) {
1216      new_up.set(new_up.x(),-new_up.y(),new_up.z());
1217    }
1218  } else {
1219    new_up = up;
1220    if (new_vp.z()*vp.z() <0) {
1221      new_up.set(new_up.x(),-new_up.y(),new_up.z());
1222    }
1223  }
1224  fVP.SetUpVector(new_up);
1225  ////////////////
1226  // Rotates by fixed azimuthal angle delta_theta.
1227 
1228  cosalpha = new_up.dot (new_vp.unit());
1229  sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
1230  yprime = (new_up.cross (new_vp.unit())).unit ();
1231  xprime = yprime.cross (new_up);
1232  // Projection of vp on plane perpendicular to up...
1233  a1 = sinalpha * xprime;
1234  // Required new projection...
1235  a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
1236  // Required Increment vector...
1237  delta = a2 - a1;
1238  // So new viewpoint is...
1239  viewPoint = new_vp.unit() + delta;
1240 
1241  fVP.SetViewAndLights (viewPoint);
1242}
1243
1244#endif
Note: See TracBrowser for help on using the repository browser.