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

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

print PS marche, mais plein de msg de debug a supprimer

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