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

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

marche, mais en cours de debug sur OI

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