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