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

Last change on this file since 939 was 939, checked in by garnier, 17 years ago

OK, juste avant de suppr les comm inutiles

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