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

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

ca marche

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