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

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

update with CVS

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