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

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

test pour GL_POINTS au lieu de glBitmap

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