Geant4-11
G4OpenGLStoredSceneHandler.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 10th February 1997
30// OpenGL stored scene - creates OpenGL display lists.
31
33
36#include "G4VPhysicalVolume.hh"
37#include "G4LogicalVolume.hh"
38#include "G4Polyline.hh"
39#include "G4Polymarker.hh"
40#include "G4Text.hh"
41#include "G4Circle.hh"
42#include "G4Square.hh"
43#include "G4Polyhedron.hh"
44#include "G4AttHolder.hh"
46#include "G4OpenGLViewer.hh"
47#include "G4AttHolder.hh"
48
49#include <typeinfo>
50
52
56
58 fDisplayListId(0),
59 fPickName(0),
60 fpG4TextPlus(0),
61 fMarkerOrPolyline(false)
62{}
63
66 fTransform(po.fTransform),
68 fColour(po.fColour),
69 fpG4TextPlus(po.fpG4TextPlus? new G4TextPlus(*po.fpG4TextPlus): 0),
70 fMarkerOrPolyline(po.fMarkerOrPolyline)
71{}
72
75 fTransform(tr),
76 fPickName(0),
77 fpG4TextPlus(0),
78 fMarkerOrPolyline(false)
79{}
80
82{
83 delete fpG4TextPlus;
84}
85
86G4OpenGLStoredSceneHandler::PO& G4OpenGLStoredSceneHandler::PO::operator=
88{
89 if (&rhs == this) return *this;
90 fDisplayListId = rhs.fDisplayListId;
91 fTransform = rhs.fTransform;
92 fPickName = rhs.fPickName;
93 fColour = rhs.fColour;
94 fpG4TextPlus = rhs.fpG4TextPlus? new G4TextPlus(*rhs.fpG4TextPlus): 0;
95 fMarkerOrPolyline = rhs.fMarkerOrPolyline;
96 return *this;
97}
98
101 fPickName(0),
102 fStartTime(-G4VisAttributes::fVeryLongTime),
103 fEndTime(G4VisAttributes::fVeryLongTime),
104 fpG4TextPlus(0),
105 fMarkerOrPolyline(false)
106{}
107
110 fTransform(to.fTransform),
112 fStartTime(to.fStartTime),
113 fEndTime(to.fEndTime),
114 fColour(to.fColour),
115 fpG4TextPlus(to.fpG4TextPlus? new G4TextPlus(*to.fpG4TextPlus): 0),
116 fMarkerOrPolyline(to.fMarkerOrPolyline)
117{}
118
120 fDisplayListId(id),
121 fTransform(tr),
122 fPickName(0),
123 fStartTime(-G4VisAttributes::fVeryLongTime),
124 fEndTime(G4VisAttributes::fVeryLongTime),
125 fpG4TextPlus(0),
126 fMarkerOrPolyline(false)
127{}
128
130{
131 delete fpG4TextPlus;
132}
133
134G4OpenGLStoredSceneHandler::TO& G4OpenGLStoredSceneHandler::TO::operator=
136{
137 if (&rhs == this) return *this;
138 fDisplayListId = rhs.fDisplayListId;
139 fTransform = rhs.fTransform;
140 fPickName = rhs.fPickName;
141 fStartTime = rhs.fStartTime;
142 fEndTime = rhs.fEndTime;
143 fColour = rhs.fColour;
144 fpG4TextPlus = rhs.fpG4TextPlus? new G4TextPlus(*rhs.fpG4TextPlus): 0;
145 fMarkerOrPolyline = rhs.fMarkerOrPolyline;
146 return *this;
147}
148
150(G4VGraphicsSystem& system,
151 const G4String& name):
153fTopPODL (0)
154{}
155
157{}
158
160(const G4Transform3D& objectTransformation)
161{
162 G4OpenGLSceneHandler::BeginPrimitives (objectTransformation);
163 if (fReadyForTransients) glDrawBuffer (GL_FRONT);
164 // Display list setup moved to AddPrimitivePreamble. See notes there.
165}
166
168{
169 // See all primitives immediately... At least soon...
170 ScaledFlush();
171 glDrawBuffer (GL_BACK);
173}
174
176(const G4Transform3D& objectTransformation)
177{
178 G4OpenGLSceneHandler::BeginPrimitives2D(objectTransformation);
179 if (fReadyForTransients) glDrawBuffer (GL_FRONT);
180}
181
183{
184 // See all primitives immediately... At least soon...
185 ScaledFlush();
186 glDrawBuffer (GL_BACK);
188}
189
191{
192 return AddPrimitivePreambleInternal(visible, true, false);
193}
195{
196 return AddPrimitivePreambleInternal(visible, false, true);
197}
199{
200 return AddPrimitivePreambleInternal(visible, false, false);
201}
202
204(const G4Visible& visible, bool isMarker, bool isPolyline)
205{
206// Get applicable vis attributes for all primitives.
208 const G4Colour& c = GetColour ();
209 G4double opacity = c.GetAlpha ();
210
211 G4bool transparency_enabled = true;
212 G4bool isMarkerNotHidden = true;
213 G4OpenGLViewer* pOGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
214 if (pOGLViewer) {
215 transparency_enabled = pOGLViewer->transparency_enabled;
216 isMarkerNotHidden = pOGLViewer->fVP.IsMarkerNotHidden();
217 }
218
219 G4bool isTransparent = opacity < 1.;
220 G4bool isMarkerOrPolyline = isMarker || isPolyline;
221 G4bool treatAsTransparent = transparency_enabled && isTransparent;
222 G4bool treatAsNotHidden = isMarkerNotHidden && isMarkerOrPolyline;
223
224 if (fProcessing2D) glDisable (GL_DEPTH_TEST);
225 else {
226 if (isMarkerOrPolyline && isMarkerNotHidden)
227 glDisable (GL_DEPTH_TEST);
228 else {glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL);}
229 }
230
231 if (fThreePassCapable) {
232
233 // Ensure transparent objects are drawn opaque ones and before
234 // non-hidden markers. The problem of blending/transparency/alpha
235 // is quite a tricky one - see History of opengl-V07-01-01/2/3.
237 // First pass...
238 if (treatAsTransparent) { // Request pass for transparent objects...
240 }
241 if (treatAsNotHidden) { // Request pass for non-hidden markers...
243 }
244 // On first pass, transparent objects and non-hidden markers are not drawn...
245 if (treatAsTransparent || treatAsNotHidden) {
246 return false; // No further processing.
247 }
248 }
249
250 // On second pass, only transparent objects are drawn...
252 if (!treatAsTransparent) {
253 return false; // No further processing.
254 }
255 }
256
257 // On third pass, only non-hidden markers are drawn...
259 if (!treatAsNotHidden) {
260 return false; // No further processing.
261 }
262 }
263 } // fThreePassCapable
264
265 // Loads G4Atts for picking...
266 G4bool isPicking = false;
268 isPicking = true;
269 glLoadName(++fPickName);
270 G4AttHolder* holder = new G4AttHolder;
271 LoadAtts(visible, holder);
272 fPickMap[fPickName] = holder;
273 }
274
275 const G4VSolid* pSolid = 0;
276
277 // Can we re-use a display list?
278 if (isMarker)
279 // It is a marker, which may have its own position relative to fObjectTransformation
280 goto end_of_display_list_reuse_test;
282 // Touchables have been modified - don't risk re-using display list.
283 goto end_of_display_list_reuse_test;
284 { // It is a viable candidate for display list re-use
285 G4PhysicalVolumeModel* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
286 if (pPVModel) {
287 // Check that it isn't a G4LogicalVolumeModel (which is a sub-class of
288 // G4PhysicalVolumeModel).
289 G4LogicalVolumeModel* pLVModel =
290 dynamic_cast<G4LogicalVolumeModel*>(pPVModel);
291 if (pLVModel)
292 // Logical volume model - don't re-use.
293 goto end_of_display_list_reuse_test;
294 // If part of the geometry hierarchy, i.e., from a
295 // G4PhysicalVolumeModel, check if a display list already exists for
296 // this solid, re-use it if possible. We could be smarter, and
297 // recognise repeated branches of the geometry hierarchy, for
298 // example. But this algorithm should be secure, I think...
299 G4VPhysicalVolume* pPV = pPVModel->GetCurrentPV();
300 if (!pPV)
301 // It's probably a dummy model, e.g., for a user-drawn hit?
302 goto end_of_display_list_reuse_test;
303 G4LogicalVolume* pLV = pPV->GetLogicalVolume();
304 if (!pLV)
305 // Dummy model again?
306 goto end_of_display_list_reuse_test;
307 pSolid = pLV->GetSolid();
308 EAxis axis = kRho;
309 G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
310 if (pCurrentPV -> IsReplicated ()) {
311 G4int nReplicas;
312 G4double width;
313 G4double offset;
314 G4bool consuming;
315 pCurrentPV->GetReplicationData(axis,nReplicas,width,offset,consuming);
316 }
317 // Provided it is not parametrised (because if so, the
318 // solid's parameters might have been changed)...
319 if (!(pCurrentPV -> IsParameterised ()) &&
320 // Provided it is not replicated radially (because if so, the
321 // solid's parameters will have been changed)...
322 !(pCurrentPV -> IsReplicated () && axis == kRho) &&
323 // ...and if the solid has already been rendered...
324 (fSolidMap.find (pSolid) != fSolidMap.end ())) {
325 fDisplayListId = fSolidMap [pSolid];
327 if (isPicking) po.fPickName = fPickName;
328 po.fColour = c;
329 po.fMarkerOrPolyline = isMarkerOrPolyline;
330 fPOList.push_back(po);
331 // No need to test if gl commands are used (result of
332 // ExtraPOProcessing) because we have already decided they will
333 // not, at least not here. Also, pass a dummy G4Visible since
334 // not relevant for G4PhysicalVolumeModel.
335 (void) ExtraPOProcessing(G4Visible(), fPOList.size() - 1);
336 return false; // No further processing.
337 }
338 }
339 }
340end_of_display_list_reuse_test:
341
342 // Because of our need to control colour of transients (display by
343 // time fading), display lists may only cover a single primitive.
344 // So display list setup is here.
345
347 fDisplayListId = glGenLists (1);
348 if (glGetError() == GL_OUT_OF_MEMORY ||
350 G4cout <<
351 "********************* WARNING! ********************"
352 "\n* Display list limit reached in OpenGL."
353 "\n* Continuing drawing WITHOUT STORING. Scene only partially refreshable."
354 "\n* Current limit: " << fDisplayListLimit << " primitives"
355 ". Change with \"/vis/ogl/set/displayListLimit\"."
356 "\n***************************************************"
357 << G4endl;
359 }
360 }
361
362 if (pSolid) fSolidMap [pSolid] = fDisplayListId;
363
367 if (isPicking) to.fPickName = fPickName;
368 to.fColour = c;
371 to.fMarkerOrPolyline = isMarkerOrPolyline;
372 fTOList.push_back(to);
373 // For transient objects, colour, transformation, are kept in
374 // the TO, so should *not* be in the display list. As mentioned
375 // above, in some cases (display-by-time fading) we need to have
376 // independent control of colour. But for now transform and set
377 // colour for immediate display.
378 glPushMatrix();
380 glMultMatrixd (oglt.GetGLMatrix ());
381 if (transparency_enabled) {
382 glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
383 } else {
384 glColor3d(c.GetRed(),c.GetGreen(),c.GetBlue());
385 }
386 (void) ExtraTOProcessing(visible, fTOList.size() - 1);
387 // Ignore return value of the above. If this visible does not use
388 // gl commands, a display list is created that is empty and not
389 // used.
390 glNewList (fDisplayListId, GL_COMPILE_AND_EXECUTE);
391 } else {
393 if (isPicking) po.fPickName = fPickName;
394 po.fColour = c;
395 po.fMarkerOrPolyline = isMarkerOrPolyline;
396 fPOList.push_back(po);
397 // For permanent objects, colour is kept in the PO, so should
398 // *not* be in the display list. This is so that sub-classes
399 // may implement colour modifications according to their own
400 // criteria, e.g., scene tree slider in Qt. But for now set
401 // colour for immediate display.
402 if (transparency_enabled) {
403 glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
404 } else {
405 glColor3d(c.GetRed(),c.GetGreen(),c.GetBlue());
406 }
407 G4bool usesGLCommands = ExtraPOProcessing(visible, fPOList.size() - 1);
408 // Transients are displayed as they come (GL_COMPILE_AND_EXECUTE
409 // above) but persistents are compiled into display lists
410 // (GL_COMPILE only) and then drawn from the display lists with
411 // their fObjectTransformation as stored in fPOList. Thus,
412 // there is no need to do glMultMatrixd here. If
413 // ExtraPOProcessing says the visible object does not use gl
414 // commands, simply return and abandon further processing. It
415 // is assumed that all relevant information is kept in the
416 // POList.
417 if (!usesGLCommands) return false;
418 glNewList (fDisplayListId, GL_COMPILE);
419 }
420 } else { // Out of memory (or being used when display lists not required).
421 glPushMatrix();
423 glMultMatrixd (oglt.GetGLMatrix ());
424 if (transparency_enabled) {
425 glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
426 } else {
427 glColor3d(c.GetRed(),c.GetGreen(),c.GetBlue());
428 }
429 }
430
431 if (fProcessing2D) {
432 // Push current 3D world matrices and load identity to define screen
433 // coordinates...
434 glMatrixMode (GL_PROJECTION);
435 glPushMatrix();
436 glLoadIdentity();
437 if (pOGLViewer) {
438 pOGLViewer->g4GlOrtho (-1., 1., -1., 1., -G4OPENGL_FLT_BIG, G4OPENGL_FLT_BIG);
439 }
440 glMatrixMode (GL_MODELVIEW);
441 glPushMatrix();
442 glLoadIdentity();
444 glMultMatrixd (oglt.GetGLMatrix ());
445 glDisable (GL_LIGHTING);
446 } else {
447 if (isMarker) {
448 glDisable (GL_LIGHTING);
449 } else {
450 glEnable (GL_LIGHTING);
451 }
452 }
453
454 return true;
455}
456
458{
459 if (fProcessing2D) {
460 // Pop current 3D world matrices back again...
461 glMatrixMode (GL_PROJECTION);
462 glPopMatrix();
463 glMatrixMode (GL_MODELVIEW);
464 glPopMatrix();
465 }
466
467 // if ((glGetError() == GL_TABLE_TOO_LARGE) || (glGetError() == GL_OUT_OF_MEMORY)) { // Could close?
468 if (glGetError() == GL_OUT_OF_MEMORY) { // Could close?
469 G4cerr <<
470 "ERROR: G4OpenGLStoredSceneHandler::AddPrimitivePostamble: Failure"
471 " to allocate display List for fTopPODL - try OpenGL Immediated mode."
472 << G4endl;
473 }
475 glEndList();
476 if (glGetError() == GL_OUT_OF_MEMORY) { // Could close?
477 G4cerr <<
478 "ERROR: G4OpenGLStoredSceneHandler::AddPrimitivePostamble: Failure"
479 " to allocate display List for fTopPODL - try OpenGL Immediated mode."
480 << G4endl;
481 }
482 }
484 glPopMatrix();
485 }
486}
487
489{
490 G4bool furtherprocessing = AddPrimitivePreamble(polyline);
491 if (furtherprocessing) {
494 }
495}
496
498{
499 G4bool furtherprocessing = AddPrimitivePreamble(polymarker);
500 if (furtherprocessing) {
503 }
504}
505
507{
508 // Note: colour is still handled in
509 // G4OpenGLSceneHandler::AddPrimitive(const G4Text&), so it still
510 // gets into the display list
511 G4bool furtherprocessing = AddPrimitivePreamble(text);
512 if (furtherprocessing) {
515 }
516}
517
519{
520 G4bool furtherprocessing = AddPrimitivePreamble(circle);
521 if (furtherprocessing) {
524 }
525}
526
528{
529 G4bool furtherprocessing = AddPrimitivePreamble(square);
530 if (furtherprocessing) {
533 }
534}
535
537{
538 // Note: colour is still handled in
539 // G4OpenGLSceneHandler::AddPrimitive(const G4Polyhedron&), so it still
540 // gets into the display list
541 G4bool furtherprocessing = AddPrimitivePreamble(polyhedron);
542 if (furtherprocessing) {
545 }
546}
547
550 /* Debug...
551 fDisplayListId = glGenLists (1);
552 G4cout << "OGL::fDisplayListId (start): " << fDisplayListId << G4endl;
553 */
554}
555
557 // Make a List which calls the other lists.
558 fTopPODL = glGenLists (1);
559 if (glGetError() == GL_OUT_OF_MEMORY) { // Could pre-allocate?
560 G4cerr <<
561 "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
562 " display List for fTopPODL - try OpenGL Immediated mode."
563 << G4endl;
564 } else {
565
566 glNewList (fTopPODL, GL_COMPILE); {
567 for (size_t i = 0; i < fPOList.size (); i++) {
568 glPushMatrix();
569 G4OpenGLTransform3D oglt (fPOList[i].fTransform);
570 glMultMatrixd (oglt.GetGLMatrix ());
572 glLoadName(fPOList[i].fPickName);
573 glCallList (fPOList[i].fDisplayListId);
574 glPopMatrix();
575 }
576 }
577 glEndList ();
578
579 if (glGetError() == GL_OUT_OF_MEMORY) { // Could close?
580 G4cerr <<
581 "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
582 " display List for fTopPODL - try OpenGL Immediated mode."
583 << G4endl;
584 }
585 }
586
588}
589
591
592 //G4cout << "G4OpenGLStoredSceneHandler::ClearStore" << G4endl;
593
594 G4VSceneHandler::ClearStore (); // Sets need kernel visit, etc.
595
596 // Delete OpenGL permanent display lists.
597 for (size_t i = 0; i < fPOList.size (); i++)
598 glDeleteLists (fPOList[i].fDisplayListId, 1);
599 if (fTopPODL) glDeleteLists (fTopPODL, 1);
600 fTopPODL = 0;
601
602 // Clear other lists, dictionary, etc.
603 fPOList.clear ();
604 fSolidMap.clear ();
606
607 // ...and clear transient store...
608 for (size_t i = 0; i < fTOList.size (); i++)
609 glDeleteLists(fTOList[i].fDisplayListId, 1);
610 fTOList.clear ();
611
613}
614
616{
617 //G4cout << "G4OpenGLStoredSceneHandler::ClearTransientStore" << G4endl;
618
619 // Delete OpenGL transient display lists and Transient Objects themselves.
620 for (size_t i = 0; i < fTOList.size (); i++)
621 glDeleteLists(fTOList[i].fDisplayListId, 1);
622 fTOList.clear ();
623
625
626 // Redraw the scene ready for the next event.
627 if (fpViewer) {
628 fpViewer -> SetView ();
629 fpViewer -> ClearView ();
630 fpViewer -> DrawView ();
631 }
632}
#define G4OPENGL_FLT_BIG
Definition: G4OpenGL.hh:89
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
G4double GetBlue() const
Definition: G4Colour.hh:154
G4double GetAlpha() const
Definition: G4Colour.hh:155
G4double GetRed() const
Definition: G4Colour.hh:152
G4double GetGreen() const
Definition: G4Colour.hh:153
G4VSolid * GetSolid() const
virtual void BeginPrimitives2D(const G4Transform3D &objectTransformation)
void AddPrimitive(const G4Polyline &)
virtual void BeginPrimitives(const G4Transform3D &objectTransformation)
std::map< GLuint, G4AttHolder * > fPickMap
virtual G4bool ExtraPOProcessing(const G4Visible &, size_t)
bool AddPrimitivePreambleInternal(const G4Visible &visible, bool isMarker, bool isPolyline)
std::map< const G4VSolid *, G4int, std::less< const G4VSolid * > > fSolidMap
void AddPrimitive(const G4Polyline &)
G4bool AddPrimitivePreamble(const G4VMarker &visible)
G4OpenGLStoredSceneHandler(G4VGraphicsSystem &system, const G4String &name="")
virtual G4bool ExtraTOProcessing(const G4Visible &, size_t)
void BeginPrimitives(const G4Transform3D &objectTransformation)
void BeginPrimitives2D(const G4Transform3D &objectTransformation)
const GLdouble * GetGLMatrix()
G4bool transparency_enabled
void g4GlOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
G4VPhysicalVolume * GetCurrentPV() const
Definition: G4Text.hh:72
G4LogicalVolume * GetLogicalVolume() const
virtual void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const =0
virtual void BeginModeling()
void LoadAtts(const G4Visible &, G4AttHolder *)
const G4Colour & GetColour()
G4Transform3D fObjectTransformation
virtual void EndModeling()
G4VViewer * fpViewer
const G4VisAttributes * fpVisAttribs
virtual void ClearStore()
const G4VisAttributes * GetApplicableVisAttributes(const G4VisAttributes *) const
const G4ViewParameters & GetViewParameters() const
G4ViewParameters fVP
Definition: G4VViewer.hh:219
const std::vector< G4ModelingParameters::VisAttributesModifier > & GetVisAttributesModifiers() const
G4bool IsMarkerNotHidden() const
G4bool IsPicking() const
G4double GetStartTime() const
G4double GetEndTime() const
const G4VisAttributes * GetVisAttributes() const
EAxis
Definition: geomdefs.hh:54
@ kRho
Definition: geomdefs.hh:58
const char * name(G4int ptype)