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

Last change on this file since 831 was 801, checked in by garnier, 18 years ago

r840@wl-72126: garnier | 2008-05-16 17:45:55 +0200
en test avec de nouveaux calculs...

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