Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4OpenGLViewer.cc
Go to the documentation of this file.
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//
28//
29// Andrew Walkden 27th March 1996
30// OpenGL view - opens window, hard copy, etc.
31
32#ifdef G4VIS_BUILD_OPENGL_DRIVER
33
34#include "G4ios.hh"
36#include "G4OpenGLViewer.hh"
39#include "G4OpenGL2PSAction.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 "G4Text.hh"
51
52#ifdef G4OPENGL_VERSION_2
53// We need to have a Wt gl drawer because we will draw inside the WtGL component (ImmediateWtViewer)
54#include "G4OpenGLVboDrawer.hh"
55#endif
56
57// GL2PS
58#include "Geant4_gl2ps.h"
59
60#include <sstream>
61#include <string>
62#include <iomanip>
63
64G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
65G4VViewer (scene, -1),
66#ifdef G4OPENGL_VERSION_2
67fVboDrawer(NULL),
68#endif
69fPrintColour (true),
70fVectoredPs (true),
71fOpenGLSceneHandler(scene),
72background (G4Colour(0.,0.,0.)),
73transparency_enabled (true),
74antialiasing_enabled (false),
75haloing_enabled (false),
76fRot_sens(1.),
77fPan_sens(0.01),
78fWinSize_x(0),
79fWinSize_y(0),
80fDefaultExportImageFormat("pdf"),
81fExportImageFormat("pdf"),
82fExportFilenameIndex(0),
83fPrintSizeX(-1),
84fPrintSizeY(-1),
85fPointSize (0),
86fDefaultExportFilename("G4OpenGL"),
87fSizeHasChanged(0),
88fGl2psDefaultLineWith(1),
89fGl2psDefaultPointSize(2),
90fGlViewInitialized(false),
91fIsGettingPickInfos(false)
92#ifdef G4OPENGL_VERSION_2
93,fShaderProgram(0)
94,fVertexPositionAttribute(0)
95,fVertexNormalAttribute(0)
96,fpMatrixUniform(0)
97,fcMatrixUniform(0)
98,fmvMatrixUniform(0)
99,fnMatrixUniform(0)
100#endif
101{
102 // Make changes to view parameters for OpenGL...
103 fVP.SetAutoRefresh(true);
104 fDefaultVP.SetAutoRefresh(true);
105
106 fGL2PSAction = new G4OpenGL2PSAction();
107
108 // add supported export image format
109 addExportImageFormat("eps");
110 addExportImageFormat("ps");
111 addExportImageFormat("pdf");
112 addExportImageFormat("svg");
113
114 // Change the default name
115 fExportFilename += fDefaultExportFilename + "_" + GetShortName().data();
116
117 // glClearColor (0.0, 0.0, 0.0, 0.0);
118 // glClearDepth (1.0);
119 // glDisable (GL_BLEND);
120 // glDisable (GL_LINE_SMOOTH);
121 // glDisable (GL_POLYGON_SMOOTH);
122
123}
124
125G4OpenGLViewer::~G4OpenGLViewer ()
126{
127 delete fGL2PSAction;
128}
129
130void G4OpenGLViewer::InitializeGLView ()
131{
132#ifdef G4OPENGL_VERSION_2
133 if (fVboDrawer) {
134
135 // First, load a simple shader
136 fShaderProgram = glCreateProgram();
137 Shader vertexShader = glCreateShader(GL_VERTEX_SHADER);
138 const char * vSrc = fVboDrawer->getVertexShaderSrc();
139 glShaderSource(vertexShader, 1, &vSrc, NULL);
140 glCompileShader(vertexShader);
141 glAttachShader(fShaderProgram, vertexShader);
142
143 Shader fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
144 const char * fSrc = fVboDrawer->getFragmentShaderSrc();
145 glShaderSource(fragmentShader, 1, &fSrc, NULL);
146 glCompileShader(fragmentShader);
147
148 glAttachShader(fShaderProgram, fragmentShader);
149 glLinkProgram(fShaderProgram);
150 glUseProgram(fShaderProgram);
151
152 // UniformLocation uColor = getUniformLocation(fShaderProgram, "uColor");
153 // uniform4fv(uColor, [0.0, 0.3, 0.0, 1.0]);
154
155 // Extract the references to the attributes from the shader.
156
157 fVertexPositionAttribute =
158 glGetAttribLocation(fShaderProgram, "aVertexPosition");
159
160
161 glEnableVertexAttribArray(fVertexPositionAttribute);
162
163 // Extract the references the uniforms from the shader
164 fpMatrixUniform = glGetUniformLocation(fShaderProgram, "uPMatrix");
165 fcMatrixUniform = glGetUniformLocation(fShaderProgram, "uCMatrix");
166 fmvMatrixUniform = glGetUniformLocation(fShaderProgram, "uMVMatrix");
167 fnMatrixUniform = glGetUniformLocation(fShaderProgram, "uNMatrix");
168 ftMatrixUniform = glGetUniformLocation(fShaderProgram, "uTMatrix");
169
170 /* glUniformMatrix4fv(fcMatrixUniform, 1, 0, identity);
171 glUniformMatrix4fv(fpMatrixUniform, 1, 0, identity);
172 glUniformMatrix4fv(ftMatrixUniform, 1, 0, identity);
173 glUniformMatrix4fv(fmvMatrixUniform, 1, 0, identity);
174 */
175 // We have to set that in order to avoid calls on opengl commands before all is ready
176 fGlViewInitialized = true;
177 }
178#endif
179
180 if (fWinSize_x == 0) {
181 fWinSize_x = fVP.GetWindowSizeHintX();
182 }
183 if (fWinSize_y == 0) {
184 fWinSize_y = fVP.GetWindowSizeHintY();
185 }
186
187 glClearColor (0.0, 0.0, 0.0, 0.0);
188 glClearDepth (1.0);
189#ifndef G4OPENGL_VERSION_2
190 glDisable (GL_LINE_SMOOTH);
191 glDisable (GL_POLYGON_SMOOTH);
192#endif
193
194// clear the buffers and window?
195 ClearView ();
196 FinishView ();
197
198 glDepthFunc (GL_LEQUAL);
199 glDepthMask (GL_TRUE);
200
201 glEnable (GL_BLEND);
202 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
203
204}
205
206void G4OpenGLViewer::ClearView () {
207 ClearViewWithoutFlush();
208
209 if(!isFramebufferReady()) {
210 return;
211 }
212
213 glFlush();
214}
215
216
217void G4OpenGLViewer::ClearViewWithoutFlush () {
218 // Ready for clear ?
219 // See : http://lists.apple.com/archives/mac-opengl/2012/Jul/msg00038.html
220 if(!isFramebufferReady()) {
221 return;
222 }
223
224 glClearColor (background.GetRed(),
225 background.GetGreen(),
226 background.GetBlue(),
227 1.);
228 glClearDepth (1.0);
229 //Below line does not compile with Mesa includes.
230 //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
231 glClear (GL_COLOR_BUFFER_BIT);
232 glClear (GL_DEPTH_BUFFER_BIT);
233 glClear (GL_STENCIL_BUFFER_BIT);
234}
235
236
237void G4OpenGLViewer::ResizeWindow(unsigned int aWidth, unsigned int aHeight) {
238 if ((fWinSize_x != aWidth) || (fWinSize_y != aHeight)) {
239 fWinSize_x = aWidth;
240 fWinSize_y = aHeight;
241 fSizeHasChanged = true;
242 } else {
243 fSizeHasChanged = false;
244 }
245}
246
247/**
248 * Set the viewport of the scene
249 * MAXIMUM SIZE is :
250 * GLint dims[2];
251 * glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
252 */
253void G4OpenGLViewer::ResizeGLView()
254{
255 // Check size
256 GLint dims[2];
257 dims[0] = 0;
258 dims[1] = 0;
259
260 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
261
262 if ((dims[0] !=0 ) && (dims[1] !=0)) {
263
264 if (fWinSize_x > (unsigned)dims[0]) {
265 G4cerr << "Try to resize view greater than max X viewport dimension. Desired size "<<fWinSize_x <<" is resize to "<< dims[0] << G4endl;
266 fWinSize_x = dims[0];
267 }
268 if (fWinSize_y > (unsigned)dims[1]) {
269 G4cerr << "Try to resize view greater than max Y viewport dimension. Desired size "<<fWinSize_y <<" is resize to "<< dims[1] << G4endl;
270 fWinSize_y = dims[1];
271 }
272 }
273
274 glViewport(0, 0, fWinSize_x,fWinSize_y);
275
276
277}
278
279
280void G4OpenGLViewer::SetView () {
281 // if getting pick infos, should not resize the view.
282 if (fIsGettingPickInfos) return;
283
284 if (!fSceneHandler.GetScene()) {
285 return;
286 }
287 // Calculates view representation based on extent of object being
288 // viewed and (initial) viewpoint. (Note: it can change later due
289 // to user interaction via visualization system's GUI.)
290
291 // Lighting.
292 GLfloat lightPosition [4];
293 lightPosition [0] = fVP.GetActualLightpointDirection().x();
294 lightPosition [1] = fVP.GetActualLightpointDirection().y();
295 lightPosition [2] = fVP.GetActualLightpointDirection().z();
296 lightPosition [3] = 0.;
297 // Light position is "true" light direction, so must come after gluLookAt.
298 GLfloat ambient [] = { 0.2f, 0.2f, 0.2f, 1.f};
299 GLfloat diffuse [] = { 0.8f, 0.8f, 0.8f, 1.f};
300 glEnable (GL_LIGHT0);
301 glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
302 glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
303
304 G4double ratioX = 1;
305 G4double ratioY = 1;
306 if (fWinSize_y > fWinSize_x) {
307 ratioX = ((G4double)fWinSize_y) / ((G4double)fWinSize_x);
308 }
309 if (fWinSize_x > fWinSize_y) {
310 ratioY = ((G4double)fWinSize_x) / ((G4double)fWinSize_y);
311 }
312
313 // Get radius of scene, etc.
314 // Note that this procedure properly takes into account zoom, dolly and pan.
315 const G4Point3D targetPoint
316 = fSceneHandler.GetScene()->GetStandardTargetPoint()
317 + fVP.GetCurrentTargetPoint ();
318 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
319 if(radius<=0.) radius = 1.;
320 const G4double cameraDistance = fVP.GetCameraDistance (radius);
321 const G4Point3D cameraPosition =
322 targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
323 const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
324 const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
325 const GLdouble right = fVP.GetFrontHalfHeight (pnear, radius) * ratioY;
326 const GLdouble left = -right;
327 const GLdouble top = fVP.GetFrontHalfHeight (pnear, radius) * ratioX;
328 const GLdouble bottom = -top;
329
330 // FIXME
331 ResizeGLView();
332 //SHOULD SetWindowsSizeHint()...
333
334 glMatrixMode (GL_PROJECTION); // set up Frustum.
335 glLoadIdentity();
336
337 const G4Vector3D scaleFactor = fVP.GetScaleFactor();
338 glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
339
340 if (fVP.GetFieldHalfAngle() == 0.) {
341 g4GlOrtho (left, right, bottom, top, pnear, pfar);
342 }
343 else {
344 g4GlFrustum (left, right, bottom, top, pnear, pfar);
345 }
346
347 glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
348 glLoadIdentity();
349
350 const G4Normal3D& upVector = fVP.GetUpVector ();
351 G4Point3D gltarget;
352 if (cameraDistance > 1.e-6 * radius) {
353 gltarget = targetPoint;
354 }
355 else {
356 gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
357 }
358
359 const G4Point3D& pCamera = cameraPosition; // An alias for brevity.
360
361 g4GluLookAt (pCamera.x(), pCamera.y(), pCamera.z(), // Viewpoint.
362 gltarget.x(), gltarget.y(), gltarget.z(), // Target point.
363 upVector.x(), upVector.y(), upVector.z()); // Up vector.
364 // Light position is "true" light direction, so must come after gluLookAt.
365 glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
366
367 // The idea is to use back-to-back clipping planes. This can cut an object
368 // down to just a few pixels, which can make it difficult to see. So, for
369 // now, comment this out and use the generic (Boolean) method, via
370 // G4VSolid* G4OpenGLSceneHandler::CreateSectionSolid ()
371 // { return G4VSceneHandler::CreateSectionSolid(); }
372// if (fVP.IsSection () ) { // pair of back to back clip planes.
373// const G4Plane3D& sp = fVP.GetSectionPlane ();
374// double sArray[4];
375// sArray[0] = sp.a();
376// sArray[1] = sp.b();
377// sArray[2] = sp.c();
378// sArray[3] = sp.d() + radius * 1.e-05;
379// glClipPlane (GL_CLIP_PLANE0, sArray);
380// glEnable (GL_CLIP_PLANE0);
381// sArray[0] = -sp.a();
382// sArray[1] = -sp.b();
383// sArray[2] = -sp.c();
384// sArray[3] = -sp.d() + radius * 1.e-05;
385// glClipPlane (GL_CLIP_PLANE1, sArray);
386// glEnable (GL_CLIP_PLANE1);
387// } else {
388// glDisable (GL_CLIP_PLANE0);
389// glDisable (GL_CLIP_PLANE1);
390// }
391
392 // What we call intersection of cutaways is easy in OpenGL. You
393 // just keep cutting. Unions are more tricky - you have to have
394 // multiple passes and this is handled in
395 // G4OpenGLImmediate/StoredViewer::ProcessView.
396 const G4Planes& cutaways = fVP.GetCutawayPlanes();
397 size_t nPlanes = cutaways.size();
398 if (fVP.IsCutaway() &&
399 fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
400 nPlanes > 0) {
401 double a[4];
402 a[0] = cutaways[0].a();
403 a[1] = cutaways[0].b();
404 a[2] = cutaways[0].c();
405 a[3] = cutaways[0].d();
406 glClipPlane (GL_CLIP_PLANE2, a);
407 glEnable (GL_CLIP_PLANE2);
408 if (nPlanes > 1) {
409 a[0] = cutaways[1].a();
410 a[1] = cutaways[1].b();
411 a[2] = cutaways[1].c();
412 a[3] = cutaways[1].d();
413 glClipPlane (GL_CLIP_PLANE3, a);
414 glEnable (GL_CLIP_PLANE3);
415 }
416 if (nPlanes > 2) {
417 a[0] = cutaways[2].a();
418 a[1] = cutaways[2].b();
419 a[2] = cutaways[2].c();
420 a[3] = cutaways[2].d();
421 glClipPlane (GL_CLIP_PLANE4, a);
422 glEnable (GL_CLIP_PLANE4);
423 }
424 } else {
425 glDisable (GL_CLIP_PLANE2);
426 glDisable (GL_CLIP_PLANE3);
427 glDisable (GL_CLIP_PLANE4);
428 }
429
430 // Background.
431 background = fVP.GetBackgroundColour ();
432
433}
434
435
436
437void G4OpenGLViewer::ResetView () {
439 fRot_sens = 1;
440 fPan_sens = 0.01;
441}
442
443
444void G4OpenGLViewer::HaloingFirstPass () {
445
446 //To perform haloing, first Draw all information to the depth buffer
447 //alone, using a chunky line width, and then Draw all info again, to
448 //the colour buffer, setting a thinner line width an the depth testing
449 //function to less than or equal, so if two lines cross, the one
450 //passing behind the other will not pass the depth test, and so not
451 //get rendered either side of the infront line for a short distance.
452
453 //First, disable writing to the colo(u)r buffer...
454 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
455
456 //Now enable writing to the depth buffer...
457 glDepthMask (GL_TRUE);
458 glDepthFunc (GL_LESS);
459 glClearDepth (1.0);
460
461 //Finally, set the line width to something wide...
462 ChangeLineWidth(3.0);
463
464}
465
466void G4OpenGLViewer::HaloingSecondPass () {
467
468 //And finally, turn the colour buffer back on with a sesible line width...
469 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
470 glDepthFunc (GL_LEQUAL);
471 ChangeLineWidth(1.0);
472
473}
474
475G4String G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
476{
477 const std::vector < G4OpenGLViewerPickMap* > & pickMap = GetPickDetails(x,y);
478 G4String txt = "";
479 if (pickMap.size() == 0) {
480// txt += "No hits recorded.";;
481 } else {
482 for (unsigned int a=0; a < pickMap.size(); a++) {
483 if (pickMap[a]->getAttributes().size() > 0) {
484 txt += pickMap[a]->print();
485 }
486 }
487 }
488 return txt;
489}
490
491const std::vector < G4OpenGLViewerPickMap* > & G4OpenGLViewer::GetPickDetails(GLdouble x, GLdouble y)
492{
493 static std::vector < G4OpenGLViewerPickMap* > pickMapVector;
494 for (auto pickMap: pickMapVector) {
495 delete pickMap;
496 }
497 pickMapVector.clear();
498
499 const G4int BUFSIZE = 512;
500 GLuint selectBuffer[BUFSIZE];
501 glSelectBuffer(BUFSIZE, selectBuffer);
502 glRenderMode(GL_SELECT);
503 glInitNames();
504 glPushName(0);
505 glMatrixMode(GL_PROJECTION);
506 G4double currentProjectionMatrix[16];
507 glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
508 glPushMatrix();
509 glLoadIdentity();
510 GLint viewport[4];
511 glGetIntegerv(GL_VIEWPORT, viewport);
512/* G4cout
513 << "viewport, x,y: "
514 << viewport[0] << ',' << viewport[1] << ',' << viewport[2] << ',' << viewport[3]
515 << ", " << x << ',' << y
516 << G4endl;
517*/
518 fIsGettingPickInfos = true;
519 // Define 5x5 pixel pick area
520 g4GluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
521 glMultMatrixd(currentProjectionMatrix);
522 glMatrixMode(GL_MODELVIEW);
523 DrawView();
524 GLint hits = glRenderMode(GL_RENDER);
525 fIsGettingPickInfos = false;
526 if (hits < 0) {
527 G4cout << "Too many hits. Zoom in to reduce overlaps." << G4endl;
528 goto restoreMatrices;
529 }
530 if (hits > 0) {
531 GLuint* p = selectBuffer;
532 for (GLint i = 0; i < hits; ++i) {
533 GLuint nnames = *p++;
534 // This bit of debug code or...
535 //GLuint zmin = *p++;
536 //GLuint zmax = *p++;
537 //G4cout << "Hit " << i << ": " << nnames << " names"
538 // << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
539 // ...just increment the pointer
540 p++;
541 p++;
542 for (GLuint j = 0; j < nnames; ++j) {
543 GLuint name = *p++;
544 std::map<GLuint, G4AttHolder*>::iterator iter =
545 fOpenGLSceneHandler.fPickMap.find(name);
546 if (iter != fOpenGLSceneHandler.fPickMap.end()) {
547 G4AttHolder* attHolder = iter->second;
548 if(attHolder && attHolder->GetAttDefs().size()) {
549 for (size_t iAtt = 0;
550 iAtt < attHolder->GetAttDefs().size(); ++iAtt) {
551 std::ostringstream oss;
552 oss << G4AttCheck(attHolder->GetAttValues()[iAtt],
553 attHolder->GetAttDefs()[iAtt]);
554 G4OpenGLViewerPickMap* pickMap = new G4OpenGLViewerPickMap();
555// G4cout
556// << "i,j, attHolder->GetAttDefs().size(): "
557// << i << ',' << j
558// << ", " << attHolder->GetAttDefs().size()
559// << G4endl;
560// G4cout << "G4OpenGLViewer::GetPickDetails: " << oss.str() << G4endl;
561 pickMap->addAttributes(oss.str());
562 pickMap->setHitNumber(i);
563 pickMap->setSubHitNumber(j);
564 pickMap->setPickName(name);
565 pickMapVector.push_back(pickMap);
566 }
567 }
568 }
569 }
570 }
571 }
572
573restoreMatrices:
574 glMatrixMode(GL_PROJECTION);
575 glPopMatrix();
576 glMatrixMode(GL_MODELVIEW);
577
578 return pickMapVector;
579}
580
581GLubyte* G4OpenGLViewer::grabPixels
582(int inColor, unsigned int width, unsigned int height) {
583
584 GLubyte* buffer;
585 GLint swapbytes, lsbfirst, rowlength;
586 GLint skiprows, skippixels, alignment;
587 GLenum format;
588 int size;
589
590 if (inColor) {
591 format = GL_RGB;
592 size = width*height*3;
593 } else {
594 format = GL_LUMINANCE;
595 size = width*height*1;
596 }
597
598 buffer = new GLubyte[size];
599 if (buffer == NULL)
600 return NULL;
601
602 glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
603 glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
604 glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
605
606 glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
607 glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
608 glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
609
610 glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
611 glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
612 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
613
614 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
615 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
616 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
617
618 glReadBuffer(GL_FRONT);
619 glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
620
621 glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
622 glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
623 glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
624
625 glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
626 glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
627 glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
628
629 return buffer;
630}
631
632bool G4OpenGLViewer::printEPS() {
633 bool res;
634
635 // Change the LC_NUMERIC value in order to have "." separtor and not ","
636 // This case is only useful for French, Canadien...
637 size_t len = strlen(setlocale(LC_NUMERIC,NULL));
638 char* oldLocale = (char*)(malloc(len+1));
639 if(oldLocale!=NULL) strncpy(oldLocale,setlocale(LC_NUMERIC,NULL),len);
640 setlocale(LC_NUMERIC,"C");
641
642 if (((fExportImageFormat == "eps") || (fExportImageFormat == "ps")) && (!fVectoredPs)) {
643 res = printNonVectoredEPS();
644 } else {
645 res = printVectoredEPS();
646 }
647
648 // restore the local
649 if (oldLocale) {
650 setlocale(LC_NUMERIC,oldLocale);
651 free(oldLocale);
652 }
653
654 if (res == false) {
655 G4cerr << "Error saving file... " << getRealPrintFilename().c_str() << G4endl;
656 } else {
657 G4cout << "File " << getRealPrintFilename().c_str() << " size: " << getRealExportWidth() << "x" << getRealExportHeight() << " has been saved " << G4endl;
658
659 // increment index if necessary
660 if ( fExportFilenameIndex != -1) {
661 fExportFilenameIndex++;
662 }
663 }
664
665 return res;
666}
667
668bool G4OpenGLViewer::printVectoredEPS() {
669 return printGl2PS();
670}
671
672bool G4OpenGLViewer::printNonVectoredEPS () {
673
674 int width = getRealExportWidth();
675 int height = getRealExportHeight();
676
677 FILE* fp;
678 GLubyte* pixels;
679 GLubyte* curpix;
680 int components, pos, i;
681
682 pixels = grabPixels (fPrintColour, width, height);
683
684 if (pixels == NULL) {
685 G4cerr << "Failed to get pixels from OpenGl viewport" << G4endl;
686 return false;
687 }
688 if (fPrintColour) {
689 components = 3;
690 } else {
691 components = 1;
692 }
693 std::string name = getRealPrintFilename();
694 fp = fopen (name.c_str(), "w");
695 if (fp == NULL) {
696 G4cerr << "Can't open filename " << name.c_str() << G4endl;
697 return false;
698 }
699
700 fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
701 fprintf (fp, "%%%%Title: %s\n", name.c_str());
702 fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
703 fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
704 fprintf (fp, "%%%%EndComments\n");
705 fprintf (fp, "gsave\n");
706 fprintf (fp, "/bwproc {\n");
707 fprintf (fp, " rgbproc\n");
708 fprintf (fp, " dup length 3 idiv string 0 3 0 \n");
709 fprintf (fp, " 5 -1 roll {\n");
710 fprintf (fp, " add 2 1 roll 1 sub dup 0 eq\n");
711 fprintf (fp, " { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
712 fprintf (fp, " 3 1 roll 5 -1 roll } put 1 add 3 0 \n");
713 fprintf (fp, " { 2 1 roll } ifelse\n");
714 fprintf (fp, " }forall\n");
715 fprintf (fp, " pop pop pop\n");
716 fprintf (fp, "} def\n");
717 fprintf (fp, "systemdict /colorimage known not {\n");
718 fprintf (fp, " /colorimage {\n");
719 fprintf (fp, " pop\n");
720 fprintf (fp, " pop\n");
721 fprintf (fp, " /rgbproc exch def\n");
722 fprintf (fp, " { bwproc } image\n");
723 fprintf (fp, " } def\n");
724 fprintf (fp, "} if\n");
725 fprintf (fp, "/picstr %d string def\n", width * components);
726 fprintf (fp, "%d %d scale\n", width, height);
727 fprintf (fp, "%d %d %d\n", width, height, 8);
728 fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height);
729 fprintf (fp, "{currentfile picstr readhexstring pop}\n");
730 fprintf (fp, "false %d\n", components);
731 fprintf (fp, "colorimage\n");
732
733 curpix = (GLubyte*) pixels;
734 pos = 0;
735 for (i = width*height*components; i>0; i--) {
736 fprintf (fp, "%02hx ", (unsigned short)(*(curpix++)));
737 if (++pos >= 32) {
738 fprintf (fp, "\n");
739 pos = 0;
740 }
741 }
742 if (pos)
743 fprintf (fp, "\n");
744
745 fprintf (fp, "grestore\n");
746 fprintf (fp, "showpage\n");
747 delete [] pixels;
748 fclose (fp);
749
750 // Reset for next time (useful is size change)
751 // fPrintSizeX = -1;
752 // fPrintSizeY = -1;
753
754 return true;
755}
756
757/** Return if gl2ps is currently writing
758 */
759bool G4OpenGLViewer::isGl2psWriting() {
760
761 if (!fGL2PSAction) return false;
762 if (fGL2PSAction->fileWritingEnabled()) {
763 return true;
764 }
765 return false;
766}
767
768
769G4bool G4OpenGLViewer::isFramebufferReady() {
770 bool check = false;
771#ifdef G4VIS_BUILD_OPENGLQT_DRIVER
772 check = true;
773#endif
774#ifdef G4VIS_BUILD_OPENGLX_DRIVER
775 check = false;
776#endif
777#ifdef G4VIS_BUILD_OPENGLXM_DRIVER
778 check = false;
779#endif
780#ifdef G4VIS_BUILD_OPENGLWIN32_DRIVER
781 check = false;
782#endif
783
784#if GL_ARB_framebuffer_object
785 if (check) {
786// if ( glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNDEFINED) {
787// return false;
788// }
789 }
790#endif
791 return true;
792}
793
794
795/* Draw Gl2Ps text if needed
796 */
797void G4OpenGLViewer::DrawText(const G4Text& g4text)
798{
799 // gl2ps or GL window ?
800 if (isGl2psWriting()) {
801
803 G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
804 G4Point3D position = g4text.GetPosition();
805
806 G4String textString = g4text.GetText();
807
808 glRasterPos3d(position.x(),position.y(),position.z());
809 GLint align = GL2PS_TEXT_B;
810
811 switch (g4text.GetLayout()) {
812 case G4Text::left: align = GL2PS_TEXT_BL; break;
813 case G4Text::centre: align = GL2PS_TEXT_B; break;
814 case G4Text::right: align = GL2PS_TEXT_BR;
815 }
816
817 gl2psTextOpt(textString.c_str(),"Times-Roman",GLshort(size),align,0);
818
819 } else {
820
821 static G4int callCount = 0;
822 ++callCount;
823 //if (callCount <= 10 || callCount%100 == 0) {
824 if (callCount <= 1) {
825 G4cout <<
826 "G4OpenGLViewer::DrawText: Not implemented for \""
827 << fName <<
828 "\"\n Called with "
829 << g4text
830 << G4endl;
831 }
832 }
833}
834
835/** Change PointSize on gl2ps if needed
836 */
837void G4OpenGLViewer::ChangePointSize(G4double size) {
838
839 if (isGl2psWriting()) {
840 fGL2PSAction->setPointSize(int(size));
841 } else {
842 glPointSize (size);
843 }
844}
845
846
847/** Change LineSize on gl2ps if needed
848 */
849void G4OpenGLViewer::ChangeLineWidth(G4double width) {
850
851 if (isGl2psWriting()) {
852 fGL2PSAction->setLineWidth(int(width));
853 } else {
854 glLineWidth (width);
855 }
856}
857
858/**
859 Export image with the given name with width and height
860 Several cases :
861 If name is "", filename will have the default value
862 If name is "toto.png", set the name to "toto" and the format to "png". No incremented suffix is added.
863 If name is "toto", set the name to "toto" and the format to default (or current format if specify).
864 Will also add an incremented suffix at the end of the file
865*/
866bool G4OpenGLViewer::exportImage(std::string name, int width, int height) {
867
868 if (! setExportFilename(name)) {
869 return false;
870 }
871
872 if ((width != -1) && (height != -1)) {
873 setExportSize(width, height);
874 }
875
876 if (fExportImageFormat == "eps") {
877 fGL2PSAction->setExportImageFormat(GL2PS_EPS);
878 } else if (fExportImageFormat == "ps") {
879 fGL2PSAction->setExportImageFormat(GL2PS_PS);
880 } else if (fExportImageFormat == "svg") {
881 fGL2PSAction->setExportImageFormat(GL2PS_SVG);
882 } else if (fExportImageFormat == "pdf") {
883 fGL2PSAction->setExportImageFormat(GL2PS_PDF);
884 } else {
885 setExportImageFormat(fExportImageFormat,true); // will display a message if this format is not correct for the current viewer
886 return false;
887 }
888 return printEPS();
889}
890
891
892bool G4OpenGLViewer::printGl2PS() {
893
894 int width = getRealExportWidth();
895 int height = getRealExportHeight();
896 bool res = true;
897
898 // no need to redraw at each new primitive for printgl2PS
899 G4OpenGLSceneHandler& oglSceneHandler = dynamic_cast<G4OpenGLSceneHandler&>(fSceneHandler);
900 G4OpenGLSceneHandler::FlushAction originalFlushAction = oglSceneHandler.GetFlushAction();
901 oglSceneHandler.SetFlushAction(G4OpenGLSceneHandler::never);
902
903 if (!fGL2PSAction) return false;
904
905 fGL2PSAction->setFileName(getRealPrintFilename().c_str());
906 // try to resize
907 int X = fWinSize_x;
908 int Y = fWinSize_y;
909
910 fWinSize_x = width;
911 fWinSize_y = height;
912 // Laurent G. 16/03/10 : Not the good way to do.
913 // We should draw in a new offscreen context instead of
914 // resizing and drawing in current window...
915 // This should be solve when we will do an offscreen method
916 // to render OpenGL
917 // See :
918 // http://developer.apple.com/Mac/library/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html
919 // http://www.songho.ca/opengl/gl_fbo.html
920
921 ResizeGLView();
922 bool extendBuffer = true;
923 bool endWriteAction = false;
924 bool beginWriteAction = true;
925 bool filePointerOk = true;
926 while ((extendBuffer) && (! endWriteAction) && (filePointerOk)) {
927
928 beginWriteAction = fGL2PSAction->enableFileWriting();
929 // 3 cases :
930 // - true
931 // - false && ! fGL2PSAction->fileWritingEnabled() => bad file name
932 // - false && fGL2PSAction->fileWritingEnabled() => buffer size problem ?
933
934 filePointerOk = fGL2PSAction->fileWritingEnabled();
935
936 if (beginWriteAction) {
937
938 // Set the viewport
939 // By default, we choose the line width (trajectories...)
940 fGL2PSAction->setLineWidth(fGl2psDefaultLineWith);
941 // By default, we choose the point size (markers...)
942 fGL2PSAction->setPointSize(fGl2psDefaultPointSize);
943
944 DrawView ();
945 endWriteAction = fGL2PSAction->disableFileWriting();
946 }
947 if (filePointerOk) {
948 if ((! endWriteAction) || (! beginWriteAction)) {
949 extendBuffer = fGL2PSAction->extendBufferSize();
950 }
951 }
952 }
953 fGL2PSAction->resetBufferSizeParameters();
954
955 if (!extendBuffer ) {
956 G4cerr << "ERROR: gl2ps buffer size is not big enough to print this geometry. Try to extend it. No output produced"<< G4endl;
957 res = false;
958 }
959 if (!beginWriteAction ) {
960 G4cerr << "ERROR: saving file "<<getRealPrintFilename().c_str()<<". Check read/write access. No output produced" << G4endl;
961 res = false;
962 }
963 if (!endWriteAction ) {
964 G4cerr << "gl2ps error. No output produced" << G4endl;
965 res = false;
966 }
967 fWinSize_x = X;
968 fWinSize_y = Y;
969
970 oglSceneHandler.SetFlushAction(originalFlushAction);
971
972 // Reset for next time (useful is size change)
973 // fPrintSizeX = 0;
974 // fPrintSizeY = 0;
975
976 return res;
977}
978
979unsigned int G4OpenGLViewer::getWinWidth() const{
980 return fWinSize_x;
981}
982
983unsigned int G4OpenGLViewer::getWinHeight() const{
984 return fWinSize_y;
985}
986
987G4bool G4OpenGLViewer::sizeHasChanged() {
988 return fSizeHasChanged;
989}
990
991G4int G4OpenGLViewer::getRealExportWidth() {
992 if (fPrintSizeX == -1) {
993 return fWinSize_x;
994 }
995 GLint dims[2];
996 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
997
998 // L.Garnier 01-2010: Some problems with mac 10.6
999 if ((dims[0] !=0 ) && (dims[1] !=0)) {
1000 if (fPrintSizeX > dims[0]){
1001 return dims[0];
1002 }
1003 }
1004 if (fPrintSizeX < -1){
1005 return 0;
1006 }
1007 return fPrintSizeX;
1008}
1009
1010G4int G4OpenGLViewer::getRealExportHeight() {
1011 if (fPrintSizeY == -1) {
1012 return fWinSize_y;
1013 }
1014 GLint dims[2];
1015 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
1016
1017 // L.Garnier 01-2010: Some problems with mac 10.6
1018 if ((dims[0] !=0 ) && (dims[1] !=0)) {
1019 if (fPrintSizeY > dims[1]){
1020 return dims[1];
1021 }
1022 }
1023 if (fPrintSizeY < -1){
1024 return 0;
1025 }
1026 return fPrintSizeY;
1027}
1028
1029void G4OpenGLViewer::setExportSize(G4int X, G4int Y) {
1030 fPrintSizeX = X;
1031 fPrintSizeY = Y;
1032}
1033
1034/**
1035 If name is "" or "!", filename and extension will have the default value.
1036 If name is "toto.png", set the name to "toto" and the format to "png". No incremented suffix is added.
1037 If name is "toto", set the name to "toto" and the format to default (or current format if specify).
1038 If name is the same as previous, do not reset incremented suffix.
1039*/
1040bool G4OpenGLViewer::setExportFilename(G4String name,G4bool inc) {
1041 if (name == "!") {
1042 name = "";
1043 }
1044
1045 if (inc) {
1046 if ((name != "") && (fExportFilename != name)) {
1047 fExportFilenameIndex=0;
1048 }
1049 } else {
1050 fExportFilenameIndex=-1;
1051 }
1052
1053 if (name.size() == 0) {
1054 name = getRealPrintFilename().c_str();
1055 } else {
1056 // guess format by extention
1057 std::string extension = name.substr(name.find_last_of(".") + 1);
1058 // If there is a dot in the name the above might find rubbish, so...
1059 if (extension.size() >= 3 && extension.size() <= 4) { // Possible extension
1060 if (setExportImageFormat(extension, false)) { // Extension found
1061 fExportFilename = name.substr(0,name.find_last_of("."));
1062 } else { // No viable extension found
1063 return false;
1064 }
1065 } else { // Assume name is already the required without-extension part
1066 fExportFilename = name;
1067 }
1068 }
1069 return true;
1070}
1071
1072std::string G4OpenGLViewer::getRealPrintFilename() {
1073 std::string temp = fExportFilename;
1074 if (fExportFilenameIndex != -1) {
1075 temp += std::string("_");
1076 std::ostringstream os;
1077 os << std::setw(4) << std::setfill('0') << fExportFilenameIndex;
1078 std::string nb_str = os.str();
1079 temp += nb_str;
1080 }
1081 temp += "."+fExportImageFormat;
1082 return temp;
1083}
1084
1085GLdouble G4OpenGLViewer::getSceneNearWidth()
1086{
1087 if (!fSceneHandler.GetScene()) {
1088 return 0;
1089 }
1090 const G4Point3D targetPoint
1091 = fSceneHandler.GetScene()->GetStandardTargetPoint()
1092 + fVP.GetCurrentTargetPoint ();
1093 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1094 if(radius<=0.) radius = 1.;
1095 const G4double cameraDistance = fVP.GetCameraDistance (radius);
1096 const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1097 return 2 * fVP.GetFrontHalfHeight (pnear, radius);
1098}
1099
1100GLdouble G4OpenGLViewer::getSceneFarWidth()
1101{
1102 if (!fSceneHandler.GetScene()) {
1103 return 0;
1104 }
1105 const G4Point3D targetPoint
1106 = fSceneHandler.GetScene()->GetStandardTargetPoint()
1107 + fVP.GetCurrentTargetPoint ();
1108 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1109 if(radius<=0.) radius = 1.;
1110 const G4double cameraDistance = fVP.GetCameraDistance (radius);
1111 const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1112 const GLdouble pfar = fVP.GetFarDistance (cameraDistance, pnear, radius);
1113 return 2 * fVP.GetFrontHalfHeight (pfar, radius);
1114}
1115
1116
1117GLdouble G4OpenGLViewer::getSceneDepth()
1118{
1119 if (!fSceneHandler.GetScene()) {
1120 return 0;
1121 }
1122 const G4Point3D targetPoint
1123 = fSceneHandler.GetScene()->GetStandardTargetPoint()
1124 + fVP.GetCurrentTargetPoint ();
1125 G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
1126 if(radius<=0.) radius = 1.;
1127 const G4double cameraDistance = fVP.GetCameraDistance (radius);
1128 const GLdouble pnear = fVP.GetNearDistance (cameraDistance, radius);
1129 return fVP.GetFarDistance (cameraDistance, pnear, radius)- pnear;
1130}
1131
1132
1133
1134void G4OpenGLViewer::rotateScene(G4double dx, G4double dy)
1135{
1136 if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
1137 rotateSceneInViewDirection(dx,dy);
1138 } else {
1139 if( dx != 0) {
1140 rotateSceneThetaPhi(dx,0);
1141 }
1142 if( dy != 0) {
1143 rotateSceneThetaPhi(0,dy);
1144 }
1145 }
1146}
1147
1148
1149void G4OpenGLViewer::rotateSceneToggle(G4double dx, G4double dy)
1150{
1151 if (fVP.GetRotationStyle() != G4ViewParameters::freeRotation) {
1152 rotateSceneInViewDirection(dx,dy);
1153 } else {
1154 if( dx != 0) {
1155 rotateSceneThetaPhi(dx,0);
1156 }
1157 if( dy != 0) {
1158 rotateSceneThetaPhi(0,dy);
1159 }
1160 }
1161}
1162
1163void G4OpenGLViewer::rotateSceneThetaPhi(G4double dx, G4double dy)
1164{
1165 if (!fSceneHandler.GetScene()) {
1166 return;
1167 }
1168
1169 G4Vector3D vp;
1170 G4Vector3D up;
1171
1172 G4Vector3D xprime;
1173 G4Vector3D yprime;
1174 G4Vector3D zprime;
1175
1176 G4double delta_alpha;
1177 G4double delta_theta;
1178
1179 G4Vector3D new_vp;
1180 G4Vector3D new_up;
1181
1182 G4double cosalpha;
1183 G4double sinalpha;
1184
1185 G4Vector3D a1;
1186 G4Vector3D a2;
1187 G4Vector3D delta;
1188 G4Vector3D viewPoint;
1189
1190
1191 //phi spin stuff here
1192
1193 vp = fVP.GetViewpointDirection ().unit ();
1194 up = fVP.GetUpVector ().unit ();
1195
1196 yprime = (up.cross(vp)).unit();
1197 zprime = (vp.cross(yprime)).unit();
1198
1199 if (fVP.GetLightsMoveWithCamera()) {
1200 delta_alpha = dy * fRot_sens;
1201 delta_theta = -dx * fRot_sens;
1202 } else {
1203 delta_alpha = -dy * fRot_sens;
1204 delta_theta = dx * fRot_sens;
1205 }
1206
1207 delta_alpha *= CLHEP::deg;
1208 delta_theta *= CLHEP::deg;
1209
1210 new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
1211
1212 // to avoid z rotation flipping
1213 // to allow more than 360∞ rotation
1214
1215 if (fVP.GetLightsMoveWithCamera()) {
1216 new_up = (new_vp.cross(yprime)).unit();
1217 if (new_vp.z()*vp.z() <0) {
1218 new_up.set(new_up.x(),-new_up.y(),new_up.z());
1219 }
1220 } else {
1221 new_up = up;
1222 if (new_vp.z()*vp.z() <0) {
1223 new_up.set(new_up.x(),-new_up.y(),new_up.z());
1224 }
1225 }
1226 fVP.SetUpVector(new_up);
1227 ////////////////
1228 // Rotates by fixed azimuthal angle delta_theta.
1229
1230 cosalpha = new_up.dot (new_vp.unit());
1231 sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
1232 yprime = (new_up.cross (new_vp.unit())).unit ();
1233 xprime = yprime.cross (new_up);
1234 // Projection of vp on plane perpendicular to up...
1235 a1 = sinalpha * xprime;
1236 // Required new projection...
1237 a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
1238 // Required Increment vector...
1239 delta = a2 - a1;
1240 // So new viewpoint is...
1241 viewPoint = new_vp.unit() + delta;
1242
1243 fVP.SetViewAndLights (viewPoint);
1244}
1245
1246
1247void G4OpenGLViewer::rotateSceneInViewDirection(G4double dx, G4double dy)
1248{
1249 if (!fSceneHandler.GetScene()) {
1250 return;
1251 }
1252
1253 G4Vector3D vp;
1254 G4Vector3D up;
1255
1256 G4Vector3D xprime;
1257 G4Vector3D yprime;
1258 G4Vector3D zprime;
1259
1260 G4Vector3D new_vp;
1261 G4Vector3D new_up;
1262
1263 G4Vector3D a1;
1264 G4Vector3D a2;
1265 G4Vector3D delta;
1266 G4Vector3D viewPoint;
1267
1268 dx = dx/100;
1269 dy = dy/100;
1270
1271 //phi spin stuff here
1272
1273 vp = fVP.GetViewpointDirection ().unit();
1274 up = fVP.GetUpVector ().unit();
1275
1276 G4Vector3D zPrimeVector = G4Vector3D(up.y()*vp.z()-up.z()*vp.y(),
1277 up.z()*vp.x()-up.x()*vp.z(),
1278 up.x()*vp.y()-up.y()*vp.x());
1279
1280 viewPoint = vp/fRot_sens + (zPrimeVector*dx - up*dy) ;
1281 new_up = G4Vector3D(viewPoint.y()*zPrimeVector.z()-viewPoint.z()*zPrimeVector.y(),
1282 viewPoint.z()*zPrimeVector.x()-viewPoint.x()*zPrimeVector.z(),
1283 viewPoint.x()*zPrimeVector.y()-viewPoint.y()*zPrimeVector.x());
1284
1285 G4Vector3D new_upUnit = new_up.unit();
1286
1287
1288
1289 fVP.SetUpVector(new_upUnit);
1290 fVP.SetViewAndLights (viewPoint);
1291}
1292
1293
1294void G4OpenGLViewer::addExportImageFormat(std::string format) {
1295 fExportImageFormatVector.push_back(format);
1296}
1297
1298bool G4OpenGLViewer::setExportImageFormat(std::string format, bool quiet) {
1299 bool found = false;
1300 std::string list;
1301 for (unsigned int a=0; a<fExportImageFormatVector.size(); a++) {
1302 list +=fExportImageFormatVector.at(a) + " ";
1303
1304 if (fExportImageFormatVector.at(a) == format) {
1305 if (! quiet) {
1306 G4cout << " Changing export format to \"" << format << "\"" << G4endl;
1307 }
1308 if (format != fExportImageFormat) {
1309 fExportFilenameIndex = 0;
1310 fExportImageFormat = format;
1311 }
1312 return true;
1313 }
1314 }
1315 if (! found) {
1316 if (format.size() == 0) {
1317 G4cout << " Current formats availables are : " << list << G4endl;
1318 } else {
1319 G4cerr << " Format \"" << format << "\" is not available for the selected viewer. Current formats availables are : " << list << G4endl;
1320 }
1321 }
1322 return false;
1323}
1324
1325
1326// From MESA implementation :
1327// http://www.techques.com/question/1-8660454/gluPickMatrix-code-from-Mesa
1328
1329void G4OpenGLViewer::g4GluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height,
1330 GLint viewport[4])
1331 {
1332 GLdouble mat[16];
1333 GLdouble sx, sy;
1334 GLdouble tx, ty;
1335
1336 sx = viewport[2] / width;
1337 sy = viewport[3] / height;
1338 tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
1339 ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
1340
1341#define M(row, col) mat[col*4+row]
1342 M(0, 0) = sx;
1343 M(0, 1) = 0.0;
1344 M(0, 2) = 0.0;
1345 M(0, 3) = tx;
1346 M(1, 0) = 0.0;
1347 M(1, 1) = sy;
1348 M(1, 2) = 0.0;
1349 M(1, 3) = ty;
1350 M(2, 0) = 0.0;
1351 M(2, 1) = 0.0;
1352 M(2, 2) = 1.0;
1353 M(2, 3) = 0.0;
1354 M(3, 0) = 0.0;
1355 M(3, 1) = 0.0;
1356 M(3, 2) = 0.0;
1357 M(3, 3) = 1.0;
1358#undef M
1359
1360 glMultMatrixd(mat);
1361}
1362
1363
1364
1365
1366
1367// From MESA implementation :
1368// https://github.com/jlamarche/iOS-OpenGLES-Stuff/blob/master/Wavefront%20OBJ%20Loader/Classes/gluLookAt.m
1369// or http://www.daniweb.com/software-development/game-development/threads/308901/lookat-matrix-source-code
1370
1371void G4OpenGLViewer::g4GluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
1372 GLdouble centerx, GLdouble centery, GLdouble
1373 centerz,
1374 GLdouble upx, GLdouble upy, GLdouble upz )
1375{
1376 GLdouble mat[16];
1377 GLdouble x[3], y[3], z[3];
1378 GLdouble mag;
1379
1380 /* Make rotation matrix */
1381
1382 /* Z vector */
1383 z[0] = eyex - centerx;
1384 z[1] = eyey - centery;
1385 z[2] = eyez - centerz;
1386 mag = std::sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
1387 if (mag) { /* mpichler, 19950515 */
1388 z[0] /= mag;
1389 z[1] /= mag;
1390 z[2] /= mag;
1391 }
1392
1393 /* Y vector */
1394 y[0] = upx;
1395 y[1] = upy;
1396 y[2] = upz;
1397
1398 /* X vector = Y cross Z */
1399 x[0] = y[1] * z[2] - y[2] * z[1];
1400 x[1] = -y[0] * z[2] + y[2] * z[0];
1401 x[2] = y[0] * z[1] - y[1] * z[0];
1402
1403 /* Recompute Y = Z cross X */
1404 y[0] = z[1] * x[2] - z[2] * x[1];
1405 y[1] = -z[0] * x[2] + z[2] * x[0];
1406 y[2] = z[0] * x[1] - z[1] * x[0];
1407
1408 /* mpichler, 19950515 */
1409 /* cross product gives area of parallelogram, which is < 1.0 for
1410 * non-perpendicular unit-length vectors; so normalize x, y here
1411 */
1412
1413 mag = std::sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
1414 if (mag) {
1415 x[0] /= mag;
1416 x[1] /= mag;
1417 x[2] /= mag;
1418 }
1419
1420 mag = std::sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
1421 if (mag) {
1422 y[0] /= mag;
1423 y[1] /= mag;
1424 y[2] /= mag;
1425 }
1426
1427#define M(row,col) mat[col*4+row]
1428 M(0, 0) = x[0];
1429 M(0, 1) = x[1];
1430 M(0, 2) = x[2];
1431 M(0, 3) = 0.0;
1432 M(1, 0) = y[0];
1433 M(1, 1) = y[1];
1434 M(1, 2) = y[2];
1435 M(1, 3) = 0.0;
1436 M(2, 0) = z[0];
1437 M(2, 1) = z[1];
1438 M(2, 2) = z[2];
1439 M(2, 3) = 0.0;
1440 M(3, 0) = 0.0;
1441 M(3, 1) = 0.0;
1442 M(3, 2) = 0.0;
1443 M(3, 3) = 1.0;
1444#undef M
1445 glMultMatrixd(mat);
1446
1447 /* Translate Eye to Origin */
1448 glTranslated(-eyex, -eyey, -eyez);
1449}
1450
1451void G4OpenGLViewer::g4GlOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {
1452 // glOrtho (left, right, bottom, top, near, far);
1453
1454 GLdouble a = 2.0 / (right - left);
1455 GLdouble b = 2.0 / (top - bottom);
1456 GLdouble c = -2.0 / (zFar - zNear);
1457
1458 GLdouble tx = - (right + left)/(right - left);
1459 GLdouble ty = - (top + bottom)/(top - bottom);
1460 GLdouble tz = - (zFar + zNear)/(zFar - zNear);
1461
1462 GLdouble ortho[16] = {
1463 a, 0, 0, 0,
1464 0, b, 0, 0,
1465 0, 0, c, 0,
1466 tx, ty, tz, 1
1467 };
1468 glMultMatrixd(ortho);
1469
1470}
1471
1472
1473void G4OpenGLViewer::g4GlFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {
1474 // glFrustum (left, right, bottom, top, near, far);
1475
1476 GLdouble deltaX = right - left;
1477 GLdouble deltaY = top - bottom;
1478 GLdouble deltaZ = zFar - zNear;
1479
1480 GLdouble a = 2.0f * zNear / deltaX;
1481 GLdouble b = 2.0f * zNear / deltaY;
1482 GLdouble c = (right + left) / deltaX;
1483 GLdouble d = (top + bottom) / deltaY;
1484 GLdouble e = -(zFar + zNear) / (zFar - zNear);
1485 GLdouble f = -2.0f * zFar * zNear / deltaZ;
1486
1487 GLdouble proj[16] = {
1488 a, 0, 0, 0,
1489 0, b, 0, 0,
1490 c, d, e, -1.0f,
1491 0, 0, f, 0
1492 };
1493
1494 glMultMatrixd(proj);
1495
1496}
1497
1498
1499#ifdef G4OPENGL_VERSION_2
1500
1501// Associate the VBO drawer to the OpenGLViewer and the OpenGLSceneHandler
1502void G4OpenGLViewer::setVboDrawer(G4OpenGLVboDrawer* drawer) {
1503 fVboDrawer = drawer;
1504 try {
1505 G4OpenGLSceneHandler& sh = dynamic_cast<G4OpenGLSceneHandler&>(fSceneHandler);
1506 sh.setVboDrawer(fVboDrawer);
1507 } catch(std::bad_cast exp) { }
1508}
1509
1510#endif
1511
1512
1513G4String G4OpenGLViewerPickMap::print() {
1514 std::ostringstream txt;
1515 for (unsigned int a=0; a<fAttributes.size(); a++) {
1516 txt << fAttributes[a];
1517 if (a < fAttributes.size() - 1) txt << "\n";
1518 }
1519 return txt.str();
1520}
1521
1522#endif
double Y(double density)
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:34
std::vector< G4Plane3D > G4Planes
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define gl2psTextOpt
Definition: Geant4_gl2ps.h:44
const std::vector< const std::vector< G4AttValue > * > & GetAttValues() const
Definition: G4AttHolder.hh:59
const std::vector< const std::map< G4String, G4AttDef > * > & GetAttDefs() const
Definition: G4AttHolder.hh:61
Definition: G4Text.hh:72
Layout GetLayout() const
G4String GetText() const
@ centre
Definition: G4Text.hh:76
@ right
Definition: G4Text.hh:76
@ left
Definition: G4Text.hh:76
G4Point3D GetPosition() const
virtual void ResetView()
BasicVector3D< T > cross(const BasicVector3D< T > &v) const
BasicVector3D< T > unit() const
void set(T x1, T y1, T z1)
T dot(const BasicVector3D< T > &v) const
#define GL2PS_SVG
Definition: gl2ps.h:131
#define GL2PS_TEXT_BL
Definition: gl2ps.h:196
#define GL2PS_TEXT_BR
Definition: gl2ps.h:197
#define GL2PS_EPS
Definition: gl2ps.h:128
#define GL2PS_PDF
Definition: gl2ps.h:130
#define GL2PS_PS
Definition: gl2ps.h:127
#define GL2PS_TEXT_B
Definition: gl2ps.h:195
const char * name(G4int ptype)
#define buffer
Definition: xmlparse.cc:628