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

Last change on this file since 940 was 940, checked in by garnier, 16 years ago

Ok dans CVS

  • Property svn:mime-type set to text/cpp
File size: 34.0 KB
RevLine 
[529]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//
[940]27// $Id: G4OpenGLViewer.cc,v 1.49 2009/03/05 11:04:20 lgarnier Exp $
[873]28// GEANT4 tag $Name:  $
[529]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"
[923]40#include "G4OpenGL2PSAction.hh"
[529]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"
[593]49#include "G4AttHolder.hh"
50#include "G4AttCheck.hh"
[918]51
[923]52// GL2PS
53#include "Geant4_gl2ps.h"
54
[593]55#include <sstream>
[529]56
[593]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
[529]87G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
88G4VViewer (scene, -1),
[916]89fPrintFilename ("G4OpenGL.eps"),
90fPrintColour (true),
91fVectoredPs (true),
[593]92fOpenGLSceneHandler(scene),
[529]93background (G4Colour(0.,0.,0.)),
94transparency_enabled (true),
95antialiasing_enabled (false),
96haloing_enabled (false),
[789]97fStartTime(-DBL_MAX),
98fEndTime(DBL_MAX),
[529]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.),
[916]114fDisplayLightFrontBlue(0.),
115fPointSize (0)
[529]116{
117  // Make changes to view parameters for OpenGL...
118  fVP.SetAutoRefresh(true);
119  fDefaultVP.SetAutoRefresh(true);
[897]120  fWinSize_x = fVP.GetWindowSizeHintX();
121  fWinSize_y = fVP.GetWindowSizeHintY();
[529]122
[921]123  fGL2PSAction = new G4OpenGL2PSAction();
124
[529]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
[906]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
[529]170void G4OpenGLViewer::SetView () {
[858]171
172  if (!fSceneHandler.GetScene()) {
[908]173    G4cerr << "G4OpenGLStoredViewer: Creating a Viewer without a scene is not allowed. \nPlease use /vis/scene/create before /vis/open/.... "
[858]174           << G4endl;
175    return;
176  }
[529]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();
[906]204  const GLdouble pnear  = fVP.GetNearDistance (cameraDistance, radius);
205  const GLdouble pfar   = fVP.GetFarDistance  (cameraDistance, pnear, radius);
[529]206  const GLdouble right  = fVP.GetFrontHalfHeight (pnear, radius);
207  const GLdouble left   = -right;
208  const GLdouble bottom = left;
209  const GLdouble top    = right;
210 
[906]211  // FIXME
212  ResizeGLView();
[908]213  //SHOULD SetWindowsSizeHint()...
[906]214
[529]215  glMatrixMode (GL_PROJECTION); // set up Frustum.
216  glLoadIdentity();
217
[906]218  const G4Vector3D scaleFactor = fVP.GetScaleFactor();
219  glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
[529]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);
[908]226  } 
[906]227
[529]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.
[906]244
[529]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
[593]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
[938]399bool G4OpenGLViewer::printVectoredEPS() {
[593]400
401  // Print vectored PostScript
402 
403  G4int size = 5000000;
[754]404  GLfloat* feedback_buffer = new GLfloat[size];
[593]405  glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
406  glRenderMode (GL_FEEDBACK);
407 
408  DrawView();
[754]409
410  GLint returned;
[593]411  returned = glRenderMode (GL_RENDER);
412 
[754]413  FILE* file;
[916]414  if (!fPrintFilename.empty()) {
415    file = fopen (fPrintFilename.c_str(), "w");
[593]416    if (file) {
417      spewWireframeEPS (file, returned, feedback_buffer, "rendereps");
[918]418      fclose(file);
[593]419    } else {
[938]420      G4cerr << "Could not open " <<fPrintFilename.c_str() <<" for writing"<< G4endl;
421      return false;
[593]422    }
423  } else {
424    printBuffer (returned, feedback_buffer);
425  }
426
427  delete[] feedback_buffer;
[938]428  return true;
[593]429}
430
431void G4OpenGLViewer::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer)
432{
433  G4int i;
434
435  printf("  ");
436  for (i = 0; i < 7; i++) {
437    printf("%4.2f ", buffer[size - (*count)]);
438    *count = *count - 1;
439  }
440  printf("\n");
441}
442
443void G4OpenGLViewer::spewWireframeEPS (FILE* file, GLint size, GLfloat* buffer, const char* cr) {
444
445  GLfloat EPS_GOURAUD_THRESHOLD=0.1;
446
447  GLfloat clearColor[4], viewport[4];
448  GLfloat lineWidth;
449  G4int i;
450
451  glGetFloatv (GL_VIEWPORT, viewport);
452  glGetFloatv (GL_COLOR_CLEAR_VALUE, clearColor);
453  glGetFloatv (GL_LINE_WIDTH, &lineWidth);
[916]454  glGetFloatv (GL_POINT_SIZE, &fPointSize);
[593]455
456  fputs ("%!PS-Adobe-2.0 EPSF-2.0\n", file);
457  fprintf (file, "%%%%Creator: %s (using OpenGL feedback)\n", cr);
458  fprintf (file, "%%%%BoundingBox: %g %g %g %g\n", viewport[0], viewport[1], viewport[2], viewport[3]);
459  fputs ("%%EndComments\n", file);
460  fputs ("\n", file);
461  fputs ("gsave\n", file);
462  fputs ("\n", file);
463
464  fputs ("% the gouraudtriangle PostScript fragment below is free\n", file);
465  fputs ("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file);
466  fprintf (file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD);
467  for (i=0; gouraudtriangleEPS[i]; i++) {
468    fprintf (file, "%s\n", gouraudtriangleEPS[i]);
469  }
470
471  fprintf(file, "\n%g setlinewidth\n", lineWidth);
472 
473  fprintf (file, "%g %g %g setrgbcolor\n", clearColor[0], clearColor[1], clearColor[2]);
474  fprintf (file, "%g %g %g %g rectfill\n\n", viewport[0], viewport[1], viewport[2], viewport[3]);
475
476  spewSortedFeedback (file, size, buffer);
477
478  fputs ("grestore\n\n", file);
479  fputs ("showpage\n", file);
480
481  fclose(file);
482}
483
484void G4OpenGLViewer::printBuffer (GLint size, GLfloat* buffer) {
485
486  GLint count;
487  G4int token, nvertices;
488
489  count=size;
490  while(count) {
491    token=G4int (buffer[size-count]);
492    count--;
493    switch (token) {
494
495    case GL_PASS_THROUGH_TOKEN:
496      printf ("GL_PASS_THROUGH_TOKEN\n");
497      printf ("  %4.2f\n", buffer[size-count]);
498      count--;
499      break;
500
501    case GL_POINT_TOKEN:
502      printf ("GL_POINT_TOKEN\n");
503      print3DcolorVertex (size, &count, buffer);
504      break;
505
506    case GL_LINE_TOKEN:
507      printf ("GL_LINE_TOKEN\n");
508      print3DcolorVertex (size, &count, buffer);
509      print3DcolorVertex (size, &count, buffer);
510      break;
511     
512    case GL_LINE_RESET_TOKEN:
513      printf ("GL_LINE_RESET_TOKEN\n");
514      print3DcolorVertex (size, &count, buffer);
515      print3DcolorVertex (size, &count, buffer);
516      break;
517
518    case GL_POLYGON_TOKEN:
519      printf ("GL_POLYGON_TOKEN\n");
520      nvertices=G4int (buffer[size-count]);
521      count--;
522      for (; nvertices>0; nvertices--) {
523        print3DcolorVertex (size, &count, buffer);
524      }
525    }
526  }
527}
528
529G4float* G4OpenGLViewer::spewPrimitiveEPS (FILE* file, GLfloat* loc) {
530 
531  G4int token;
532  G4int nvertices, i;
533  GLfloat red, green, blue, intensity;
534  G4int smooth;
535  GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax;
536  G4int steps;
537  Feedback3Dcolor *vertex;
538  GLfloat xstep(0.), ystep(0.), rstep(0.), gstep(0.), bstep(0.);
539  GLfloat xnext(0.), ynext(0.), rnext(0.), gnext(0.), bnext(0.), distance(0.);
540
541  token=G4int (*loc);
542  loc++;
543  switch (token) {
544  case GL_LINE_RESET_TOKEN:
545  case GL_LINE_TOKEN:
546    vertex=(Feedback3Dcolor*)loc;
547    dr=vertex[1].red - vertex[0].red;
548    dg=vertex[1].green - vertex[0].green;
549    db=vertex[1].blue - vertex[0].blue;
550
[916]551    if (!fPrintColour) {
[593]552      dr+=(dg+db);
553      dr/=3.0;
554      dg=dr;
555      db=dr;
556    }
557
558    if (dr!=0 || dg!=0 || db!=0) {
559      dx=vertex[1].x - vertex[0].x;
560      dy=vertex[1].y - vertex[0].y;
561      distance=std::sqrt(dx*dx + dy*dy);
562
563      absR=std::fabs(dr);
564      absG=std::fabs(dg);
565      absB=std::fabs(db);
566
567      #define Max(a, b) (((a)>(b))?(a):(b))
568
569      #define EPS_SMOOTH_LINE_FACTOR 0.06
570
571      colormax=Max(absR, Max(absG, absB));
572      steps=Max(1, G4int (colormax*distance*EPS_SMOOTH_LINE_FACTOR));
573     
574      xstep=dx/steps;
575      ystep=dy/steps;
576
577      rstep=dr/steps;
578      gstep=dg/steps;
579      bstep=db/steps;
580
581      xnext=vertex[0].x;
582      ynext=vertex[0].y;
583      rnext=vertex[0].red;
584      gnext=vertex[0].green;
585      bnext=vertex[0].blue;
586
[916]587      if (!fPrintColour) {
[593]588        rnext+=(gnext+bnext);
589        rnext/=3.0;
590        gnext=rnext;
591        bnext=rnext;
592      }
593
594      xnext -= xstep/2.0;
595      ynext -= ystep/2.0;
596      rnext -= rstep/2.0;
597      gnext -= gstep/2.0;
598      bnext -= bstep/2.0;
599    } else {
600      steps=0;
601    }
[916]602    if (fPrintColour) {
[593]603      fprintf (file, "%g %g %g setrgbcolor\n",
604               vertex[0].red, vertex[0].green, vertex[0].blue);
605    } else {
606      intensity = (vertex[0].red + vertex[0].green + vertex[0].blue) / 3.0;
607      fprintf (file, "%g %g %g setrgbcolor\n",
608               intensity, intensity, intensity);
609    }     
610    fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
611
612    for (i=0; i<steps; i++) {
613
614      xnext += xstep;
615      ynext += ystep;
616      rnext += rstep;
617      gnext += gstep;
618      bnext += bstep;
619
620      fprintf (file, "%g %g lineto stroke\n", xnext, ynext);
621      fprintf (file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext);
622      fprintf (file, "%g %g moveto\n", xnext, ynext);
623    }
624    fprintf (file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y);
625
626    loc += 14;
627    break;
628
629  case GL_POLYGON_TOKEN:
630    nvertices = G4int (*loc);
631    loc++;
632    vertex=(Feedback3Dcolor*)loc;
633    if (nvertices>0) {
634      red=vertex[0].red;
635      green=vertex[0].green;
636      blue=vertex[0].blue;
637      smooth=0;
638     
[916]639      if (!fPrintColour) {
[593]640        red+=(green+blue);
641        red/=3.0;
642        green=red;
643        blue=red;
644      }
645     
[916]646      if (fPrintColour) {
[593]647        for (i=1; i<nvertices; i++) {
648          if (red!=vertex[i].red || green!=vertex[i].green || blue!=vertex[i].blue) {
649            smooth=1;
650            break;
651          }
652        }
653      } else {
654        for (i=1; i<nvertices; i++) {
655          intensity = vertex[i].red + vertex[i].green + vertex[i].blue;
656          intensity/=3.0;
657          if (red!=intensity) {
658            smooth=1;
659            break;
660          }
661        }
662      }
663
664      if (smooth) {
665        G4int triOffset;
666        for (i=0; i<nvertices-2; i++) {
667          triOffset = i*7;
668          fprintf (file, "[%g %g %g %g %g %g]",
669                   vertex[0].x, vertex[i+1].x, vertex[i+2].x,
670                   vertex[0].y, vertex[i+1].y, vertex[i+2].y);
[916]671          if (fPrintColour) {
[593]672            fprintf (file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n",
673                     vertex[0].red, vertex[0].green, vertex[0].blue,
674                     vertex[i+1].red, vertex[i+1].green, vertex[i+1].blue,
675                     vertex[i+2].red, vertex[i+2].green, vertex[i+2].blue);
676          } else {
677
678            intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
679            intensity/=3.0;
680            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
681
682            intensity = vertex[1].red + vertex[1].green + vertex[1].blue;
683            intensity/=3.0;
684            fprintf (file, " [%g %g %g]", intensity, intensity, intensity);
685
686            intensity = vertex[2].red + vertex[2].green + vertex[2].blue;
687            intensity/=3.0;
688            fprintf (file, " [%g %g %g] gouraudtriangle\n", intensity, intensity, intensity);
689          }
690        }
691      } else {
692        fprintf (file, "newpath\n");
693        fprintf (file, "%g %g %g setrgbcolor\n", red, green, blue);
694        fprintf (file, "%g %g moveto\n", vertex[0].x, vertex[0].y);
695        for (i=1; i<nvertices; i++) {
696          fprintf (file, "%g %g lineto\n", vertex[i].x, vertex[i].y);
697        }
698        fprintf (file, "closepath fill\n\n");
699      }
700    }
701    loc += nvertices*7;
702    break;
703
704  case GL_POINT_TOKEN:
705    vertex=(Feedback3Dcolor*)loc;
[916]706    if (fPrintColour) {
[593]707      fprintf (file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue);
708    } else {
709      intensity = vertex[0].red + vertex[0].green + vertex[0].blue;
710      intensity/=3.0;
711      fprintf (file, "%g %g %g setrgbcolor\n", intensity, intensity, intensity);
712    }     
[916]713    fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, fPointSize / 2.0);
[593]714    loc += 7;           /* Each vertex element in the feedback
715                           buffer is 7 GLfloats. */
716    break;
717  default:
718    /* XXX Left as an excersie to the reader. */
719    static G4bool spewPrimitiveEPSWarned = false;
720    if (!spewPrimitiveEPSWarned) {
721      std::ostringstream oss;
722      oss <<
723        "Incomplete implementation.  Unexpected token (" << token << ")."
724        "\n  (Seems to be caused by text.)";
725      G4Exception("G4OpenGLViewer::spewPrimitiveEPS",
726                  "Unexpected token",
727                  JustWarning,
728                  oss.str().c_str());
729      spewPrimitiveEPSWarned = true;
730    }
731  }
732  return loc;
733}
734
735typedef struct G4OpenGLViewerDepthIndex {
736  GLfloat *ptr;
737  GLfloat depth;
738} DepthIndex;
739
740extern "C" {
741  int G4OpenGLViewercompare(const void *a, const void *b)
742  {
743    const DepthIndex *p1 = (DepthIndex *) a;
744    const DepthIndex *p2 = (DepthIndex *) b;
745    GLfloat diff = p2->depth - p1->depth;
746   
747    if (diff > 0.0) {
748      return 1;
749    } else if (diff < 0.0) {
750      return -1;
751    } else {
752      return 0;
753    }
754  }
755}
756
[914]757GLubyte* G4OpenGLViewer::grabPixels (int inColor, unsigned int width, unsigned int height) {
758 
759  GLubyte* buffer;
760  GLint swapbytes, lsbfirst, rowlength;
761  GLint skiprows, skippixels, alignment;
762  GLenum format;
763  int size;
764
765  if (inColor) {
766    format = GL_RGB;
767    size = width*height*3;
768  } else {
769    format = GL_LUMINANCE;
770    size = width*height*1;
771  }
772
773  buffer = new GLubyte[size];
774  if (buffer == NULL)
775    return NULL;
776
777  glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
778  glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
779  glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
780
781  glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
782  glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
783  glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
784
785  glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
786  glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
787  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
788
789  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
790  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
791  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
792
793  glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
794
795  glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
796  glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
797  glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
798 
799  glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
800  glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
801  glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
802 
803  return buffer;
804}
805
[938]806int G4OpenGLViewer::printNonVectoredEPS (int inColour,
[914]807                                unsigned int width,
808                                unsigned int height) {
809
810  FILE* fp;
811  GLubyte* pixels;
812  GLubyte* curpix;
813  int components, pos, i;
814
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 
[938]825  fp = fopen (fPrintFilename.c_str(), "w");
[914]826  if (fp == NULL) {
827    return 2;
828  }
829 
830  fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
[938]831  fprintf (fp, "%%%%Title: %s\n", fPrintFilename.c_str());
[914]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
[918]882
[938]883bool G4OpenGLViewer::printGl2PS(unsigned int width,unsigned int height) {
[918]884
[938]885  if (!fGL2PSAction) return false;
[929]886
[938]887  fGL2PSAction->setFileName(fPrintFilename.c_str());
888  // try to resize
889  int X = fWinSize_x;
890  int Y = fWinSize_y;
[929]891
[938]892  fWinSize_x = width;
893  fWinSize_y = height;
894  ResizeGLView();
[921]895  if (fGL2PSAction->enableFileWriting()) {
[931]896    DrawView ();
[921]897    fGL2PSAction->disableFileWriting();
898  }
[929]899
[938]900  fWinSize_x = X;
901  fWinSize_y = Y;
902  ResizeGLView();
[929]903
[938]904  return true;
[918]905}
906
[712]907GLdouble G4OpenGLViewer::getSceneNearWidth()
908{
909  const G4Point3D targetPoint
910    = fSceneHandler.GetScene()->GetStandardTargetPoint()
911    + fVP.GetCurrentTargetPoint ();
912  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
913  if(radius<=0.) radius = 1.;
914  const G4double cameraDistance = fVP.GetCameraDistance (radius);
915  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
916  return 2 * fVP.GetFrontHalfHeight (pnear, radius);
917}
918
919GLdouble G4OpenGLViewer::getSceneFarWidth()
920{
921  const G4Point3D targetPoint
922    = fSceneHandler.GetScene()->GetStandardTargetPoint()
923    + fVP.GetCurrentTargetPoint ();
924  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
925  if(radius<=0.) radius = 1.;
926  const G4double cameraDistance = fVP.GetCameraDistance (radius);
927  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
928  const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
929  return 2 * fVP.GetFrontHalfHeight (pfar, radius);
930}
931
932
933GLdouble G4OpenGLViewer::getSceneDepth()
934{
935  const G4Point3D targetPoint
936    = fSceneHandler.GetScene()->GetStandardTargetPoint()
937    + fVP.GetCurrentTargetPoint ();
938  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
939  if(radius<=0.) radius = 1.;
940  const G4double cameraDistance = fVP.GetCameraDistance (radius);
941  const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
942  return fVP.GetFarDistance  (cameraDistance, pnear, radius)- pnear;
943}
944
945
[593]946void G4OpenGLViewer::spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer)
947{
948  int token;
949  GLfloat *loc, *end;
950  Feedback3Dcolor *vertex;
951  GLfloat depthSum;
952  int nprimitives, item;
953  DepthIndex *prims;
954  int nvertices, i;
955
956  end = buffer + size;
957
958  /* Count how many primitives there are. */
959  nprimitives = 0;
960  loc = buffer;
961  while (loc < end) {
962    token = int (*loc);
963    loc++;
964    switch (token) {
965    case GL_LINE_TOKEN:
966    case GL_LINE_RESET_TOKEN:
967      loc += 14;
968      nprimitives++;
969      break;
970    case GL_POLYGON_TOKEN:
971      nvertices = int (*loc);
972      loc++;
973      loc += (7 * nvertices);
974      nprimitives++;
975      break;
976    case GL_POINT_TOKEN:
977      loc += 7;
978      nprimitives++;
979      break;
980    default:
981      /* XXX Left as an excersie to the reader. */
982      static G4bool spewSortedFeedbackWarned = false;
983      if (!spewSortedFeedbackWarned) {
984        std::ostringstream oss;
985        oss <<
986          "Incomplete implementation.  Unexpected token (" << token << ")."
987          "\n  (Seems to be caused by text.)";
988        G4Exception("G4OpenGLViewer::spewSortedFeedback",
989                    "Unexpected token",
990                    JustWarning,
991                    oss.str().c_str());
992        spewSortedFeedbackWarned = true;
993      }
994      nprimitives++;
995    }
996  }
997
998  /* Allocate an array of pointers that will point back at
999     primitives in the feedback buffer.  There will be one
1000     entry per primitive.  This array is also where we keep the
1001     primitive's average depth.  There is one entry per
1002     primitive  in the feedback buffer. */
1003  prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives);
1004
1005  item = 0;
1006  loc = buffer;
1007  while (loc < end) {
1008    prims[item].ptr = loc;  /* Save this primitive's location. */
1009    token = int (*loc);
1010    loc++;
1011    switch (token) {
1012    case GL_LINE_TOKEN:
1013    case GL_LINE_RESET_TOKEN:
1014      vertex = (Feedback3Dcolor *) loc;
1015      depthSum = vertex[0].z + vertex[1].z;
1016      prims[item].depth = depthSum / 2.0;
1017      loc += 14;
1018      break;
1019    case GL_POLYGON_TOKEN:
1020      nvertices = int (*loc);
1021      loc++;
1022      vertex = (Feedback3Dcolor *) loc;
1023      depthSum = vertex[0].z;
1024      for (i = 1; i < nvertices; i++) {
1025        depthSum += vertex[i].z;
1026      }
1027      prims[item].depth = depthSum / nvertices;
1028      loc += (7 * nvertices);
1029      break;
1030    case GL_POINT_TOKEN:
1031      vertex = (Feedback3Dcolor *) loc;
1032      prims[item].depth = vertex[0].z;
1033      loc += 7;
1034      break;
1035    default:
1036      /* XXX Left as an excersie to the reader. */
1037      assert(1);
1038    }
1039    item++;
1040  }
1041  assert(item == nprimitives);
1042
1043  /* Sort the primitives back to front. */
1044  qsort(prims, nprimitives, sizeof(DepthIndex), G4OpenGLViewercompare);
1045
1046  /* Understand that sorting by a primitives average depth
1047     doesn't allow us to disambiguate some cases like self
1048     intersecting polygons.  Handling these cases would require
1049     breaking up the primitives.  That's too involved for this
1050     example.  Sorting by depth is good enough for lots of
1051     applications. */
1052
1053  /* Emit the Encapsulated PostScript for the primitives in
1054     back to front order. */
1055  for (item = 0; item < nprimitives; item++) {
1056    (void) spewPrimitiveEPS(file, prims[item].ptr);
1057  }
1058
1059  free(prims);
1060}
1061
[798]1062void G4OpenGLViewer::rotateScene(G4double dx, G4double dy,G4double deltaRotation)
1063{
1064
1065  G4Vector3D vp;
1066  G4Vector3D up;
1067 
1068  G4Vector3D xprime;
1069  G4Vector3D yprime;
1070  G4Vector3D zprime;
1071 
1072  G4double delta_alpha;
1073  G4double delta_theta;
1074 
1075  G4Vector3D new_vp;
1076  G4Vector3D new_up;
1077 
1078  G4double cosalpha;
1079  G4double sinalpha;
1080 
1081  G4Vector3D a1;
1082  G4Vector3D a2;
1083  G4Vector3D delta;
1084  G4Vector3D viewPoint;
1085
1086   
1087  //phi spin stuff here
1088 
1089  vp = fVP.GetViewpointDirection ().unit ();
1090  up = fVP.GetUpVector ().unit ();
1091 
1092  yprime = (up.cross(vp)).unit();
1093  zprime = (vp.cross(yprime)).unit();
1094 
1095  if (fVP.GetLightsMoveWithCamera()) {
1096    delta_alpha = dy * deltaRotation;
1097    delta_theta = -dx * deltaRotation;
1098  } else {
1099    delta_alpha = -dy * deltaRotation;
1100    delta_theta = dx * deltaRotation;
1101  }   
1102 
1103  delta_alpha *= deg;
1104  delta_theta *= deg;
1105 
1106  new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
1107 
1108  // to avoid z rotation flipping
1109  // to allow more than 360° rotation
[847]1110
[801]1111  const G4Point3D targetPoint
1112    = fSceneHandler.GetScene()->GetStandardTargetPoint()
1113    + fVP.GetCurrentTargetPoint ();
1114  G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1115  if(radius<=0.) radius = 1.;
1116  const G4double cameraDistance = fVP.GetCameraDistance (radius);
1117  const G4Point3D cameraPosition =
1118    targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
1119
[798]1120  if (fVP.GetLightsMoveWithCamera()) {
1121    new_up = (new_vp.cross(yprime)).unit();
1122    if (new_vp.z()*vp.z() <0) {
1123      new_up.set(new_up.x(),-new_up.y(),new_up.z());
1124    }
1125  } else {
1126    new_up = up;
1127    if (new_vp.z()*vp.z() <0) {
1128      new_up.set(new_up.x(),-new_up.y(),new_up.z());
1129    }
1130  }
1131  fVP.SetUpVector(new_up);
1132  ////////////////
1133  // Rotates by fixed azimuthal angle delta_theta.
1134 
1135  cosalpha = new_up.dot (new_vp.unit());
1136  sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
1137  yprime = (new_up.cross (new_vp.unit())).unit ();
1138  xprime = yprime.cross (new_up);
1139  // Projection of vp on plane perpendicular to up...
1140  a1 = sinalpha * xprime;
1141  // Required new projection...
1142  a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
1143  // Required Increment vector...
1144  delta = a2 - a1;
1145  // So new viewpoint is...
1146  viewPoint = new_vp.unit() + delta;
1147 
1148  fVP.SetViewAndLights (viewPoint);
1149}
1150
[529]1151#endif
Note: See TracBrowser for help on using the repository browser.