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