Geant4  9.6.p02
 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$
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 // GL2PS
54 #include "Geant4_gl2ps.h"
55 
56 #include <sstream>
57 
58 G4int G4OpenGLViewer::fPrintSizeX = -1;
59 G4int G4OpenGLViewer::fPrintSizeY = -1;
60 G4String G4OpenGLViewer::fPrintFilename = "G4OpenGL";
61 int G4OpenGLViewer::fPrintFilenameIndex = 0;
62 
63 G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
64 G4VViewer (scene, -1),
65 fPrintColour (true),
66 fVectoredPs (true),
67 fOpenGLSceneHandler(scene),
68 background (G4Colour(0.,0.,0.)),
69 transparency_enabled (true),
70 antialiasing_enabled (false),
71 haloing_enabled (false),
72 fStartTime(-DBL_MAX),
73 fEndTime(DBL_MAX),
74 fFadeFactor(0.),
75 fDisplayHeadTime(false),
76 fDisplayHeadTimeX(-0.9),
77 fDisplayHeadTimeY(-0.9),
78 fDisplayHeadTimeSize(24.),
79 fDisplayHeadTimeRed(0.),
80 fDisplayHeadTimeGreen(1.),
81 fDisplayHeadTimeBlue(1.),
82 fDisplayLightFront(false),
83 fDisplayLightFrontX(0.),
84 fDisplayLightFrontY(0.),
85 fDisplayLightFrontZ(0.),
86 fDisplayLightFrontT(0.),
87 fDisplayLightFrontRed(0.),
88 fDisplayLightFrontGreen(1.),
89 fDisplayLightFrontBlue(0.),
90 fRot_sens(1.),
91 fPan_sens(0.01),
92 fWinSize_x(0),
93 fWinSize_y(0),
94 fPointSize (0),
95 fSizeHasChanged(0),
96 fGl2psDefaultLineWith(1),
97 fGl2psDefaultPointSize(2)
98 {
99 #ifdef G4DEBUG_VIS_OGL
100  printf("G4OpenGLViewer:: Creation\n");
101 #endif
102  // Make changes to view parameters for OpenGL...
103  fVP.SetAutoRefresh(true);
104  fDefaultVP.SetAutoRefresh(true);
105 
106  fGL2PSAction = new G4OpenGL2PSAction();
107 
108  // glClearColor (0.0, 0.0, 0.0, 0.0);
109  // glClearDepth (1.0);
110  // glDisable (GL_BLEND);
111  // glDisable (GL_LINE_SMOOTH);
112  // glDisable (GL_POLYGON_SMOOTH);
113 
114 }
115 
116 G4OpenGLViewer::~G4OpenGLViewer ()
117 {
118  delete fGL2PSAction;
119 }
120 
121 void G4OpenGLViewer::InitializeGLView ()
122 {
123 #ifdef G4DEBUG_VIS_OGL
124  printf("G4OpenGLViewer::InitializeGLView\n");
125 #endif
126 
127  fWinSize_x = fVP.GetWindowSizeHintX();
128  fWinSize_y = fVP.GetWindowSizeHintY();
129 
130  glClearColor (0.0, 0.0, 0.0, 0.0);
131  glClearDepth (1.0);
132  glDisable (GL_LINE_SMOOTH);
133  glDisable (GL_POLYGON_SMOOTH);
134 
135 // clear the buffers and window?
136  ClearView ();
137  FinishView ();
138 
139  glDepthFunc (GL_LEQUAL);
140  glDepthMask (GL_TRUE);
141 
142  glEnable (GL_BLEND);
143  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
144 
145 #ifdef G4DEBUG_VIS_OGL
146  printf("G4OpenGLViewer::InitializeGLView END\n");
147 #endif
148 }
149 
150 void G4OpenGLViewer::ClearView () {
151 #ifdef G4DEBUG_VIS_OGL
152  printf("G4OpenGLViewer::ClearView\n");
153 #endif
154  glClearColor (background.GetRed(),
155  background.GetGreen(),
156  background.GetBlue(),
157  1.);
158  glClearDepth (1.0);
159  //Below line does not compile with Mesa includes.
160  //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
161  glClear (GL_COLOR_BUFFER_BIT);
162  glClear (GL_DEPTH_BUFFER_BIT);
163  glClear (GL_STENCIL_BUFFER_BIT);
164 #ifdef G4DEBUG_VIS_OGL
165  printf("G4OpenGLViewer::ClearView flush\n");
166 #endif
167  glFlush ();
168 }
169 
170 
171 void G4OpenGLViewer::ResizeWindow(unsigned int aWidth, unsigned int aHeight) {
172  if ((fWinSize_x != aWidth) || (fWinSize_y != aHeight)) {
173  fWinSize_x = aWidth;
174  fWinSize_y = aHeight;
175  fSizeHasChanged = true;
176  } else {
177  fSizeHasChanged = false;
178  }
179 }
180 
187 void G4OpenGLViewer::ResizeGLView()
188 {
189 #ifdef G4DEBUG_VIS_OGL
190  printf("G4OpenGLViewer::ResizeGLView %d %d %#lx\n",fWinSize_x,fWinSize_y,(unsigned long)this);
191 #endif
192  // Check size
193  GLint dims[2];
194  dims[0] = 0;
195  dims[1] = 0;
196 
197  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
198 
199  if ((dims[0] !=0 ) && (dims[1] !=0)) {
200 
201  if (fWinSize_x > (unsigned)dims[0]) {
202  G4cerr << "Try to resize view greater than max X viewport dimension. Desired size "<<fWinSize_x <<" is resize to "<< dims[0] << G4endl;
203  fWinSize_x = dims[0];
204  }
205  if (fWinSize_y > (unsigned)dims[1]) {
206  G4cerr << "Try to resize view greater than max Y viewport dimension. Desired size "<<fWinSize_y <<" is resize to "<< dims[1] << G4endl;
207  fWinSize_y = dims[1];
208  }
209  }
210 
211  glViewport(0, 0, fWinSize_x,fWinSize_y);
212 
213 
214 }
215 
216 
217 void G4OpenGLViewer::SetView () {
218 
219  if (!fSceneHandler.GetScene()) {
220  return;
221  }
222  // Calculates view representation based on extent of object being
223  // viewed and (initial) viewpoint. (Note: it can change later due
224  // to user interaction via visualization system's GUI.)
225 
226  // Lighting.
227  GLfloat lightPosition [4];
228  lightPosition [0] = fVP.GetActualLightpointDirection().x();
229  lightPosition [1] = fVP.GetActualLightpointDirection().y();
230  lightPosition [2] = fVP.GetActualLightpointDirection().z();
231  lightPosition [3] = 0.;
232  // Light position is "true" light direction, so must come after gluLookAt.
233  GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
234  GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
235  glEnable (GL_LIGHT0);
236  glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
237  glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
238 
239  G4double ratioX = 1;
240  G4double ratioY = 1;
241  if (fWinSize_y > fWinSize_x) {
242  ratioX = ((G4double)fWinSize_y) / ((G4double)fWinSize_x);
243  }
244  if (fWinSize_x > fWinSize_y) {
245  ratioY = ((G4double)fWinSize_x) / ((G4double)fWinSize_y);
246  }
247 
248  // Get radius of scene, etc.
249  // Note that this procedure properly takes into account zoom, dolly and pan.
250  const G4Point3D targetPoint
251  = fSceneHandler.GetScene()->GetStandardTargetPoint()
252  + fVP.GetCurrentTargetPoint ();
253  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
254  if(radius<=0.) radius = 1.;
255  const G4double cameraDistance = fVP.GetCameraDistance (radius);
256  const G4Point3D cameraPosition =
257  targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
258  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
259  const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
260  const GLdouble right = fVP.GetFrontHalfHeight (pnear, radius) * ratioY;
261  const GLdouble left = -right;
262  const GLdouble top = fVP.GetFrontHalfHeight (pnear, radius) * ratioX;
263  const GLdouble bottom = -top;
264 
265  // FIXME
266  ResizeGLView();
267  //SHOULD SetWindowsSizeHint()...
268 
269  glMatrixMode (GL_PROJECTION); // set up Frustum.
270  glLoadIdentity();
271 
272  const G4Vector3D scaleFactor = fVP.GetScaleFactor();
273  glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
274 
275  if (fVP.GetFieldHalfAngle() == 0.) {
276  glOrtho (left, right, bottom, top, pnear, pfar);
277  }
278  else {
279  glFrustum (left, right, bottom, top, pnear, pfar);
280  }
281 
282  glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
283  glLoadIdentity();
284 
285  const G4Normal3D& upVector = fVP.GetUpVector ();
286  G4Point3D gltarget;
287  if (cameraDistance > 1.e-6 * radius) {
288  gltarget = targetPoint;
289  }
290  else {
291  gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
292  }
293 
294  const G4Point3D& pCamera = cameraPosition; // An alias for brevity.
295  gluLookAt (pCamera.x(), pCamera.y(), pCamera.z(), // Viewpoint.
296  gltarget.x(), gltarget.y(), gltarget.z(), // Target point.
297  upVector.x(), upVector.y(), upVector.z()); // Up vector.
298 
299  // Light position is "true" light direction, so must come after gluLookAt.
300  glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
301 
302  // OpenGL no longer seems to reconstruct clipped edges, so, when the
303  // BooleanProcessor is up to it, abandon this and use generic
304  // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron. Also,
305  // force kernel visit on change of clipping plane in
306  // G4OpenGLStoredViewer::CompareForKernelVisit.
307  //if (fVP.IsSection () ) { // pair of back to back clip planes.
308  if (false) { // pair of back to back clip planes.
309  const G4Plane3D& sp = fVP.GetSectionPlane ();
310  double sArray[4];
311  sArray[0] = sp.a();
312  sArray[1] = sp.b();
313  sArray[2] = sp.c();
314  sArray[3] = sp.d() + radius * 1.e-05;
315  glClipPlane (GL_CLIP_PLANE0, sArray);
316  glEnable (GL_CLIP_PLANE0);
317  sArray[0] = -sp.a();
318  sArray[1] = -sp.b();
319  sArray[2] = -sp.c();
320  sArray[3] = -sp.d() + radius * 1.e-05;
321  glClipPlane (GL_CLIP_PLANE1, sArray);
322  glEnable (GL_CLIP_PLANE1);
323  } else {
324  glDisable (GL_CLIP_PLANE0);
325  glDisable (GL_CLIP_PLANE1);
326  }
327 
328  // What we call intersection of cutaways is easy in OpenGL. You
329  // just keep cutting. Unions are more tricky - you have to have
330  // multiple passes and this is handled in
331  // G4OpenGLImmediate/StoredViewer::ProcessView.
332  const G4Planes& cutaways = fVP.GetCutawayPlanes();
333  size_t nPlanes = cutaways.size();
334  if (fVP.IsCutaway() &&
335  fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
336  nPlanes > 0) {
337  double a[4];
338  a[0] = cutaways[0].a();
339  a[1] = cutaways[0].b();
340  a[2] = cutaways[0].c();
341  a[3] = cutaways[0].d();
342  glClipPlane (GL_CLIP_PLANE2, a);
343  glEnable (GL_CLIP_PLANE2);
344  if (nPlanes > 1) {
345  a[0] = cutaways[1].a();
346  a[1] = cutaways[1].b();
347  a[2] = cutaways[1].c();
348  a[3] = cutaways[1].d();
349  glClipPlane (GL_CLIP_PLANE3, a);
350  glEnable (GL_CLIP_PLANE3);
351  }
352  if (nPlanes > 2) {
353  a[0] = cutaways[2].a();
354  a[1] = cutaways[2].b();
355  a[2] = cutaways[2].c();
356  a[3] = cutaways[2].d();
357  glClipPlane (GL_CLIP_PLANE4, a);
358  glEnable (GL_CLIP_PLANE4);
359  }
360  } else {
361  glDisable (GL_CLIP_PLANE2);
362  glDisable (GL_CLIP_PLANE3);
363  glDisable (GL_CLIP_PLANE4);
364  }
365 
366  // Background.
367  background = fVP.GetBackgroundColour ();
368 
369 }
370 
371 
372 
373 void G4OpenGLViewer::ResetView () {
375  fRot_sens = 1;
376  fPan_sens = 0.01;
377 }
378 
379 
380 void G4OpenGLViewer::HaloingFirstPass () {
381 
382  //To perform haloing, first Draw all information to the depth buffer
383  //alone, using a chunky line width, and then Draw all info again, to
384  //the colour buffer, setting a thinner line width an the depth testing
385  //function to less than or equal, so if two lines cross, the one
386  //passing behind the other will not pass the depth test, and so not
387  //get rendered either side of the infront line for a short distance.
388 
389  //First, disable writing to the colo(u)r buffer...
390  glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
391 
392  //Now enable writing to the depth buffer...
393  glDepthMask (GL_TRUE);
394  glDepthFunc (GL_LESS);
395  glClearDepth (1.0);
396 
397  //Finally, set the line width to something wide...
398  ChangeLineWidth(3.0);
399 
400 }
401 
402 void G4OpenGLViewer::HaloingSecondPass () {
403 
404  //And finally, turn the colour buffer back on with a sesible line width...
405  glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
406  glDepthFunc (GL_LEQUAL);
407  ChangeLineWidth(1.0);
408 
409 }
410 
411 void G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
412 {
413  //G4cout << "X: " << x << ", Y: " << y << G4endl;
414  const G4int BUFSIZE = 512;
415  GLuint selectBuffer[BUFSIZE];
416  glSelectBuffer(BUFSIZE, selectBuffer);
417  glRenderMode(GL_SELECT);
418  glInitNames();
419  glPushName(0);
420  glMatrixMode(GL_PROJECTION);
421  G4double currentProjectionMatrix[16];
422  glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
423  glPushMatrix();
424  glLoadIdentity();
425  GLint viewport[4];
426  glGetIntegerv(GL_VIEWPORT, viewport);
427  // Define 5x5 pixel pick area
428  gluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
429  glMultMatrixd(currentProjectionMatrix);
430  glMatrixMode(GL_MODELVIEW);
431  DrawView();
432  GLint hits = glRenderMode(GL_RENDER);
433  if (hits < 0)
434  G4cout << "Too many hits. Zoom in to reduce overlaps." << G4endl;
435  else if (hits > 0) {
436  G4cout << hits << " hit(s)" << G4endl;
437  GLuint* p = selectBuffer;
438  for (GLint i = 0; i < hits; ++i) {
439  GLuint nnames = *p++;
440  // This bit of debug code or...
441  //GLuint zmin = *p++;
442  //GLuint zmax = *p++;
443  //G4cout << "Hit " << i << ": " << nnames << " names"
444  // << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
445  // ...just increment the pointer
446  p++;
447  p++;
448  for (GLuint j = 0; j < nnames; ++j) {
449  GLuint name = *p++;
450  G4cout << "Hit: " << i
451  << ", Sub-hit: " << j
452  << ", PickName: " << name << G4endl;
453  std::map<GLuint, G4AttHolder*>::iterator iter =
454  fOpenGLSceneHandler.fPickMap.find(name);
455  if (iter != fOpenGLSceneHandler.fPickMap.end()) {
456  G4AttHolder* attHolder = iter->second;
457  if(attHolder && attHolder->GetAttDefs().size()) {
458  for (size_t iAtt = 0;
459  iAtt < attHolder->GetAttDefs().size(); ++iAtt) {
460  G4cout << G4AttCheck(attHolder->GetAttValues()[iAtt],
461  attHolder->GetAttDefs()[iAtt]);
462  }
463  }
464  }
465  }
466  G4cout << G4endl;
467  }
468  }
469  glMatrixMode(GL_PROJECTION);
470  glPopMatrix();
471  glMatrixMode(GL_MODELVIEW);
472 }
473 
474 
475 
476 
477 GLubyte* G4OpenGLViewer::grabPixels (int inColor, unsigned int width, unsigned int height) {
478 
479  GLubyte* buffer;
480  GLint swapbytes, lsbfirst, rowlength;
481  GLint skiprows, skippixels, alignment;
482  GLenum format;
483  int size;
484 
485  if (inColor) {
486  format = GL_RGB;
487  size = width*height*3;
488  } else {
489  format = GL_LUMINANCE;
490  size = width*height*1;
491  }
492 
493  buffer = new GLubyte[size];
494  if (buffer == NULL)
495  return NULL;
496 
497  glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
498  glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
499  glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
500 
501  glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
502  glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
503  glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
504 
505  glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
506  glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
507  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
508 
509  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
510  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
511  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
512 
513  glReadBuffer(GL_FRONT);
514  glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
515 
516  glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
517  glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
518  glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
519 
520  glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
521  glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
522  glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
523 
524  return buffer;
525 }
526 
527 void G4OpenGLViewer::printEPS() {
528  bool res;
529 #ifdef G4DEBUG_VIS_OGL
530  printf("G4OpenGLViewer::printEPS file:%s Vec:%d Name:%s\n",getRealPrintFilename().c_str(),fVectoredPs,GetName().c_str());
531 #endif
532 
533  // Change the LC_NUMERIC value in order to have "." separtor and not ","
534  // This case is only useful for French, Canadien...
535  size_t len = strlen(setlocale(LC_NUMERIC,NULL));
536  char* oldLocale = (char*)(malloc(len+1));
537  if(oldLocale!=NULL) strncpy(oldLocale,setlocale(LC_NUMERIC,NULL),len);
538  setlocale(LC_NUMERIC,"C");
539 
540  if (fVectoredPs) {
541  res = printVectoredEPS();
542  } else {
543  res = printNonVectoredEPS();
544  }
545 
546  // restore the local
547  if (oldLocale) {
548  setlocale(LC_NUMERIC,oldLocale);
549  free(oldLocale);
550  }
551 
552  if (res == false) {
553  G4cerr << "Error while saving file... "<<getRealPrintFilename().c_str()<< G4endl;
554  } else {
555  G4cout << "File "<<getRealPrintFilename().c_str()<<" has been saved " << G4endl;
556  }
557 
558  // increment index if necessary
559  if ( fPrintFilenameIndex != -1) {
560  fPrintFilenameIndex++;
561  }
562 
563 #ifdef G4DEBUG_VIS_OGL
564  printf("G4OpenGLViewer::printEPS END\n");
565 #endif
566 }
567 
568 bool G4OpenGLViewer::printVectoredEPS() {
569  return printGl2PS();
570 }
571 
572 bool G4OpenGLViewer::printNonVectoredEPS () {
573 
574  int width = getRealPrintSizeX();
575  int height = getRealPrintSizeY();
576 
577 #ifdef G4DEBUG_VIS_OGL
578  printf("G4OpenGLViewer::printNonVectoredEPS file:%s Vec:%d X:%d Y:%d col:%d fWinX:%d fWinY:%d\n",getRealPrintFilename().c_str(),fVectoredPs,width,height,fPrintColour,fWinSize_x,fWinSize_y);
579 #endif
580  FILE* fp;
581  GLubyte* pixels;
582  GLubyte* curpix;
583  int components, pos, i;
584 
585  pixels = grabPixels (fPrintColour, width, height);
586 
587  if (pixels == NULL) {
588  G4cerr << "Failed to get pixels from OpenGl viewport" << G4endl;
589  return false;
590  }
591  if (fPrintColour) {
592  components = 3;
593  } else {
594  components = 1;
595  }
596  std::string name = getRealPrintFilename();
597  fp = fopen (name.c_str(), "w");
598  if (fp == NULL) {
599  G4cerr << "Can't open filename " << name.c_str() << G4endl;
600  return false;
601  }
602 
603  fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
604  fprintf (fp, "%%%%Title: %s\n", name.c_str());
605  fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
606  fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
607  fprintf (fp, "%%%%EndComments\n");
608  fprintf (fp, "gsave\n");
609  fprintf (fp, "/bwproc {\n");
610  fprintf (fp, " rgbproc\n");
611  fprintf (fp, " dup length 3 idiv string 0 3 0 \n");
612  fprintf (fp, " 5 -1 roll {\n");
613  fprintf (fp, " add 2 1 roll 1 sub dup 0 eq\n");
614  fprintf (fp, " { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
615  fprintf (fp, " 3 1 roll 5 -1 roll } put 1 add 3 0 \n");
616  fprintf (fp, " { 2 1 roll } ifelse\n");
617  fprintf (fp, " }forall\n");
618  fprintf (fp, " pop pop pop\n");
619  fprintf (fp, "} def\n");
620  fprintf (fp, "systemdict /colorimage known not {\n");
621  fprintf (fp, " /colorimage {\n");
622  fprintf (fp, " pop\n");
623  fprintf (fp, " pop\n");
624  fprintf (fp, " /rgbproc exch def\n");
625  fprintf (fp, " { bwproc } image\n");
626  fprintf (fp, " } def\n");
627  fprintf (fp, "} if\n");
628  fprintf (fp, "/picstr %d string def\n", width * components);
629  fprintf (fp, "%d %d scale\n", width, height);
630  fprintf (fp, "%d %d %d\n", width, height, 8);
631  fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height);
632  fprintf (fp, "{currentfile picstr readhexstring pop}\n");
633  fprintf (fp, "false %d\n", components);
634  fprintf (fp, "colorimage\n");
635 
636  curpix = (GLubyte*) pixels;
637  pos = 0;
638  for (i = width*height*components; i>0; i--) {
639  fprintf (fp, "%02hx ", (unsigned short)(*(curpix++)));
640  if (++pos >= 32) {
641  fprintf (fp, "\n");
642  pos = 0;
643  }
644  }
645  if (pos)
646  fprintf (fp, "\n");
647 
648  fprintf (fp, "grestore\n");
649  fprintf (fp, "showpage\n");
650  delete [] pixels;
651  fclose (fp);
652 
653  // Reset for next time (useful is size change)
654  // fPrintSizeX = -1;
655  // fPrintSizeY = -1;
656 
657  return true;
658 }
659 
662 bool G4OpenGLViewer::isGl2psWriting() {
663 
664  if (!fGL2PSAction) return false;
665  if (fGL2PSAction->fileWritingEnabled()) {
666  return true;
667  }
668  return false;
669 }
670 
671 
672 /* Draw Gl2Ps text if needed
673  */
674 void G4OpenGLViewer::DrawText(const G4Text& g4text)
675 {
676  // gl2ps or GL window ?
677  if (isGl2psWriting()) {
678 
680  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
681  G4Point3D position = g4text.GetPosition();
682 
683  G4String textString = g4text.GetText();
684  const char* textCString = textString.c_str();
685 
686  glRasterPos3d(position.x(),position.y(),position.z());
687  GLint align = GL2PS_TEXT_B;
688 
689  switch (g4text.GetLayout()) {
690  case G4Text::left: align = GL2PS_TEXT_BL; break;
691  case G4Text::centre: align = GL2PS_TEXT_B; break;
692  case G4Text::right: align = GL2PS_TEXT_BR;
693  }
694 
695  gl2psTextOpt(textCString,"Times-Roman",GLshort(size),align,0);
696 
697  } else {
698 
699  static G4int callCount = 0;
700  ++callCount;
701  //if (callCount <= 10 || callCount%100 == 0) {
702  if (callCount <= 1) {
703  G4cout <<
704  "G4OpenGLViewer::DrawText: Not implemented for \""
705  << fName <<
706  "\"\n Called with "
707  << g4text
708  << G4endl;
709  }
710  }
711 }
712 
715 void G4OpenGLViewer::ChangePointSize(G4double size) {
716 
717  if (isGl2psWriting()) {
718  fGL2PSAction->setPointSize(int(size));
719  } else {
720  glPointSize (size);
721  }
722 }
723 
724 
727 void G4OpenGLViewer::ChangeLineWidth(G4double width) {
728 
729  if (isGl2psWriting()) {
730  fGL2PSAction->setLineWidth(int(width));
731  } else {
732  glLineWidth (width);
733  }
734 }
735 
736 
737 bool G4OpenGLViewer::printGl2PS() {
738 
739  int width = getRealPrintSizeX();
740  int height = getRealPrintSizeY();
741 
742  if (!fGL2PSAction) return false;
743 
744  fGL2PSAction->setFileName(getRealPrintFilename().c_str());
745  // try to resize
746  int X = fWinSize_x;
747  int Y = fWinSize_y;
748 
749  fWinSize_x = width;
750  fWinSize_y = height;
751  // Laurent G. 16/03/10 : Not the good way to do.
752  // We should draw in a new offscreen context instead of
753  // resizing and drawing in current window...
754  // This should be solve when we will do an offscreen method
755  // to render OpenGL
756  // See :
757  // http://developer.apple.com/Mac/library/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html
758  // http://www.songho.ca/opengl/gl_fbo.html
759 
760  ResizeGLView();
761  bool extendBuffer = true;
762  bool endWriteAction = false;
763  bool beginWriteAction = true;
764  while ((extendBuffer) && (! endWriteAction)) {
765 
766  beginWriteAction = fGL2PSAction->enableFileWriting();
767  if (beginWriteAction) {
768 
769  // Set the viewport
770  // fGL2PSAction->setViewport(0, 0, getRealPrintSizeX(),getRealPrintSizeY());
771  // By default, we choose the line width (trajectories...)
772  fGL2PSAction->setLineWidth(fGl2psDefaultLineWith);
773  // By default, we choose the point size (markers...)
774  fGL2PSAction->setPointSize(fGl2psDefaultPointSize);
775 
776  DrawView ();
777  endWriteAction = fGL2PSAction->disableFileWriting();
778  }
779  if ((! endWriteAction) || (! beginWriteAction)) {
780  extendBuffer = fGL2PSAction->extendBufferSize();
781  }
782  }
783  fGL2PSAction->resetBufferSizeParameters();
784 
785  if (!extendBuffer ) {
786  G4cerr << "gl2ps buffer size is not big enough to print this geometry. Thy to extend it. No output produced"<< G4endl;
787  }
788  if (!beginWriteAction ) {
789  G4cerr << "Error while writing in the file "<<getRealPrintFilename().c_str()<<". Check read/write access No output produced" << G4endl;
790  }
791  if (!endWriteAction ) {
792  G4cerr << "gl2ps error. No output produced" << G4endl;
793  }
794  fWinSize_x = X;
795  fWinSize_y = Y;
796 
797  // Reset for next time (useful is size change)
798  // fPrintSizeX = 0;
799  // fPrintSizeY = 0;
800 
801  return true;
802 }
803 
804 unsigned int G4OpenGLViewer::getWinWidth() {
805  return fWinSize_x;
806 }
807 
808 unsigned int G4OpenGLViewer::getWinHeight() {
809  return fWinSize_y;
810 }
811 
812 G4bool G4OpenGLViewer::sizeHasChanged() {
813  return fSizeHasChanged;
814 }
815 
816 G4int G4OpenGLViewer::getRealPrintSizeX() {
817  if (fPrintSizeX == -1) {
818  return fWinSize_x;
819  }
820  GLint dims[2];
821  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
822 
823  // L.Garnier 01-2010: Some problems with mac 10.6
824  if ((dims[0] !=0 ) && (dims[1] !=0)) {
825  if (fPrintSizeX > dims[0]){
826  return dims[0];
827  }
828  }
829  if (fPrintSizeX < -1){
830  return 0;
831  }
832  return fPrintSizeX;
833 }
834 
835 G4int G4OpenGLViewer::getRealPrintSizeY() {
836  if (fPrintSizeY == -1) {
837  return fWinSize_y;
838  }
839  GLint dims[2];
840  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
841 
842  // L.Garnier 01-2010: Some problems with mac 10.6
843  if ((dims[0] !=0 ) && (dims[1] !=0)) {
844  if (fPrintSizeY > dims[1]){
845  return dims[1];
846  }
847  }
848  if (fPrintSizeY < -1){
849  return 0;
850  }
851  return fPrintSizeY;
852 }
853 
854 void G4OpenGLViewer::setPrintSize(G4int X, G4int Y) {
855  fPrintSizeX = X;
856  fPrintSizeY = Y;
857 }
858 
859 void G4OpenGLViewer::setPrintFilename(G4String name,G4bool inc) {
860  if (name != "") {
861  fPrintFilename = name;
862  } else {
863  fPrintFilename = "G4OpenGL"; // by default
864  }
865  if (inc) {
866  fPrintFilenameIndex=0;
867  } else {
868  fPrintFilenameIndex=-1;
869  }
870 }
871 
872 std::string G4OpenGLViewer::getRealPrintFilename() {
873  std::string temp = fPrintFilename;
874  if (fPrintFilenameIndex != -1) {
875  temp += std::string("_");
876  std::ostringstream os;
877  os << fPrintFilenameIndex;
878  std::string nb_str = os.str();
879  temp += nb_str;
880  }
881  temp += ".eps";
882  return temp;
883 }
884 
885 GLdouble G4OpenGLViewer::getSceneNearWidth()
886 {
887  if (!fSceneHandler.GetScene()) {
888  return 0;
889  }
890  const G4Point3D targetPoint
891  = fSceneHandler.GetScene()->GetStandardTargetPoint()
892  + fVP.GetCurrentTargetPoint ();
893  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
894  if(radius<=0.) radius = 1.;
895  const G4double cameraDistance = fVP.GetCameraDistance (radius);
896  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
897  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
898 }
899 
900 GLdouble G4OpenGLViewer::getSceneFarWidth()
901 {
902  if (!fSceneHandler.GetScene()) {
903  return 0;
904  }
905  const G4Point3D targetPoint
906  = fSceneHandler.GetScene()->GetStandardTargetPoint()
907  + fVP.GetCurrentTargetPoint ();
908  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
909  if(radius<=0.) radius = 1.;
910  const G4double cameraDistance = fVP.GetCameraDistance (radius);
911  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
912  const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
913  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
914 }
915 
916 
917 GLdouble G4OpenGLViewer::getSceneDepth()
918 {
919  if (!fSceneHandler.GetScene()) {
920  return 0;
921  }
922  const G4Point3D targetPoint
923  = fSceneHandler.GetScene()->GetStandardTargetPoint()
924  + fVP.GetCurrentTargetPoint ();
925  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
926  if(radius<=0.) radius = 1.;
927  const G4double cameraDistance = fVP.GetCameraDistance (radius);
928  const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
929  return fVP.GetFarDistance (cameraDistance, pnear, radius)- pnear;
930 }
931 
932 
933 
934 void G4OpenGLViewer::rotateScene(G4double dx, G4double dy)
935 {
936  if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
937  rotateSceneInViewDirection(dx,dy);
938  } else {
939  if( dx != 0) {
940  rotateSceneThetaPhi(dx,0);
941  }
942  if( dy != 0) {
943  rotateSceneThetaPhi(0,dy);
944  }
945  }
946 }
947 
948 
949 void G4OpenGLViewer::rotateSceneToggle(G4double dx, G4double dy)
950 {
951  if (fVP.GetRotationStyle() != G4ViewParameters::freeRotation) {
952  rotateSceneInViewDirection(dx,dy);
953  } else {
954  if( dx != 0) {
955  rotateSceneThetaPhi(dx,0);
956  }
957  if( dy != 0) {
958  rotateSceneThetaPhi(0,dy);
959  }
960  }
961 }
962 
963 void G4OpenGLViewer::rotateSceneThetaPhi(G4double dx, G4double dy)
964 {
965  if (!fSceneHandler.GetScene()) {
966  return;
967  }
968 
969  G4Vector3D vp;
970  G4Vector3D up;
971 
972  G4Vector3D xprime;
973  G4Vector3D yprime;
974  G4Vector3D zprime;
975 
976  G4double delta_alpha;
977  G4double delta_theta;
978 
979  G4Vector3D new_vp;
980  G4Vector3D new_up;
981 
982  G4double cosalpha;
983  G4double sinalpha;
984 
985  G4Vector3D a1;
986  G4Vector3D a2;
987  G4Vector3D delta;
988  G4Vector3D viewPoint;
989 
990 
991  //phi spin stuff here
992 
993  vp = fVP.GetViewpointDirection ().unit ();
994  up = fVP.GetUpVector ().unit ();
995 
996  yprime = (up.cross(vp)).unit();
997  zprime = (vp.cross(yprime)).unit();
998 
999  if (fVP.GetLightsMoveWithCamera()) {
1000  delta_alpha = dy * fRot_sens;
1001  delta_theta = -dx * fRot_sens;
1002  } else {
1003  delta_alpha = -dy * fRot_sens;
1004  delta_theta = dx * fRot_sens;
1005  }
1006 
1007  delta_alpha *= deg;
1008  delta_theta *= deg;
1009 
1010  new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
1011 
1012  // to avoid z rotation flipping
1013  // to allow more than 360° rotation
1014 
1015  if (fVP.GetLightsMoveWithCamera()) {
1016  new_up = (new_vp.cross(yprime)).unit();
1017  if (new_vp.z()*vp.z() <0) {
1018  new_up.set(new_up.x(),-new_up.y(),new_up.z());
1019  }
1020  } else {
1021  new_up = up;
1022  if (new_vp.z()*vp.z() <0) {
1023  new_up.set(new_up.x(),-new_up.y(),new_up.z());
1024  }
1025  }
1026  fVP.SetUpVector(new_up);
1028  // Rotates by fixed azimuthal angle delta_theta.
1029 
1030  cosalpha = new_up.dot (new_vp.unit());
1031  sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
1032  yprime = (new_up.cross (new_vp.unit())).unit ();
1033  xprime = yprime.cross (new_up);
1034  // Projection of vp on plane perpendicular to up...
1035  a1 = sinalpha * xprime;
1036  // Required new projection...
1037  a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
1038  // Required Increment vector...
1039  delta = a2 - a1;
1040  // So new viewpoint is...
1041  viewPoint = new_vp.unit() + delta;
1042 
1043  fVP.SetViewAndLights (viewPoint);
1044 }
1045 
1046 
1047 void G4OpenGLViewer::rotateSceneInViewDirection(G4double dx, G4double dy)
1048 {
1049  if (!fSceneHandler.GetScene()) {
1050  return;
1051  }
1052 
1053  G4Vector3D vp;
1054  G4Vector3D up;
1055 
1056  G4Vector3D xprime;
1057  G4Vector3D yprime;
1058  G4Vector3D zprime;
1059 
1060  G4Vector3D new_vp;
1061  G4Vector3D new_up;
1062 
1063  G4Vector3D a1;
1064  G4Vector3D a2;
1065  G4Vector3D delta;
1066  G4Vector3D viewPoint;
1067 
1068  dx = dx/100;
1069  dy = dy/100;
1070 
1071  //phi spin stuff here
1072 
1073 #ifdef G4DEBUG_VIS_OGL
1074  printf("G4OpenGLViewer::rotateScene dx:%f dy:%f delta:%f\n",dx,dy, fRot_sens);
1075 #endif
1076 
1077  vp = fVP.GetViewpointDirection ().unit();
1078  up = fVP.GetUpVector ().unit();
1079 
1080  G4Vector3D zPrimeVector = G4Vector3D(up.y()*vp.z()-up.z()*vp.y(),
1081  up.z()*vp.x()-up.x()*vp.z(),
1082  up.x()*vp.y()-up.y()*vp.x());
1083 
1084  viewPoint = vp/fRot_sens + (zPrimeVector*dx - up*dy) ;
1085  new_up = G4Vector3D(viewPoint.y()*zPrimeVector.z()-viewPoint.z()*zPrimeVector.y(),
1086  viewPoint.z()*zPrimeVector.x()-viewPoint.x()*zPrimeVector.z(),
1087  viewPoint.x()*zPrimeVector.y()-viewPoint.y()*zPrimeVector.x());
1088 
1089  G4Vector3D new_upUnit = new_up.unit();
1090 
1091 
1092 
1093  fVP.SetUpVector(new_upUnit);
1094  fVP.SetViewAndLights (viewPoint);
1095 }
1096 
1097 
1098 #endif