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