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

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

Update in code, try to mutualise everything between Stored and immediate Qt Viewers

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