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

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

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

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