source: trunk/source/visualization/OpenGL/src/G4OpenGLStoredSceneHandler.cc~

Last change on this file was 1350, checked in by garnier, 14 years ago

update to last version 4.9.4

File size: 16.5 KB
Line 
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// $Id: G4OpenGLStoredSceneHandler.cc,v 1.46 2010/11/10 17:11:20 allison Exp $
28// GEANT4 tag $Name:  $
29//
30//
31// Andrew Walkden  10th February 1997
32// OpenGL stored scene - creates OpenGL display lists.
33
34#ifdef G4VIS_BUILD_OPENGL_DRIVER
35
36// Included here - problems with HP compiler if not before other includes?
37#include "G4NURBS.hh"
38
39// Here follows a special for Mesa, the OpenGL emulator.  Does not affect
40// other OpenGL's, as far as I'm aware.   John Allison 18/9/96.
41#define CENTERLINE_CLPP  /* CenterLine C++ workaround: */
42// Also seems to be required for HP's CC and AIX xlC, at least.
43
44#include "G4OpenGLStoredSceneHandler.hh"
45
46#include "G4PhysicalVolumeModel.hh"
47#include "G4VPhysicalVolume.hh"
48#include "G4LogicalVolume.hh"
49#include "G4Polyline.hh"
50#include "G4Polymarker.hh"
51#include "G4Text.hh"
52#include "G4Circle.hh"
53#include "G4Square.hh"
54#include "G4Polyhedron.hh"
55#include "G4AttHolder.hh"
56#include "G4OpenGLTransform3D.hh"
57#include "G4OpenGLViewer.hh"
58
59G4OpenGLStoredSceneHandler::PO::PO
60(G4int id,
61 const G4Transform3D& tr):
62  fDisplayListId(id),
63  fTransform(tr),
64  fPickName(0)
65{}
66
67G4OpenGLStoredSceneHandler::TO::TO
68(G4int id,
69 const G4Transform3D& tr):
70  fDisplayListId(id),
71  fTransform(tr),
72  fPickName(0),
73  fStartTime(-DBL_MAX),
74  fEndTime(DBL_MAX)
75{}
76
77G4OpenGLStoredSceneHandler::G4OpenGLStoredSceneHandler
78(G4VGraphicsSystem& system,
79 const G4String& name):
80G4OpenGLSceneHandler (system, fSceneIdCount++, name),
81fAddPrimitivePreambleNestingDepth (0),
82fTopPODL (0)
83{}
84
85G4OpenGLStoredSceneHandler::~G4OpenGLStoredSceneHandler ()
86{}
87
88void G4OpenGLStoredSceneHandler::AddPrimitivePreamble(const G4Visible& visible)
89{
90  // Track nesting depth to avoid recursive calls, for example, from a
91  // G4Polymarker that invokes a G4Circle...
92  fAddPrimitivePreambleNestingDepth++;
93  if (fAddPrimitivePreambleNestingDepth > 1) return;
94
95  // Because of our need to control colour of transients (display by
96  // time fading), display lists may only cover a single primitive.
97  // So display list setup is here.
98
99  if (fpViewer->GetViewParameters().IsPicking()) {
100    fPickMap[++fPickName] = 0;
101  }
102
103  const G4Colour& c = GetColour (visible);
104
105  if (fMemoryForDisplayLists) {
106    fDisplayListId = glGenLists (1);
107#ifdef G4DEBUG_VIS_OGL
108    printf("G4OpenGLStoredSceneHandler::AddPrimitivePreamble ->glGenList(1) : %d\n",fDisplayListId);
109#endif
110    if (glGetError() == GL_OUT_OF_MEMORY ||
111        fDisplayListId > fDisplayListLimit) {
112      G4cout <<
113  "********************* WARNING! ********************"
114  "\n*  Display list limit reached in OpenGL."
115  "\n*  Continuing drawing WITHOUT STORING. Scene only partially refreshable."
116  "\n*  Current limit: " << fDisplayListLimit <<
117  ".  Change with \"/vis/ogl/set/displayListLimit\"."
118  "\n***************************************************"
119             << G4endl;
120      fMemoryForDisplayLists = false;
121    }
122  }
123  if (fMemoryForDisplayLists) {
124    if (fReadyForTransients) {
125      TO to(fDisplayListId, *fpObjectTransformation);
126      to.fPickName = fPickName;
127      to.fColour = c;
128      const G4VisAttributes* pVA =
129        fpViewer->GetApplicableVisAttributes(visible.GetVisAttributes());
130      to.fStartTime = pVA->GetStartTime();
131      to.fEndTime = pVA->GetEndTime();
132      fTOList.push_back(to);
133      glDrawBuffer (GL_FRONT);
134      glPushMatrix();
135      G4OpenGLTransform3D oglt (*fpObjectTransformation);
136      glMultMatrixd (oglt.GetGLMatrix ());
137      glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
138      glNewList (fDisplayListId, GL_COMPILE_AND_EXECUTE);
139    }
140    else {
141      PO po(fDisplayListId, *fpObjectTransformation);
142      po.fPickName = fPickName;
143      fPOList.push_back(po);
144      glNewList (fDisplayListId, GL_COMPILE);
145      glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
146    }
147  } else {
148    glDrawBuffer (GL_FRONT);
149    glPushMatrix();
150    G4OpenGLTransform3D oglt (*fpObjectTransformation);
151    glMultMatrixd (oglt.GetGLMatrix ());
152    glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
153  }
154
155  if (fProcessing2D) {
156    // Push current 3D world matrices and load identity to define screen
157    // coordinates...
158    glMatrixMode (GL_PROJECTION);
159    glPushMatrix();
160    glLoadIdentity();
161    glOrtho (-1., 1., -1., 1., -G4OPENGL_FLT_BIG, G4OPENGL_FLT_BIG);
162    glMatrixMode (GL_MODELVIEW);
163    glPushMatrix();
164    glLoadIdentity();
165    G4OpenGLTransform3D oglt (*fpObjectTransformation);
166    glMultMatrixd (oglt.GetGLMatrix ());
167    glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
168  }
169}
170
171void G4OpenGLStoredSceneHandler::AddPrimitivePostamble()
172{
173  if (fProcessing2D) {
174    // Pop current 3D world matrices back again...
175    glMatrixMode (GL_PROJECTION);
176    glPopMatrix();
177    glMatrixMode (GL_MODELVIEW);
178    glPopMatrix();
179  }
180
181  //  if ((glGetError() == GL_TABLE_TOO_LARGE) || (glGetError() == GL_OUT_OF_MEMORY)) {  // Could close?
182  if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
183    G4cout <<
184      "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
185      "  display List for fTopPODL - try OpenGL Immediated mode."
186           << G4endl;
187  }
188  if (fMemoryForDisplayLists) {
189    glEndList();
190    if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
191      G4cout <<
192        "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
193        "  display List for fTopPODL - try OpenGL Immediated mode."
194             << G4endl;
195    }
196  }
197  if (fReadyForTransients || !fMemoryForDisplayLists) {
198    glPopMatrix();
199    glFlush ();
200    glDrawBuffer (GL_BACK);
201  }
202  fAddPrimitivePreambleNestingDepth--;
203}
204
205void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polyline& polyline)
206{
207#ifdef G4DEBUG_VIS_OGL
208    printf("G4OpenGLStoredSceneHandler::AddPrimitive polyline\n");
209#endif
210  AddPrimitivePreamble(polyline);
211  G4OpenGLSceneHandler::AddPrimitive(polyline);
212  AddPrimitivePostamble();
213}
214
215void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polymarker& polymarker)
216{
217#ifdef G4DEBUG_VIS_OGL
218    printf("G4OpenGLStoredSceneHandler::AddPrimitive polymarker\n");
219#endif
220  AddPrimitivePreamble(polymarker);
221  G4OpenGLSceneHandler::AddPrimitive(polymarker);
222  AddPrimitivePostamble();
223}
224
225void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Text& text)
226{
227  // Note: colour is still handled in
228  // G4OpenGLSceneHandler::AddPrimitive(const G4Text&), so it still
229  // gets into the display list
230#ifdef G4DEBUG_VIS_OGL
231    printf("G4OpenGLStoredSceneHandler::AddPrimitive Text\n");
232#endif
233  AddPrimitivePreamble(text);
234  G4OpenGLSceneHandler::AddPrimitive(text);
235  AddPrimitivePostamble();
236}
237
238void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Circle& circle)
239{
240#ifdef G4DEBUG_VIS_OGL
241    printf("G4OpenGLStoredSceneHandler::AddPrimitive circle\n");
242#endif
243  AddPrimitivePreamble(circle);
244  G4OpenGLSceneHandler::AddPrimitive(circle);
245  AddPrimitivePostamble();
246}
247
248void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Square& square)
249{
250#ifdef G4DEBUG_VIS_OGL
251    printf("G4OpenGLStoredSceneHandler::AddPrimitive square\n");
252#endif
253  AddPrimitivePreamble(square);
254  G4OpenGLSceneHandler::AddPrimitive(square);
255  AddPrimitivePostamble();
256}
257
258void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Scale& scale)
259{
260  // Let base class split into primitives.
261  G4OpenGLSceneHandler::AddPrimitive(scale);
262}
263
264void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polyhedron& polyhedron)
265{
266  // Note: colour is still handled in
267  // G4OpenGLSceneHandler::AddPrimitive(const G4Polyhedron&), so it still
268  // gets into the display list
269#ifdef G4DEBUG_VIS_OGL
270    printf("G4OpenGLStoredSceneHandler::AddPrimitive polyhedron\n");
271#endif
272  AddPrimitivePreamble(polyhedron);
273  G4OpenGLSceneHandler::AddPrimitive(polyhedron);
274  AddPrimitivePostamble();
275}
276
277void G4OpenGLStoredSceneHandler::AddPrimitive (const G4NURBS& nurbs)
278{
279  // Note: colour is still handled in
280  // G4OpenGLSceneHandler::AddPrimitive(const G4NURBS&), so it still
281  // gets into the display list
282#ifdef G4DEBUG_VIS_OGL
283    printf("G4OpenGLStoredSceneHandler::AddPrimitive nurbs\n");
284#endif
285  AddPrimitivePreamble(nurbs);
286  G4OpenGLSceneHandler::AddPrimitive(nurbs);
287  AddPrimitivePostamble();
288}
289
290void G4OpenGLStoredSceneHandler::BeginPrimitives
291(const G4Transform3D& objectTransformation)
292
293  G4OpenGLSceneHandler::BeginPrimitives (objectTransformation);
294
295  // Display list setup moved to AddPrimitivePreamble.  See notes there.
296}
297
298void G4OpenGLStoredSceneHandler::EndPrimitives ()
299{
300  G4OpenGLSceneHandler::EndPrimitives ();
301}
302
303void G4OpenGLStoredSceneHandler::BeginPrimitives2D
304(const G4Transform3D& objectTransformation)
305{
306  G4OpenGLSceneHandler::BeginPrimitives2D(objectTransformation);
307}
308
309void G4OpenGLStoredSceneHandler::EndPrimitives2D ()
310{
311  G4OpenGLSceneHandler::EndPrimitives2D ();
312}
313
314void G4OpenGLStoredSceneHandler::BeginModeling () {
315  G4VSceneHandler::BeginModeling();
316  ClearStore();  // ...and all that goes with it.
317  /* Debug...
318  fDisplayListId = glGenLists (1);
319  G4cout << "OGL::fDisplayListId (start): " << fDisplayListId << G4endl;
320  */
321}
322
323void G4OpenGLStoredSceneHandler::EndModeling () {
324  // Make a List which calls the other lists.
325  fTopPODL = glGenLists (1);
326#ifdef G4DEBUG_VIS_OGL
327    printf("G4OpenGLStoredSceneHandler::EndModeling ->glGenList(1) : %d\n",fTopPODL);
328#endif
329  if (glGetError() == GL_OUT_OF_MEMORY) {  // Could pre-allocate?
330    G4cout <<
331      "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
332      "  display List for fTopPODL - try OpenGL Immediated mode."
333           << G4endl;
334  } else {
335    glNewList (fTopPODL, GL_COMPILE_AND_EXECUTE); {
336      for (size_t i = 0; i < fPOList.size (); i++) {
337        glPushMatrix();
338        G4OpenGLTransform3D oglt (fPOList[i].fTransform);
339        glMultMatrixd (oglt.GetGLMatrix ());
340        if (fpViewer->GetViewParameters().IsPicking())
341          glLoadName(fPOList[i].fPickName);
342        glCallList (fPOList[i].fDisplayListId);
343        glPopMatrix();
344      }
345    }
346    glEndList ();
347    if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
348      G4cout <<
349        "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
350        "  display List for fTopPODL - try OpenGL Immediated mode."
351             << G4endl;
352    }
353  }
354
355  G4VSceneHandler::EndModeling ();
356
357  /* Debug...
358  fDisplayListId = glGenLists (1);
359  G4cout << "OGL::fDisplayListId (end): " << fDisplayListId << G4endl;
360  */
361}
362
363void G4OpenGLStoredSceneHandler::ClearStore () {
364
365  //G4cout << "G4OpenGLStoredSceneHandler::ClearStore" << G4endl;
366
367  G4VSceneHandler::ClearStore ();  // Sets need kernel visit, etc.
368
369  // Delete OpenGL permanent display lists.
370  for (size_t i = 0; i < fPOList.size (); i++)
371    glDeleteLists (fPOList[i].fDisplayListId, 1);
372  if (fTopPODL) glDeleteLists (fTopPODL, 1);
373  fTopPODL = 0;
374
375  // Clear other lists, dictionary, etc.
376  fPOList.clear ();
377  fSolidMap.clear ();
378  ClearAndDestroyAtts();
379
380  // ...and clear transient store...
381  for (size_t i = 0; i < fTOList.size (); i++)
382    glDeleteLists(fTOList[i].fDisplayListId, 1);
383  fTOList.clear ();
384
385  fMemoryForDisplayLists = true;
386}
387
388void G4OpenGLStoredSceneHandler::ClearTransientStore () {
389
390  //G4cout << "G4OpenGLStoredSceneHandler::ClearTransientStore" << G4endl;
391
392  G4VSceneHandler::ClearTransientStore ();
393
394  // Delete OpenGL transient display lists and Transient Objects themselves.
395  for (size_t i = 0; i < fTOList.size (); i++)
396    glDeleteLists(fTOList[i].fDisplayListId, 1);
397  fTOList.clear ();
398
399  fMemoryForDisplayLists = true;
400
401  // Make sure screen corresponds to graphical database...
402  if (fpViewer) {
403    fpViewer -> SetView ();
404    fpViewer -> ClearView ();
405    fpViewer -> DrawView ();
406  }
407}
408
409void G4OpenGLStoredSceneHandler::RequestPrimitives (const G4VSolid& solid)
410{
411  if (fReadyForTransients) {
412    // Always draw transient solids, e.g., hits represented as solids.
413    // (As we have no control over the order of drawing of transient
414    // objects, we cannot do anything about transparent ones, as
415    // below, so always draw them.)
416    G4VSceneHandler::RequestPrimitives (solid);
417    return;
418  }
419
420  // For non-transient (run-duration) objects, ensure transparent
421  // objects are drawn last.  The problem of
422  // blending/transparency/alpha is quite a tricky one - see History
423  // of opengl-V07-01-01/2/3.
424  // Get vis attributes - pick up defaults if none.
425  const G4VisAttributes* pVA =
426    fpViewer -> GetApplicableVisAttributes(fpVisAttribs);
427  const G4Colour& c = pVA -> GetColour ();
428  G4double opacity = c.GetAlpha ();
429
430  if (!fSecondPass) {
431    G4bool transparency_enabled = true;
432    G4OpenGLViewer* pViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
433    if (pViewer) transparency_enabled = pViewer->transparency_enabled;
434    if (transparency_enabled && opacity < 1.) {
435      // On first pass, transparent objects are not drawn, but flag is set...
436      fSecondPassRequested = true;
437      return;
438    }
439  }
440
441  // On second pass, opaque objects are not drwan...
442  if (fSecondPass && opacity >= 1.) return;
443
444  G4PhysicalVolumeModel* pPVModel =
445    dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
446 
447  if (pPVModel) {
448    // If part of the geometry hierarchy, i.e., from a
449    // G4PhysicalVolumeModel, check if a display list already exists for
450    // this solid, re-use it if possible.  We could be smarter, and
451    // recognise repeated branches of the geometry hierarchy, for
452    // example.  But this algorithm should be secure, I think...
453    const G4VSolid* pSolid = &solid;
454    EAxis axis = kRho;
455    G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
456    if (pCurrentPV -> IsReplicated ()) {
457      G4int nReplicas;
458      G4double width;
459      G4double offset;
460      G4bool consuming;
461      pCurrentPV->GetReplicationData(axis,nReplicas,width,offset,consuming);
462    }
463    // Provided it is not parametrised (because if so, the
464    // solid's parameters might have been changed)...
465    if (!(pCurrentPV -> IsParameterised ()) &&
466        // Provided it is not replicated radially (because if so, the
467        // solid's parameters will have been changed)...
468        !(pCurrentPV -> IsReplicated () && axis == kRho) &&
469        // ...and if the solid has already been rendered...
470        (fSolidMap.find (pSolid) != fSolidMap.end ())) {
471      fDisplayListId = fSolidMap [pSolid];
472      PO po(fDisplayListId,*fpObjectTransformation);
473      if (fpViewer->GetViewParameters().IsPicking()) {
474        G4AttHolder* holder = new G4AttHolder;
475        // Load G4Atts from G4VisAttributes, if any...
476        const G4VisAttributes* va = pPVModel->GetCurrentLV()->GetVisAttributes();
477        if (va) {
478          const std::map<G4String,G4AttDef>* vaDefs = va->GetAttDefs();
479          if (vaDefs) holder->AddAtts(va->CreateAttValues(), vaDefs);
480        }
481        // Load G4Atts from G4PhysicalVolumeModel...
482        const std::map<G4String,G4AttDef>* defs = pPVModel->GetAttDefs();
483        if (defs) holder->AddAtts(pPVModel->CreateCurrentAttValues(), defs);
484        fPickMap[++fPickName] = holder;
485        po.fPickName = fPickName;
486      }
487      fPOList.push_back(po);
488    }
489    else {
490      G4VSceneHandler::RequestPrimitives (solid);
491      fSolidMap [pSolid] = fDisplayListId;
492    }
493    return;
494  }
495
496  // Otherwise invoke base class method...
497  G4VSceneHandler::RequestPrimitives (solid);
498}
499
500G4int G4OpenGLStoredSceneHandler::fSceneIdCount = 0;
501
502G4int  G4OpenGLStoredSceneHandler::fDisplayListId = 0;
503G4bool G4OpenGLStoredSceneHandler::fMemoryForDisplayLists = true;
504G4int  G4OpenGLStoredSceneHandler::fDisplayListLimit = 50000;
505
506#endif
Note: See TracBrowser for help on using the repository browser.