Geant4  10.01.p03
G4OpenGLViewer.cc
Go to the documentation of this file.
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 87443 2014-12-04 12:26:31Z gunter $
28 //
29 //
30 // Andrew Walkden 27th March 1996
31 // OpenGL view - opens window, hard copy, etc.
32 
33 #ifdef G4VIS_BUILD_OPENGL_DRIVER
34 
35 #include "G4ios.hh"
36 #include "G4SystemOfUnits.hh"
37 #include "G4OpenGLViewer.hh"
38 #include "G4OpenGLSceneHandler.hh"
39 #include "G4OpenGLTransform3D.hh"
40 #include "G4OpenGL2PSAction.hh"
41 
42 #include "G4Scene.hh"
43 #include "G4VisExtent.hh"
44 #include "G4LogicalVolume.hh"
45 #include "G4VSolid.hh"
46 #include "G4Point3D.hh"
47 #include "G4Normal3D.hh"
48 #include "G4Plane3D.hh"
49 #include "G4AttHolder.hh"
50 #include "G4AttCheck.hh"
51 #include "G4Text.hh"
52 
53 #ifdef G4OPENGL_VERSION_2
54 // We need to have a Wt gl drawer because we will draw inside the WtGL component (ImmediateWtViewer)
55 #include "G4OpenGLVboDrawer.hh"
56 #endif
57 
58 // GL2PS
59 #include "Geant4_gl2ps.h"
60 
61 #include <sstream>
62 #include <string>
63 
64 //#define G4DEBUG_VIS_OGL 1
65 
66 G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
67 G4VViewer (scene, -1),
68 #ifdef G4OPENGL_VERSION_2
69 fVboDrawer(NULL),
70 #endif
71 fPrintColour (true),
72 fVectoredPs (true),
73 fOpenGLSceneHandler(scene),
74 background (G4Colour(0.,0.,0.)),
75 transparency_enabled (true),
76 antialiasing_enabled (false),
77 haloing_enabled (false),
78 fStartTime(-DBL_MAX),
79 fEndTime(DBL_MAX),
80 fFadeFactor(0.),
81 fDisplayHeadTime(false),
82 fDisplayHeadTimeX(-0.9),
83 fDisplayHeadTimeY(-0.9),
84 fDisplayHeadTimeSize(24.),
85 fDisplayHeadTimeRed(0.),
86 fDisplayHeadTimeGreen(1.),
87 fDisplayHeadTimeBlue(1.),
88 fDisplayLightFront(false),
89 fDisplayLightFrontX(0.),
90 fDisplayLightFrontY(0.),
91 fDisplayLightFrontZ(0.),
92 fDisplayLightFrontT(0.),
93 fDisplayLightFrontRed(0.),
94 fDisplayLightFrontGreen(1.),
95 fDisplayLightFrontBlue(0.),
96 fRot_sens(1.),
97 fPan_sens(0.01),
98 fWinSize_x(0),
99 fWinSize_y(0),
100 fDefaultExportImageFormat("pdf"),
101 fExportImageFormat("pdf"),
102 fExportFilenameIndex(0),
103 fPrintSizeX(-1),
104 fPrintSizeY(-1),
105 fPointSize (0),
106 fDefaultExportFilename("G4OpenGL"),
107 fSizeHasChanged(0),
108 fGl2psDefaultLineWith(1),
109 fGl2psDefaultPointSize(2),
110 fGlViewInitialized(false),
111 fIsGettingPickInfos(false)
112 #ifdef G4OPENGL_VERSION_2
113 ,fShaderProgram(0)
114 ,fVertexPositionAttribute(0)
115 ,fVertexNormalAttribute(0)
116 ,fpMatrixUniform(0)
117 ,fcMatrixUniform(0)
118 ,fmvMatrixUniform(0)
119 ,fnMatrixUniform(0)
120 #endif
121 {
122 #ifdef G4DEBUG_VIS_OGL
123  printf("G4OpenGLViewer:: Creation\n");
124 #endif
125  // Make changes to view parameters for OpenGL...
126  fVP.SetAutoRefresh(true);
127  fDefaultVP.SetAutoRefresh(true);
128 
129  fGL2PSAction = new G4OpenGL2PSAction();
130 
131  // add supported export image format
132  addExportImageFormat("eps");
133  addExportImageFormat("ps");
134  addExportImageFormat("pdf");
135  addExportImageFormat("svg");
136 
137  // Change the default name
138  fExportFilename += fDefaultExportFilename + "_" + GetShortName().data();
139 
140  // glClearColor (0.0, 0.0, 0.0, 0.0);
141  // glClearDepth (1.0);
142  // glDisable (GL_BLEND);
143  // glDisable (GL_LINE_SMOOTH);
144  // glDisable (GL_POLYGON_SMOOTH);
145 
146 }
147 
148 G4OpenGLViewer::~G4OpenGLViewer ()
149 {
150  delete fGL2PSAction;
151 }
152 
153 void G4OpenGLViewer::InitializeGLView ()
154 {
155 #ifdef G4OPENGL_VERSION_2
156  if (fVboDrawer) {
157 
158  // First, load a simple shader
159  fShaderProgram = glCreateProgram();
160  Shader vertexShader = glCreateShader(GL_VERTEX_SHADER);
161  const char * vSrc = fVboDrawer->getVertexShaderSrc();
162  glShaderSource(vertexShader, 1, &vSrc, NULL);
163  glCompileShader(vertexShader);
164  glAttachShader(fShaderProgram, vertexShader);
165 
166  Shader fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
167  const char * fSrc = fVboDrawer->getFragmentShaderSrc();
168  glShaderSource(fragmentShader, 1, &fSrc, NULL);
169  glCompileShader(fragmentShader);
170 
171  glAttachShader(fShaderProgram, fragmentShader);
172  glLinkProgram(fShaderProgram);
173  glUseProgram(fShaderProgram);
174 
175  // UniformLocation uColor = getUniformLocation(fShaderProgram, "uColor");
176  // uniform4fv(uColor, [0.0, 0.3, 0.0, 1.0]);
177 
178  // Extract the references to the attributes from the shader.
179 
180  fVertexPositionAttribute =
181  glGetAttribLocation(fShaderProgram, "aVertexPosition");
182 
183 
184  glEnableVertexAttribArray(fVertexPositionAttribute);
185 
186  // Extract the references the uniforms from the shader
187  fpMatrixUniform = glGetUniformLocation(fShaderProgram, "uPMatrix");
188  fcMatrixUniform = glGetUniformLocation(fShaderProgram, "uCMatrix");
189  fmvMatrixUniform = glGetUniformLocation(fShaderProgram, "uMVMatrix");
190  fnMatrixUniform = glGetUniformLocation(fShaderProgram, "uNMatrix");
191  ftMatrixUniform = glGetUniformLocation(fShaderProgram, "uTMatrix");
192 
193  /* glUniformMatrix4fv(fcMatrixUniform, 1, 0, identity);
194  glUniformMatrix4fv(fpMatrixUniform, 1, 0, identity);
195  glUniformMatrix4fv(ftMatrixUniform, 1, 0, identity);
196  glUniformMatrix4fv(fmvMatrixUniform, 1, 0, identity);
197  */
198  // We have to set that in order to avoid calls on opengl commands before all is ready
199  fGlViewInitialized = true;
200  }
201 #endif
202 
203 #ifdef G4DEBUG_VIS_OGL
204  printf("G4OpenGLViewer::InitializeGLView\n");
205 #endif
206 
207  fWinSize_x = fVP.GetWindowSizeHintX();
208  fWinSize_y = fVP.GetWindowSizeHintY();
209 
210  glClearColor (0.0, 0.0, 0.0, 0.0);
211  glClearDepth (1.0);
212 #ifndef G4OPENGL_VERSION_2
213  glDisable (GL_LINE_SMOOTH);
214  glDisable (GL_POLYGON_SMOOTH);
215 #endif
216 
217 // clear the buffers and window?
218  ClearView ();
219  FinishView ();
220 
221  glDepthFunc (GL_LEQUAL);
222  glDepthMask (GL_TRUE);
223 
224  glEnable (GL_BLEND);
225  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
226 
227 #ifdef G4DEBUG_VIS_OGL
228  printf("G4OpenGLViewer::InitializeGLView END\n");
229 #endif
230 }
231 
232 void G4OpenGLViewer::ClearView () {
233  ClearViewWithoutFlush();
234  glFlush();
235 }
236 
237 
238 void G4OpenGLViewer::ClearViewWithoutFlush () {
239  // Ready for clear ?
240  // See : http://lists.apple.com/archives/mac-opengl/2012/Jul/msg00038.html
241 #if GL_EXT_framebuffer_object
242 // if ( glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNDEFINED) {
243 // return;
244 // }
245 #endif
246 
247  glClearColor (background.GetRed(),
248  background.GetGreen(),
249  background.GetBlue(),
250  1.);
251  glClearDepth (1.0);
252  //Below line does not compile with Mesa includes.
253  //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
254  glClear (GL_COLOR_BUFFER_BIT);
255  glClear (GL_DEPTH_BUFFER_BIT);
256  glClear (GL_STENCIL_BUFFER_BIT);
257 }
258 
259 
260 void G4OpenGLViewer::ResizeWindow(unsigned int aWidth, unsigned int aHeight) {
261  if ((fWinSize_x != aWidth) || (fWinSize_y != aHeight)) {
262  fWinSize_x = aWidth;
263  fWinSize_y = aHeight;
264  fSizeHasChanged = true;
265  } else {
266  fSizeHasChanged = false;
267  }
268 }
269 
276 void G4OpenGLViewer::ResizeGLView()
277 {
278 #ifdef G4DEBUG_VIS_OGL
279  printf("G4OpenGLViewer::ResizeGLView %d %d %#lx\n",fWinSize_x,fWinSize_y,(unsigned long)this);
280 #endif
281  // Check size
282  GLint dims[2];
283  dims[0] = 0;
284  dims[1] = 0;
285 
286  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
287 
288  if ((dims[0] !=0 ) && (dims[1] !=0)) {
289 
290  if (fWinSize_x > (unsigned)dims[0]) {
291  G4cerr << "Try to resize view greater than max X viewport dimension. Desired size "<<fWinSize_x <<" is resize to "<< dims[0] << G4endl;
292  fWinSize_x = dims[0];
293  }
294  if (fWinSize_y > (unsigned)dims[1]) {
295  G4cerr << "Try to resize view greater than max Y viewport dimension. Desired size "<<fWinSize_y <<" is resize to "<< dims[1] << G4endl;
296  fWinSize_y = dims[1];
297  }
298  }
299 
300  glViewport(0, 0, fWinSize_x,fWinSize_y);
301 
302 
303 }
304 
305 
306 void G4OpenGLViewer::SetView () {
307  // if getting pick infos, should not resize the view.
308  if (fIsGettingPickInfos) return;
309 
310  if (!fSceneHandler.GetScene()) {
311  return;
312  }
313  // Calculates view representation based on extent of object being
314  // viewed and (initial) viewpoint. (Note: it can change later due
315  // to user interaction via visualization system's GUI.)
316 
317  // Lighting.
318  GLfloat lightPosition [4];
319  lightPosition [0] = fVP.GetActualLightpointDirection().x();
320  lightPosition [1] = fVP.GetActualLightpointDirection().y();
321  lightPosition [2] = fVP.GetActualLightpointDirection().z();
322  lightPosition [3] = 0.;
323  // Light position is "true" light direction, so must come after gluLookAt.
324  GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
325  GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
326  glEnable (GL_LIGHT0);
327  glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
328  glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
329 
330  G4double ratioX = 1;
331  G4double ratioY = 1;
332  if (fWinSize_y > fWinSize_x) {
333  ratioX = ((G4double)fWinSize_y) / ((G4double)fWinSize_x);
334  }
335  if (fWinSize_x > fWinSize_y) {
336  ratioY = ((G4double)fWinSize_x) / ((G4double)fWinSize_y);
337  }
338 
339  // Get radius of scene, etc.
340  // Note that this procedure properly takes into account zoom, dolly and pan.
341  const G4Point3D targetPoint
342  = fSceneHandler.GetScene()->GetStandardTargetPoint()
343  + fVP.GetCurrentTargetPoint ();
344  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
345  if(radius<=0.) radius = 1.;
346  const G4double cameraDistance = fVP.GetCameraDistance (radius);
347  const G4Point3D cameraPosition =
348  targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
349  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
350  const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
351  const GLdouble right = fVP.GetFrontHalfHeight (pnear, radius) * ratioY;
352  const GLdouble left = -right;
353  const GLdouble top = fVP.GetFrontHalfHeight (pnear, radius) * ratioX;
354  const GLdouble bottom = -top;
355 
356  // FIXME
357  ResizeGLView();
358  //SHOULD SetWindowsSizeHint()...
359 
360  glMatrixMode (GL_PROJECTION); // set up Frustum.
361  glLoadIdentity();
362 
363  const G4Vector3D scaleFactor = fVP.GetScaleFactor();
364  glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
365 
366  if (fVP.GetFieldHalfAngle() == 0.) {
367  glOrtho (left, right, bottom, top, pnear, pfar);
368  }
369  else {
370  glFrustum (left, right, bottom, top, pnear, pfar);
371  }
372 
373  glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
374  glLoadIdentity();
375 
376  const G4Normal3D& upVector = fVP.GetUpVector ();
377  G4Point3D gltarget;
378  if (cameraDistance > 1.e-6 * radius) {
379  gltarget = targetPoint;
380  }
381  else {
382  gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
383  }
384 
385  const G4Point3D& pCamera = cameraPosition; // An alias for brevity.
386 
387  g4GluLookAt (pCamera.x(), pCamera.y(), pCamera.z(), // Viewpoint.
388  gltarget.x(), gltarget.y(), gltarget.z(), // Target point.
389  upVector.x(), upVector.y(), upVector.z()); // Up vector.
390  // Light position is "true" light direction, so must come after gluLookAt.
391  glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
392 
393  // OpenGL no longer seems to reconstruct clipped edges, so, when the
394  // BooleanProcessor is up to it, abandon this and use generic
395  // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron. Also,
396  // force kernel visit on change of clipping plane in
397  // G4OpenGLStoredViewer::CompareForKernelVisit.
398  //if (fVP.IsSection () ) { // pair of back to back clip planes.
399  if (false) { // pair of back to back clip planes.
400  const G4Plane3D& sp = fVP.GetSectionPlane ();
401  double sArray[4];
402  sArray[0] = sp.a();
403  sArray[1] = sp.b();
404  sArray[2] = sp.c();
405  sArray[3] = sp.d() + radius * 1.e-05;
406  glClipPlane (GL_CLIP_PLANE0, sArray);
407  glEnable (GL_CLIP_PLANE0);
408  sArray[0] = -sp.a();
409  sArray[1] = -sp.b();
410  sArray[2] = -sp.c();
411  sArray[3] = -sp.d() + radius * 1.e-05;
412  glClipPlane (GL_CLIP_PLANE1, sArray);
413  glEnable (GL_CLIP_PLANE1);
414  } else {
415  glDisable (GL_CLIP_PLANE0);
416  glDisable (GL_CLIP_PLANE1);
417  }
418 
419  // What we call intersection of cutaways is easy in OpenGL. You
420  // just keep cutting. Unions are more tricky - you have to have
421  // multiple passes and this is handled in
422  // G4OpenGLImmediate/StoredViewer::ProcessView.
423  const G4Planes& cutaways = fVP.GetCutawayPlanes();
424  size_t nPlanes = cutaways.size();
425  if (fVP.IsCutaway() &&
426  fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
427  nPlanes > 0) {
428  double a[4];
429  a[0] = cutaways[0].a();
430  a[1] = cutaways[0].b();
431  a[2] = cutaways[0].c();
432  a[3] = cutaways[0].d();
433  glClipPlane (GL_CLIP_PLANE2, a);
434  glEnable (GL_CLIP_PLANE2);
435  if (nPlanes > 1) {
436  a[0] = cutaways[1].a();
437  a[1] = cutaways[1].b();
438  a[2] = cutaways[1].c();
439  a[3] = cutaways[1].d();
440  glClipPlane (GL_CLIP_PLANE3, a);
441  glEnable (GL_CLIP_PLANE3);
442  }
443  if (nPlanes > 2) {
444  a[0] = cutaways[2].a();
445  a[1] = cutaways[2].b();
446  a[2] = cutaways[2].c();
447  a[3] = cutaways[2].d();
448  glClipPlane (GL_CLIP_PLANE4, a);
449  glEnable (GL_CLIP_PLANE4);
450  }
451  } else {
452  glDisable (GL_CLIP_PLANE2);
453  glDisable (GL_CLIP_PLANE3);
454  glDisable (GL_CLIP_PLANE4);
455  }
456 
457  // Background.
458  background = fVP.GetBackgroundColour ();
459 
460 }
461 
462 
463 
464 void G4OpenGLViewer::ResetView () {
466  fRot_sens = 1;
467  fPan_sens = 0.01;
468 }
469 
470 
471 void G4OpenGLViewer::HaloingFirstPass () {
472 
473  //To perform haloing, first Draw all information to the depth buffer
474  //alone, using a chunky line width, and then Draw all info again, to
475  //the colour buffer, setting a thinner line width an the depth testing
476  //function to less than or equal, so if two lines cross, the one
477  //passing behind the other will not pass the depth test, and so not
478  //get rendered either side of the infront line for a short distance.
479 
480  //First, disable writing to the colo(u)r buffer...
481  glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
482 
483  //Now enable writing to the depth buffer...
484  glDepthMask (GL_TRUE);
485  glDepthFunc (GL_LESS);
486  glClearDepth (1.0);
487 
488  //Finally, set the line width to something wide...
489  ChangeLineWidth(3.0);
490 
491 }
492 
493 void G4OpenGLViewer::HaloingSecondPass () {
494 
495  //And finally, turn the colour buffer back on with a sesible line width...
496  glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
497  glDepthFunc (GL_LEQUAL);
498  ChangeLineWidth(1.0);
499 
500 }
501 
502 G4String G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
503 {
504  std::vector < G4OpenGLViewerPickMap* > pickMap = GetPickDetails(x,y);
505  G4String txt = "";
506  if (pickMap.size() == 0) {
507  txt += "Too many hits. Zoom in to reduce overlaps.";;
508  } else {
509  for (unsigned int a=0; a< pickMap.size(); a++) {
510  txt += pickMap[a]->print();
511  }
512  }
513  return txt;
514 }
515 
516 std::vector < G4OpenGLViewerPickMap* > G4OpenGLViewer::GetPickDetails(GLdouble x, GLdouble y)
517 {
518  std::vector < G4OpenGLViewerPickMap* > pickMapVector;
519 
520  std::ostringstream oss;
521  const G4int BUFSIZE = 512;
522  GLuint selectBuffer[BUFSIZE];
523  glSelectBuffer(BUFSIZE, selectBuffer);
524  glRenderMode(GL_SELECT);
525  glInitNames();
526  glPushName(0);
527  glMatrixMode(GL_PROJECTION);
528  G4double currentProjectionMatrix[16];
529  glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
530  glPushMatrix();
531  glLoadIdentity();
532  GLint viewport[4];
533  glGetIntegerv(GL_VIEWPORT, viewport);
534  fIsGettingPickInfos = true;
535  // Define 5x5 pixel pick area
536  g4GluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
537  glMultMatrixd(currentProjectionMatrix);
538  glMatrixMode(GL_MODELVIEW);
539  DrawView();
540  GLint hits = glRenderMode(GL_RENDER);
541  fIsGettingPickInfos = false;
542  if (hits > 0) {
543 
544  GLuint* p = selectBuffer;
545  for (GLint i = 0; i < hits; ++i) {
546  G4OpenGLViewerPickMap* pickMap = new G4OpenGLViewerPickMap();
547  GLuint nnames = *p++;
548  // This bit of debug code or...
549  //GLuint zmin = *p++;
550  //GLuint zmax = *p++;
551  //G4cout << "Hit " << i << ": " << nnames << " names"
552  // << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
553  // ...just increment the pointer
554  p++;
555  p++;
556  for (GLuint j = 0; j < nnames; ++j) {
557  GLuint name = *p++;
558  pickMap->setHitNumber(i);
559  pickMap->setSubHitNumber(j);
560  pickMap->setPickName(name);
561  std::map<GLuint, G4AttHolder*>::iterator iter =
562  fOpenGLSceneHandler.fPickMap.find(name);
563  if (iter != fOpenGLSceneHandler.fPickMap.end()) {
564  G4AttHolder* attHolder = iter->second;
565  if(attHolder && attHolder->GetAttDefs().size()) {
566  for (size_t iAtt = 0;
567  iAtt < attHolder->GetAttDefs().size(); ++iAtt) {
568  oss << G4AttCheck(attHolder->GetAttValues()[iAtt],
569  attHolder->GetAttDefs()[iAtt]);
570  pickMap->addAttributes(oss.str());
571  }
572  }
573  }
574  }
575  pickMapVector.push_back(pickMap);
576  }
577  }
578  glMatrixMode(GL_PROJECTION);
579  glPopMatrix();
580  glMatrixMode(GL_MODELVIEW);
581  return pickMapVector;
582 }
583 
584 GLubyte* G4OpenGLViewer::grabPixels
585 (int inColor, unsigned int width, unsigned int height) {
586 
587  GLubyte* buffer;
588  GLint swapbytes, lsbfirst, rowlength;
589  GLint skiprows, skippixels, alignment;
590  GLenum format;
591  int size;
592 
593  if (inColor) {
594  format = GL_RGB;
595  size = width*height*3;
596  } else {
597  format = GL_LUMINANCE;
598  size = width*height*1;
599  }
600 
601  buffer = new GLubyte[size];
602  if (buffer == NULL)
603  return NULL;
604 
605  glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
606  glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
607  glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
608 
609  glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
610  glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
611  glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
612 
613  glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
614  glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
615  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
616 
617  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
618  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
619  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
620 
621  glReadBuffer(GL_FRONT);
622  glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
623 
624  glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
625  glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
626  glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
627 
628  glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
629  glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
630  glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
631 
632  return buffer;
633 }
634 
635 bool G4OpenGLViewer::printEPS() {
636  bool res;
637 #ifdef G4DEBUG_VIS_OGL
638  printf("G4OpenGLViewer::printEPS file:%s Vec:%d Name:%s\n",getRealPrintFilename().c_str(),fVectoredPs,GetName().c_str());
639 #endif
640 
641  // Change the LC_NUMERIC value in order to have "." separtor and not ","
642  // This case is only useful for French, Canadien...
643  size_t len = strlen(setlocale(LC_NUMERIC,NULL));
644  char* oldLocale = (char*)(malloc(len+1));
645  if(oldLocale!=NULL) strncpy(oldLocale,setlocale(LC_NUMERIC,NULL),len);
646  setlocale(LC_NUMERIC,"C");
647 
648  if (((fExportImageFormat == "eps") || (fExportImageFormat == "ps")) && (!fVectoredPs)) {
649  res = printNonVectoredEPS();
650  } else {
651  res = printVectoredEPS();
652  }
653 
654  // restore the local
655  if (oldLocale) {
656  setlocale(LC_NUMERIC,oldLocale);
657  free(oldLocale);
658  }
659 
660  if (res == false) {
661  G4cerr << "Error saving file... " << getRealPrintFilename().c_str() << G4endl;
662  } else {
663  G4cout << "File " << getRealPrintFilename().c_str() << " size: " << getRealExportWidth() << "x" << getRealExportHeight() << " has been saved " << G4endl;
664 
665  // increment index if necessary
666  if ( fExportFilenameIndex != -1) {
667  fExportFilenameIndex++;
668  }
669  }
670 
671 
672 #ifdef G4DEBUG_VIS_OGL
673  printf("G4OpenGLViewer::printEPS END\n");
674 #endif
675  return res;
676 }
677 
678 bool G4OpenGLViewer::printVectoredEPS() {
679  return printGl2PS();
680 }
681 
682 bool G4OpenGLViewer::printNonVectoredEPS () {
683 
684  int width = getRealExportWidth();
685  int height = getRealExportHeight();
686 
687 #ifdef G4DEBUG_VIS_OGL
688  printf("G4OpenGLViewer::printNonVectoredEPS file:%s Vec:%d X:%d Y:%d col:%d fWinX:%d fWinY:%d\n",getRealPrintFilename().c_str(),fVectoredPs,width,height,fPrintColour,fWinSize_x,fWinSize_y);
689 #endif
690  FILE* fp;
691  GLubyte* pixels;
692  GLubyte* curpix;
693  int components, pos, i;
694 
695  pixels = grabPixels (fPrintColour, width, height);
696 
697  if (pixels == NULL) {
698  G4cerr << "Failed to get pixels from OpenGl viewport" << G4endl;
699  return false;
700  }
701  if (fPrintColour) {
702  components = 3;
703  } else {
704  components = 1;
705  }
706  std::string name = getRealPrintFilename();
707  fp = fopen (name.c_str(), "w");
708  if (fp == NULL) {
709  G4cerr << "Can't open filename " << name.c_str() << G4endl;
710  return false;
711  }
712 
713  fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
714  fprintf (fp, "%%%%Title: %s\n", name.c_str());
715  fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
716  fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
717  fprintf (fp, "%%%%EndComments\n");
718  fprintf (fp, "gsave\n");
719  fprintf (fp, "/bwproc {\n");
720  fprintf (fp, " rgbproc\n");
721  fprintf (fp, " dup length 3 idiv string 0 3 0 \n");
722  fprintf (fp, " 5 -1 roll {\n");
723  fprintf (fp, " add 2 1 roll 1 sub dup 0 eq\n");
724  fprintf (fp, " { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
725  fprintf (fp, " 3 1 roll 5 -1 roll } put 1 add 3 0 \n");
726  fprintf (fp, " { 2 1 roll } ifelse\n");
727  fprintf (fp, " }forall\n");
728  fprintf (fp, " pop pop pop\n");
729  fprintf (fp, "} def\n");
730  fprintf (fp, "systemdict /colorimage known not {\n");
731  fprintf (fp, " /colorimage {\n");
732  fprintf (fp, " pop\n");
733  fprintf (fp, " pop\n");
734  fprintf (fp, " /rgbproc exch def\n");
735  fprintf (fp, " { bwproc } image\n");
736  fprintf (fp, " } def\n");
737  fprintf (fp, "} if\n");
738  fprintf (fp, "/picstr %d string def\n", width * components);
739  fprintf (fp, "%d %d scale\n", width, height);
740  fprintf (fp, "%d %d %d\n", width, height, 8);
741  fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height);
742  fprintf (fp, "{currentfile picstr readhexstring pop}\n");
743  fprintf (fp, "false %d\n", components);
744  fprintf (fp, "colorimage\n");
745 
746  curpix = (GLubyte*) pixels;
747  pos = 0;
748  for (i = width*height*components; i>0; i--) {
749  fprintf (fp, "%02hx ", (unsigned short)(*(curpix++)));
750  if (++pos >= 32) {
751  fprintf (fp, "\n");
752  pos = 0;
753  }
754  }
755  if (pos)
756  fprintf (fp, "\n");
757 
758  fprintf (fp, "grestore\n");
759  fprintf (fp, "showpage\n");
760  delete [] pixels;
761  fclose (fp);
762 
763  // Reset for next time (useful is size change)
764  // fPrintSizeX = -1;
765  // fPrintSizeY = -1;
766 
767  return true;
768 }
769 
772 bool G4OpenGLViewer::isGl2psWriting() {
773 
774  if (!fGL2PSAction) return false;
775  if (fGL2PSAction->fileWritingEnabled()) {
776  return true;
777  }
778  return false;
779 }
780 
781 
782 /* Draw Gl2Ps text if needed
783  */
784 void G4OpenGLViewer::DrawText(const G4Text& g4text)
785 {
786  // gl2ps or GL window ?
787  if (isGl2psWriting()) {
788 
790  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
791  G4Point3D position = g4text.GetPosition();
792 
793  G4String textString = g4text.GetText();
794 
795  glRasterPos3d(position.x(),position.y(),position.z());
796  GLint align = GL2PS_TEXT_B;
797 
798  switch (g4text.GetLayout()) {
799  case G4Text::left: align = GL2PS_TEXT_BL; break;
800  case G4Text::centre: align = GL2PS_TEXT_B; break;
801  case G4Text::right: align = GL2PS_TEXT_BR;
802  }
803 
804  gl2psTextOpt(textString.c_str(),"Times-Roman",GLshort(size),align,0);
805 
806  } else {
807 
808  static G4int callCount = 0;
809  ++callCount;
810  //if (callCount <= 10 || callCount%100 == 0) {
811  if (callCount <= 1) {
812  G4cout <<
813  "G4OpenGLViewer::DrawText: Not implemented for \""
814  << fName <<
815  "\"\n Called with "
816  << g4text
817  << G4endl;
818  }
819  }
820 }
821 
824 void G4OpenGLViewer::ChangePointSize(G4double size) {
825 
826  if (isGl2psWriting()) {
827  fGL2PSAction->setPointSize(int(size));
828  } else {
829  glPointSize (size);
830  }
831 }
832 
833 
836 void G4OpenGLViewer::ChangeLineWidth(G4double width) {
837 
838  if (isGl2psWriting()) {
839  fGL2PSAction->setLineWidth(int(width));
840  } else {
841  glLineWidth (width);
842  }
843 }
844 
853 bool G4OpenGLViewer::exportImage(std::string name, int width, int height) {
854 
855  if (! setExportFilename(name)) {
856  return false;
857  }
858 
859  if ((width =! -1) && (height != -1)) {
860  setExportSize(width, height);
861  }
862 
863  if (fExportImageFormat == "eps") {
864  fGL2PSAction->setExportImageFormat(GL2PS_EPS);
865  } else if (fExportImageFormat == "ps") {
866  fGL2PSAction->setExportImageFormat(GL2PS_PS);
867  } else if (fExportImageFormat == "svg") {
868  fGL2PSAction->setExportImageFormat(GL2PS_SVG);
869  } else if (fExportImageFormat == "pdf") {
870  fGL2PSAction->setExportImageFormat(GL2PS_PDF);
871  } else {
872  setExportImageFormat(fExportImageFormat,true); // will display a message if this format is not correct for the current viewer
873  return false;
874  }
875  return printEPS();
876 }
877 
878 
879 bool G4OpenGLViewer::printGl2PS() {
880 
881  int width = getRealExportWidth();
882  int height = getRealExportHeight();
883  bool res = true;
884 
885  // no need to redraw at each new primitive for printgl2PS
886  G4OpenGLSceneHandler& oglSceneHandler = dynamic_cast<G4OpenGLSceneHandler&>(fSceneHandler);
887  G4int drawInterval = oglSceneHandler.GetEventsDrawInterval();
888  oglSceneHandler.SetEventsDrawInterval(1000); // some big value but not too big to not crash memory
889 
890  if (!fGL2PSAction) return false;
891 
892  fGL2PSAction->setFileName(getRealPrintFilename().c_str());
893  // try to resize
894  int X = fWinSize_x;
895  int Y = fWinSize_y;
896 
897  fWinSize_x = width;
898  fWinSize_y = height;
899  // Laurent G. 16/03/10 : Not the good way to do.
900  // We should draw in a new offscreen context instead of
901  // resizing and drawing in current window...
902  // This should be solve when we will do an offscreen method
903  // to render OpenGL
904  // See :
905  // http://developer.apple.com/Mac/library/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html
906  // http://www.songho.ca/opengl/gl_fbo.html
907 
908  ResizeGLView();
909  bool extendBuffer = true;
910  bool endWriteAction = false;
911  bool beginWriteAction = true;
912  bool filePointerOk = true;
913  while ((extendBuffer) && (! endWriteAction) && (filePointerOk)) {
914 
915  beginWriteAction = fGL2PSAction->enableFileWriting();
916  // 3 cases :
917  // - true
918  // - false && ! fGL2PSAction->fileWritingEnabled() => bad file name
919  // - false && fGL2PSAction->fileWritingEnabled() => buffer size problem ?
920 
921  filePointerOk = fGL2PSAction->fileWritingEnabled();
922 
923  if (beginWriteAction) {
924 
925  // Set the viewport
926  // By default, we choose the line width (trajectories...)
927  fGL2PSAction->setLineWidth(fGl2psDefaultLineWith);
928  // By default, we choose the point size (markers...)
929  fGL2PSAction->setPointSize(fGl2psDefaultPointSize);
930 
931  DrawView ();
932  endWriteAction = fGL2PSAction->disableFileWriting();
933  }
934  if (filePointerOk) {
935  if ((! endWriteAction) || (! beginWriteAction)) {
936  extendBuffer = fGL2PSAction->extendBufferSize();
937  }
938  }
939  }
940  fGL2PSAction->resetBufferSizeParameters();
941 
942  if (!extendBuffer ) {
943  G4cerr << "ERROR: gl2ps buffer size is not big enough to print this geometry. Try to extend it. No output produced"<< G4endl;
944  res = false;
945  }
946  if (!beginWriteAction ) {
947  G4cerr << "ERROR: saving file "<<getRealPrintFilename().c_str()<<". Check read/write access. No output produced" << G4endl;
948  res = false;
949  }
950  if (!endWriteAction ) {
951  G4cerr << "gl2ps error. No output produced" << G4endl;
952  res = false;
953  }
954  fWinSize_x = X;
955  fWinSize_y = Y;
956 
957  oglSceneHandler.SetEventsDrawInterval(drawInterval);
958 
959  // Reset for next time (useful is size change)
960  // fPrintSizeX = 0;
961  // fPrintSizeY = 0;
962 
963  return res;
964 }
965 
966 unsigned int G4OpenGLViewer::getWinWidth() const{
967  return fWinSize_x;
968 }
969 
970 unsigned int G4OpenGLViewer::getWinHeight() const{
971  return fWinSize_y;
972 }
973 
974 G4bool G4OpenGLViewer::sizeHasChanged() {
975  return fSizeHasChanged;
976 }
977 
978 G4int G4OpenGLViewer::getRealExportWidth() {
979  if (fPrintSizeX == -1) {
980  return fWinSize_x;
981  }
982  GLint dims[2];
983  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
984 
985  // L.Garnier 01-2010: Some problems with mac 10.6
986  if ((dims[0] !=0 ) && (dims[1] !=0)) {
987  if (fPrintSizeX > dims[0]){
988  return dims[0];
989  }
990  }
991  if (fPrintSizeX < -1){
992  return 0;
993  }
994  return fPrintSizeX;
995 }
996 
997 G4int G4OpenGLViewer::getRealExportHeight() {
998  if (fPrintSizeY == -1) {
999  return fWinSize_y;
1000  }
1001  GLint dims[2];
1002  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
1003 
1004  // L.Garnier 01-2010: Some problems with mac 10.6
1005  if ((dims[0] !=0 ) && (dims[1] !=0)) {
1006  if (fPrintSizeY > dims[1]){
1007  return dims[1];
1008  }
1009  }
1010  if (fPrintSizeY < -1){
1011  return 0;
1012  }
1013  return fPrintSizeY;
1014 }
1015 
1016 void G4OpenGLViewer::setExportSize(G4int X, G4int Y) {
1017  fPrintSizeX = X;
1018  fPrintSizeY = Y;
1019 }
1020 
1027 bool G4OpenGLViewer::setExportFilename(G4String name,G4bool inc) {
1028  if (name == "!") {
1029  name = "";
1030  }
1031 
1032  if (inc) {
1033  if ((name != "") && (fExportFilename != name)) {
1034  fExportFilenameIndex=0;
1035  }
1036  } else {
1037  fExportFilenameIndex=-1;
1038  }
1039 
1040  if (name.size() == 0) {
1041  name = getRealPrintFilename().c_str();
1042  } else {
1043  // guess format by extention
1044  std::string extension = name.substr(name.find_last_of(".") + 1);
1045  // no format
1046  if (name.size() != extension.size()) {
1047  if (! setExportImageFormat(extension, false)) {
1048  return false;
1049  }
1050  }
1051  // get the name
1052  fExportFilename = name.substr(0,name.find_last_of("."));
1053  }
1054  return true;
1055 }
1056 
1057 std::string G4OpenGLViewer::getRealPrintFilename() {
1058  std::string temp = fExportFilename;
1059  if (fExportFilenameIndex != -1) {
1060  temp += std::string("_");
1061  std::ostringstream os;
1062  os << fExportFilenameIndex;
1063  std::string nb_str = os.str();
1064  temp += nb_str;
1065  }
1066  temp += "."+fExportImageFormat;
1067  return temp;
1068 }
1069 
1070 GLdouble G4OpenGLViewer::getSceneNearWidth()
1071 {
1072  if (!fSceneHandler.GetScene()) {
1073  return 0;
1074  }
1075  const G4Point3D targetPoint
1076  = fSceneHandler.GetScene()->GetStandardTargetPoint()
1077  + fVP.GetCurrentTargetPoint ();
1078  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1079  if(radius<=0.) radius = 1.;
1080  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1081  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1082  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
1083 }
1084 
1085 GLdouble G4OpenGLViewer::getSceneFarWidth()
1086 {
1087  if (!fSceneHandler.GetScene()) {
1088  return 0;
1089  }
1090  const G4Point3D targetPoint
1091  = fSceneHandler.GetScene()->GetStandardTargetPoint()
1092  + fVP.GetCurrentTargetPoint ();
1093  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1094  if(radius<=0.) radius = 1.;
1095  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1096  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1097  const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
1098  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
1099 }
1100 
1101 
1102 GLdouble G4OpenGLViewer::getSceneDepth()
1103 {
1104  if (!fSceneHandler.GetScene()) {
1105  return 0;
1106  }
1107  const G4Point3D targetPoint
1108  = fSceneHandler.GetScene()->GetStandardTargetPoint()
1109  + fVP.GetCurrentTargetPoint ();
1110  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1111  if(radius<=0.) radius = 1.;
1112  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1113  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1114  return fVP.GetFarDistance (cameraDistance, pnear, radius)- pnear;
1115 }
1116 
1117 
1118 
1119 void G4OpenGLViewer::rotateScene(G4double dx, G4double dy)
1120 {
1121  if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
1122  rotateSceneInViewDirection(dx,dy);
1123  } else {
1124  if( dx != 0) {
1125  rotateSceneThetaPhi(dx,0);
1126  }
1127  if( dy != 0) {
1128  rotateSceneThetaPhi(0,dy);
1129  }
1130  }
1131 }
1132 
1133 
1134 void G4OpenGLViewer::rotateSceneToggle(G4double dx, G4double dy)
1135 {
1136  if (fVP.GetRotationStyle() != G4ViewParameters::freeRotation) {
1137  rotateSceneInViewDirection(dx,dy);
1138  } else {
1139  if( dx != 0) {
1140  rotateSceneThetaPhi(dx,0);
1141  }
1142  if( dy != 0) {
1143  rotateSceneThetaPhi(0,dy);
1144  }
1145  }
1146 }
1147 
1148 void G4OpenGLViewer::rotateSceneThetaPhi(G4double dx, G4double dy)
1149 {
1150  if (!fSceneHandler.GetScene()) {
1151  return;
1152  }
1153 
1154  G4Vector3D vp;
1155  G4Vector3D up;
1156 
1157  G4Vector3D xprime;
1158  G4Vector3D yprime;
1159  G4Vector3D zprime;
1160 
1161  G4double delta_alpha;
1162  G4double delta_theta;
1163 
1164  G4Vector3D new_vp;
1165  G4Vector3D new_up;
1166 
1167  G4double cosalpha;
1168  G4double sinalpha;
1169 
1170  G4Vector3D a1;
1171  G4Vector3D a2;
1172  G4Vector3D delta;
1173  G4Vector3D viewPoint;
1174 
1175 
1176  //phi spin stuff here
1177 
1178  vp = fVP.GetViewpointDirection ().unit ();
1179  up = fVP.GetUpVector ().unit ();
1180 
1181  yprime = (up.cross(vp)).unit();
1182  zprime = (vp.cross(yprime)).unit();
1183 
1184  if (fVP.GetLightsMoveWithCamera()) {
1185  delta_alpha = dy * fRot_sens;
1186  delta_theta = -dx * fRot_sens;
1187  } else {
1188  delta_alpha = -dy * fRot_sens;
1189  delta_theta = dx * fRot_sens;
1190  }
1191 
1192  delta_alpha *= deg;
1193  delta_theta *= deg;
1194 
1195  new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
1196 
1197  // to avoid z rotation flipping
1198  // to allow more than 360∞ rotation
1199 
1200  if (fVP.GetLightsMoveWithCamera()) {
1201  new_up = (new_vp.cross(yprime)).unit();
1202  if (new_vp.z()*vp.z() <0) {
1203  new_up.set(new_up.x(),-new_up.y(),new_up.z());
1204  }
1205  } else {
1206  new_up = up;
1207  if (new_vp.z()*vp.z() <0) {
1208  new_up.set(new_up.x(),-new_up.y(),new_up.z());
1209  }
1210  }
1211  fVP.SetUpVector(new_up);
1213  // Rotates by fixed azimuthal angle delta_theta.
1214 
1215  cosalpha = new_up.dot (new_vp.unit());
1216  sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
1217  yprime = (new_up.cross (new_vp.unit())).unit ();
1218  xprime = yprime.cross (new_up);
1219  // Projection of vp on plane perpendicular to up...
1220  a1 = sinalpha * xprime;
1221  // Required new projection...
1222  a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
1223  // Required Increment vector...
1224  delta = a2 - a1;
1225  // So new viewpoint is...
1226  viewPoint = new_vp.unit() + delta;
1227 
1228  fVP.SetViewAndLights (viewPoint);
1229 }
1230 
1231 
1232 void G4OpenGLViewer::rotateSceneInViewDirection(G4double dx, G4double dy)
1233 {
1234  if (!fSceneHandler.GetScene()) {
1235  return;
1236  }
1237 
1238  G4Vector3D vp;
1239  G4Vector3D up;
1240 
1241  G4Vector3D xprime;
1242  G4Vector3D yprime;
1243  G4Vector3D zprime;
1244 
1245  G4Vector3D new_vp;
1246  G4Vector3D new_up;
1247 
1248  G4Vector3D a1;
1249  G4Vector3D a2;
1250  G4Vector3D delta;
1251  G4Vector3D viewPoint;
1252 
1253  dx = dx/100;
1254  dy = dy/100;
1255 
1256  //phi spin stuff here
1257 
1258 #ifdef G4DEBUG_VIS_OGL
1259  printf("G4OpenGLViewer::rotateScene dx:%f dy:%f delta:%f\n",dx,dy, fRot_sens);
1260 #endif
1261 
1262  vp = fVP.GetViewpointDirection ().unit();
1263  up = fVP.GetUpVector ().unit();
1264 
1265  G4Vector3D zPrimeVector = G4Vector3D(up.y()*vp.z()-up.z()*vp.y(),
1266  up.z()*vp.x()-up.x()*vp.z(),
1267  up.x()*vp.y()-up.y()*vp.x());
1268 
1269  viewPoint = vp/fRot_sens + (zPrimeVector*dx - up*dy) ;
1270  new_up = G4Vector3D(viewPoint.y()*zPrimeVector.z()-viewPoint.z()*zPrimeVector.y(),
1271  viewPoint.z()*zPrimeVector.x()-viewPoint.x()*zPrimeVector.z(),
1272  viewPoint.x()*zPrimeVector.y()-viewPoint.y()*zPrimeVector.x());
1273 
1274  G4Vector3D new_upUnit = new_up.unit();
1275 
1276 
1277 
1278  fVP.SetUpVector(new_upUnit);
1279  fVP.SetViewAndLights (viewPoint);
1280 }
1281 
1282 
1283 void G4OpenGLViewer::addExportImageFormat(std::string format) {
1284  fExportImageFormatVector.push_back(format);
1285 }
1286 
1287 bool G4OpenGLViewer::setExportImageFormat(std::string format, bool quiet) {
1288  bool found = false;
1289  std::string list;
1290  for (unsigned int a=0; a<fExportImageFormatVector.size(); a++) {
1291  list +=fExportImageFormatVector.at(a) + " ";
1292 
1293  if (fExportImageFormatVector.at(a) == format) {
1294  if (! quiet) {
1295  G4cout << " Changing export format to \"" << format << "\"" << G4endl;
1296  }
1297  if (format != fExportImageFormat) {
1298  fExportFilenameIndex = 0;
1299  fExportImageFormat = format;
1300  }
1301  return true;
1302  }
1303  }
1304  if (! found) {
1305  if (format.size() == 0) {
1306  G4cout << " Current formats availables are : " << list << G4endl;
1307  } else {
1308  G4cerr << " Format \"" << format << "\" is not available for the selected viewer. Current formats availables are : " << list << G4endl;
1309  }
1310  }
1311  return false;
1312 }
1313 
1314 
1315 // From MESA implementation :
1316 // http://www.techques.com/question/1-8660454/gluPickMatrix-code-from-Mesa
1317 
1318 void G4OpenGLViewer::g4GluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height,
1319  GLint viewport[4])
1320  {
1321  GLfloat mat[16];
1322  GLfloat sx, sy;
1323  GLfloat tx, ty;
1324 
1325  sx = viewport[2] / width;
1326  sy = viewport[3] / height;
1327  tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
1328  ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
1329 
1330 #define M(row, col) mat[col*4+row]
1331  M(0, 0) = sx;
1332  M(0, 1) = 0.0;
1333  M(0, 2) = 0.0;
1334  M(0, 3) = tx;
1335  M(1, 0) = 0.0;
1336  M(1, 1) = sy;
1337  M(1, 2) = 0.0;
1338  M(1, 3) = ty;
1339  M(2, 0) = 0.0;
1340  M(2, 1) = 0.0;
1341  M(2, 2) = 1.0;
1342  M(2, 3) = 0.0;
1343  M(3, 0) = 0.0;
1344  M(3, 1) = 0.0;
1345  M(3, 2) = 0.0;
1346  M(3, 3) = 1.0;
1347 #undef M
1348 
1349  glMultMatrixf(mat);
1350 }
1351 
1352 
1353 
1354 
1355 
1356 // From MESA implementation :
1357 // https://github.com/jlamarche/iOS-OpenGLES-Stuff/blob/master/Wavefront%20OBJ%20Loader/Classes/gluLookAt.m
1358 // or http://www.daniweb.com/software-development/game-development/threads/308901/lookat-matrix-source-code
1359 
1360 void G4OpenGLViewer::g4GluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
1361  GLdouble centerx, GLdouble centery, GLdouble
1362  centerz,
1363  GLdouble upx, GLdouble upy, GLdouble upz )
1364 {
1365  GLfloat mat[16];
1366  GLfloat x[3], y[3], z[3];
1367  GLfloat mag;
1368 
1369  /* Make rotation matrix */
1370 
1371  /* Z vector */
1372  z[0] = eyex - centerx;
1373  z[1] = eyey - centery;
1374  z[2] = eyez - centerz;
1375  mag = std::sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
1376  if (mag) { /* mpichler, 19950515 */
1377  z[0] /= mag;
1378  z[1] /= mag;
1379  z[2] /= mag;
1380  }
1381 
1382  /* Y vector */
1383  y[0] = upx;
1384  y[1] = upy;
1385  y[2] = upz;
1386 
1387  /* X vector = Y cross Z */
1388  x[0] = y[1] * z[2] - y[2] * z[1];
1389  x[1] = -y[0] * z[2] + y[2] * z[0];
1390  x[2] = y[0] * z[1] - y[1] * z[0];
1391 
1392  /* Recompute Y = Z cross X */
1393  y[0] = z[1] * x[2] - z[2] * x[1];
1394  y[1] = -z[0] * x[2] + z[2] * x[0];
1395  y[2] = z[0] * x[1] - z[1] * x[0];
1396 
1397  /* mpichler, 19950515 */
1398  /* cross product gives area of parallelogram, which is < 1.0 for
1399  * non-perpendicular unit-length vectors; so normalize x, y here
1400  */
1401 
1402  mag = std::sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
1403  if (mag) {
1404  x[0] /= mag;
1405  x[1] /= mag;
1406  x[2] /= mag;
1407  }
1408 
1409  mag = std::sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
1410  if (mag) {
1411  y[0] /= mag;
1412  y[1] /= mag;
1413  y[2] /= mag;
1414  }
1415 
1416 #define M(row,col) mat[col*4+row]
1417  M(0, 0) = x[0];
1418  M(0, 1) = x[1];
1419  M(0, 2) = x[2];
1420  M(0, 3) = 0.0;
1421  M(1, 0) = y[0];
1422  M(1, 1) = y[1];
1423  M(1, 2) = y[2];
1424  M(1, 3) = 0.0;
1425  M(2, 0) = z[0];
1426  M(2, 1) = z[1];
1427  M(2, 2) = z[2];
1428  M(2, 3) = 0.0;
1429  M(3, 0) = 0.0;
1430  M(3, 1) = 0.0;
1431  M(3, 2) = 0.0;
1432  M(3, 3) = 1.0;
1433 #undef M
1434  glMultMatrixf(mat);
1435 
1436  /* Translate Eye to Origin */
1437  glTranslatef(-eyex, -eyey, -eyez);
1438 }
1439 
1440 
1441 
1442 #ifdef G4OPENGL_VERSION_2
1443 
1444 // Associate the VBO drawer to the OpenGLViewer and the OpenGLSceneHandler
1445 void G4OpenGLViewer::setVboDrawer(G4OpenGLVboDrawer* drawer) {
1446  fVboDrawer = drawer;
1447  try {
1448  G4OpenGLSceneHandler& sh = dynamic_cast<G4OpenGLSceneHandler&>(fSceneHandler);
1449  sh.setVboDrawer(fVboDrawer);
1450  } catch(std::bad_cast exp) { }
1451 }
1452 
1453 #endif
1454 
1455 
1457  std::ostringstream txt;
1458 
1459  txt << fName;
1460 
1461  txt << "Hit: " << fHitNumber << ", Sub-hit: " << fSubHitNumber << ", PickName: " << fPickName << "\n";
1462 
1463  for (unsigned int a=0; a<fAttributes.size(); a++) {
1464  txt << fAttributes[a] << "\n";
1465  }
1466  return txt.str();
1467 }
1468 
1469 #endif
Definition: G4Text.hh:73
G4String fName
Definition: G4AttUtils.hh:55
G4double z
Definition: TRTMaterials.hh:39
G4String name
Definition: TRTMaterials.hh:40
static const G4double a1
const std::vector< const std::vector< G4AttValue > * > & GetAttValues() const
Definition: G4AttHolder.hh:60
#define width
#define buffer
Definition: xmlparse.cc:611
HepGeom::Point3D< G4double > G4Point3D
Definition: G4Point3D.hh:35
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:35
G4double a
Definition: TRTMaterials.hh:39
G4Point3D GetPosition() const
int G4int
Definition: G4Types.hh:78
#define position
Definition: xmlparse.cc:605
G4GLOB_DLL std::ostream G4cout
virtual void ResetView()
Layout GetLayout() const
static const double deg
Definition: G4SIunits.hh:133
bool G4bool
Definition: G4Types.hh:79
std::vector< G4Plane3D > G4Planes
G4String GetText() const
HepGeom::Plane3D< G4double > G4Plane3D
Definition: G4Plane3D.hh:37
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
void print(const std::vector< T > &data)
Definition: DicomRun.hh:109
#define DBL_MAX
Definition: templates.hh:83
static const G4double pos
static const G4double a2
const std::vector< const std::map< G4String, G4AttDef > * > & GetAttDefs() const
Definition: G4AttHolder.hh:62
G4GLOB_DLL std::ostream G4cerr
HepGeom::Normal3D< G4double > G4Normal3D
Definition: G4Normal3D.hh:35