source: trunk/source/visualization/OpenGL/src/G4OpenGLStoredSceneHandler.cc @ 1343

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

HEAD

  • Property svn:mime-type set to text/cpp
File size: 15.6 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.44 2010/11/06 12:09:41 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    if (glGetError() == GL_OUT_OF_MEMORY ||
108        fDisplayListId > fDisplayListLimit + fDisplayListBase) {
109      G4cout <<
110        "********************* WARNING! ********************"
111        "\n  Display list limit reached in OpenGL."
112        "\n  Continuing drawing in IMMEDIATE MODE."
113        "\n  Current limit: "
114             << fDisplayListLimit <<
115        ".  Change with \"/vis/ogl/set/displayListLimit\"."
116        "\n***************************************************"
117             << G4endl;
118      fMemoryForDisplayLists = false;
119    }
120  }
121  if (fMemoryForDisplayLists) {
122    if (fReadyForTransients) {
123      TO to(fDisplayListId, *fpObjectTransformation);
124      to.fPickName = fPickName;
125      to.fColour = c;
126      const G4VisAttributes* pVA =
127        fpViewer->GetApplicableVisAttributes(visible.GetVisAttributes());
128      to.fStartTime = pVA->GetStartTime();
129      to.fEndTime = pVA->GetEndTime();
130      fTOList.push_back(to);
131      glDrawBuffer (GL_FRONT);
132      glPushMatrix();
133      G4OpenGLTransform3D oglt (*fpObjectTransformation);
134      glMultMatrixd (oglt.GetGLMatrix ());
135      glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
136      glNewList (fDisplayListId, GL_COMPILE_AND_EXECUTE);
137    }
138    else {
139      PO po(fDisplayListId, *fpObjectTransformation);
140      po.fPickName = fPickName;
141      fPOList.push_back(po);
142      glNewList (fDisplayListId, GL_COMPILE);
143      glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
144    }
145  } else {
146    glDrawBuffer (GL_FRONT);
147    glPushMatrix();
148    G4OpenGLTransform3D oglt (*fpObjectTransformation);
149    glMultMatrixd (oglt.GetGLMatrix ());
150    glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
151  }
152
153  if (fProcessing2D) {
154    // Push current 3D world matrices and load identity to define screen
155    // coordinates...
156    glMatrixMode (GL_PROJECTION);
157    glPushMatrix();
158    glLoadIdentity();
159    glOrtho (-1., 1., -1., 1., -G4OPENGL_FLT_BIG, G4OPENGL_FLT_BIG);
160    glMatrixMode (GL_MODELVIEW);
161    glPushMatrix();
162    glLoadIdentity();
163    G4OpenGLTransform3D oglt (*fpObjectTransformation);
164    glMultMatrixd (oglt.GetGLMatrix ());
165    glColor3d (c.GetRed (), c.GetGreen (), c.GetBlue ());
166  }
167}
168
169void G4OpenGLStoredSceneHandler::AddPrimitivePostamble()
170{
171  if (fProcessing2D) {
172    // Pop current 3D world matrices back again...
173    glMatrixMode (GL_PROJECTION);
174    glPopMatrix();
175    glMatrixMode (GL_MODELVIEW);
176    glPopMatrix();
177  }
178
179  //  if ((glGetError() == GL_TABLE_TOO_LARGE) || (glGetError() == GL_OUT_OF_MEMORY)) {  // Could close?
180  if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
181    G4cout <<
182      "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
183      "  display List for fTopPODL - try OpenGL Immediated mode."
184           << G4endl;
185  }
186  if (fMemoryForDisplayLists) {
187    glEndList();
188    if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
189      G4cout <<
190        "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
191        "  display List for fTopPODL - try OpenGL Immediated mode."
192             << G4endl;
193    }
194  }
195  if (fReadyForTransients || !fMemoryForDisplayLists) {
196    glPopMatrix();
197    glFlush ();
198    glDrawBuffer (GL_BACK);
199  }
200  fAddPrimitivePreambleNestingDepth--;
201}
202
203void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polyline& polyline)
204{
205  AddPrimitivePreamble(polyline);
206  G4OpenGLSceneHandler::AddPrimitive(polyline);
207  AddPrimitivePostamble();
208}
209
210void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polymarker& polymarker)
211{
212  AddPrimitivePreamble(polymarker);
213  G4OpenGLSceneHandler::AddPrimitive(polymarker);
214  AddPrimitivePostamble();
215}
216
217void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Text& text)
218{
219  // Note: colour is still handled in
220  // G4OpenGLSceneHandler::AddPrimitive(const G4Text&), so it still
221  // gets into the display list
222  AddPrimitivePreamble(text);
223  G4OpenGLSceneHandler::AddPrimitive(text);
224  AddPrimitivePostamble();
225}
226
227void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Circle& circle)
228{
229  AddPrimitivePreamble(circle);
230  G4OpenGLSceneHandler::AddPrimitive(circle);
231  AddPrimitivePostamble();
232}
233
234void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Square& square)
235{
236  AddPrimitivePreamble(square);
237  G4OpenGLSceneHandler::AddPrimitive(square);
238  AddPrimitivePostamble();
239}
240
241void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Scale& scale)
242{
243  // Let base class split into primitives.
244  G4OpenGLSceneHandler::AddPrimitive(scale);
245}
246
247void G4OpenGLStoredSceneHandler::AddPrimitive (const G4Polyhedron& polyhedron)
248{
249  // Note: colour is still handled in
250  // G4OpenGLSceneHandler::AddPrimitive(const G4Polyhedron&), so it still
251  // gets into the display list
252  AddPrimitivePreamble(polyhedron);
253  G4OpenGLSceneHandler::AddPrimitive(polyhedron);
254  AddPrimitivePostamble();
255}
256
257void G4OpenGLStoredSceneHandler::AddPrimitive (const G4NURBS& nurbs)
258{
259  // Note: colour is still handled in
260  // G4OpenGLSceneHandler::AddPrimitive(const G4NURBS&), so it still
261  // gets into the display list
262  AddPrimitivePreamble(nurbs);
263  G4OpenGLSceneHandler::AddPrimitive(nurbs);
264  AddPrimitivePostamble();
265}
266
267void G4OpenGLStoredSceneHandler::BeginPrimitives
268(const G4Transform3D& objectTransformation)
269
270  G4OpenGLSceneHandler::BeginPrimitives (objectTransformation);
271
272  // Display list setup moved to AddPrimitivePreamble.  See notes there.
273}
274
275void G4OpenGLStoredSceneHandler::EndPrimitives ()
276{
277  G4OpenGLSceneHandler::EndPrimitives ();
278}
279
280void G4OpenGLStoredSceneHandler::BeginPrimitives2D
281(const G4Transform3D& objectTransformation)
282{
283  G4OpenGLSceneHandler::BeginPrimitives2D(objectTransformation);
284}
285
286void G4OpenGLStoredSceneHandler::EndPrimitives2D ()
287{
288  G4OpenGLSceneHandler::EndPrimitives2D ();
289}
290
291void G4OpenGLStoredSceneHandler::BeginModeling () {
292  G4VSceneHandler::BeginModeling();
293  ClearStore();  // ...and all that goes with it.
294  /* Debug...
295  fDisplayListId = glGenLists (1);
296  G4cout << "OGL::fDisplayListId (start): " << fDisplayListId << G4endl;
297  */
298}
299
300void G4OpenGLStoredSceneHandler::EndModeling () {
301  // Make a List which calls the other lists.
302  fTopPODL = glGenLists (1);
303  if (glGetError() == GL_OUT_OF_MEMORY) {  // Could pre-allocate?
304    G4cout <<
305      "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
306      "  display List for fTopPODL - try OpenGL Immediated mode."
307           << G4endl;
308  } else {
309    glNewList (fTopPODL, GL_COMPILE_AND_EXECUTE); {
310      for (size_t i = 0; i < fPOList.size (); i++) {
311        glPushMatrix();
312        G4OpenGLTransform3D oglt (fPOList[i].fTransform);
313        glMultMatrixd (oglt.GetGLMatrix ());
314        if (fpViewer->GetViewParameters().IsPicking())
315          glLoadName(fPOList[i].fPickName);
316        glCallList (fPOList[i].fDisplayListId);
317        glPopMatrix();
318      }
319    }
320    glEndList ();
321    if (glGetError() == GL_OUT_OF_MEMORY) {  // Could close?
322      G4cout <<
323        "ERROR: G4OpenGLStoredSceneHandler::EndModeling: Failure to allocate"
324        "  display List for fTopPODL - try OpenGL Immediated mode."
325             << G4endl;
326    }
327  }
328
329  G4VSceneHandler::EndModeling ();
330
331  /* Debug...
332  fDisplayListId = glGenLists (1);
333  G4cout << "OGL::fDisplayListId (end): " << fDisplayListId << G4endl;
334  */
335}
336
337void G4OpenGLStoredSceneHandler::ClearStore () {
338
339  G4VSceneHandler::ClearStore ();  // Sets need kernel visit, etc.
340
341  // Delete OpenGL permanent display lists.
342  for (size_t i = 0; i < fPOList.size (); i++)
343    glDeleteLists (fPOList[i].fDisplayListId, 1);
344  if (fTopPODL) glDeleteLists (fTopPODL, 1);
345  fTopPODL = 0;
346
347  // Clear other lists, dictionary, etc.
348  fPOList.clear ();
349  fSolidMap.clear ();
350  ClearAndDestroyAtts();
351
352  // ...and clear transient store...
353  for (size_t i = 0; i < fTOList.size (); i++)
354    glDeleteLists(fTOList[i].fDisplayListId, 1);
355  fTOList.clear ();
356
357  fDisplayListBase = fDisplayListId;
358  fMemoryForDisplayLists = true;
359
360}
361
362void G4OpenGLStoredSceneHandler::ClearTransientStore () {
363
364  G4VSceneHandler::ClearTransientStore ();
365
366  // Delete OpenGL transient display lists and Transient Objects themselves.
367  for (size_t i = 0; i < fTOList.size (); i++)
368    glDeleteLists(fTOList[i].fDisplayListId, 1);
369  fTOList.clear ();
370
371  fDisplayListBase = fDisplayListId;
372  fMemoryForDisplayLists = true;
373
374  // Make sure screen corresponds to graphical database...
375  if (fpViewer) {
376    fpViewer -> SetView ();
377    fpViewer -> ClearView ();
378    fpViewer -> DrawView ();
379  }
380}
381
382void G4OpenGLStoredSceneHandler::RequestPrimitives (const G4VSolid& solid)
383{
384  if (fReadyForTransients) {
385    // Always draw transient solids, e.g., hits represented as solids.
386    // (As we have no control over the order of drawing of transient
387    // objects, we cannot do anything about transparent ones, as
388    // below, so always draw them.)
389    G4VSceneHandler::RequestPrimitives (solid);
390    return;
391  }
392
393  // For non-transient (run-duration) objects, ensure transparent
394  // objects are drawn last.  The problem of
395  // blending/transparency/alpha is quite a tricky one - see History
396  // of opengl-V07-01-01/2/3.
397  // Get vis attributes - pick up defaults if none.
398  const G4VisAttributes* pVA =
399    fpViewer -> GetApplicableVisAttributes(fpVisAttribs);
400  const G4Colour& c = pVA -> GetColour ();
401  G4double opacity = c.GetAlpha ();
402
403  if (!fSecondPass) {
404    G4bool transparency_enabled = true;
405    G4OpenGLViewer* pViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
406    if (pViewer) transparency_enabled = pViewer->transparency_enabled;
407    if (transparency_enabled && opacity < 1.) {
408      // On first pass, transparent objects are not drawn, but flag is set...
409      fSecondPassRequested = true;
410      return;
411    }
412  }
413
414  // On second pass, opaque objects are not drwan...
415  if (fSecondPass && opacity >= 1.) return;
416
417  G4PhysicalVolumeModel* pPVModel =
418    dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
419 
420  if (pPVModel) {
421    // If part of the geometry hierarchy, i.e., from a
422    // G4PhysicalVolumeModel, check if a display list already exists for
423    // this solid, re-use it if possible.  We could be smarter, and
424    // recognise repeated branches of the geometry hierarchy, for
425    // example.  But this algorithm should be secure, I think...
426    const G4VSolid* pSolid = &solid;
427    EAxis axis = kRho;
428    G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
429    if (pCurrentPV -> IsReplicated ()) {
430      G4int nReplicas;
431      G4double width;
432      G4double offset;
433      G4bool consuming;
434      pCurrentPV->GetReplicationData(axis,nReplicas,width,offset,consuming);
435    }
436    // Provided it is not parametrised (because if so, the
437    // solid's parameters might have been changed)...
438    if (!(pCurrentPV -> IsParameterised ()) &&
439        // Provided it is not replicated radially (because if so, the
440        // solid's parameters will have been changed)...
441        !(pCurrentPV -> IsReplicated () && axis == kRho) &&
442        // ...and if the solid has already been rendered...
443        (fSolidMap.find (pSolid) != fSolidMap.end ())) {
444      fDisplayListId = fSolidMap [pSolid];
445      PO po(fDisplayListId,*fpObjectTransformation);
446      if (fpViewer->GetViewParameters().IsPicking()) {
447        G4AttHolder* holder = new G4AttHolder;
448        // Load G4Atts from G4VisAttributes, if any...
449        const G4VisAttributes* va = pPVModel->GetCurrentLV()->GetVisAttributes();
450        if (va) {
451          const std::map<G4String,G4AttDef>* vaDefs = va->GetAttDefs();
452          if (vaDefs) holder->AddAtts(va->CreateAttValues(), vaDefs);
453        }
454        // Load G4Atts from G4PhysicalVolumeModel...
455        const std::map<G4String,G4AttDef>* defs = pPVModel->GetAttDefs();
456        if (defs) holder->AddAtts(pPVModel->CreateCurrentAttValues(), defs);
457        fPickMap[++fPickName] = holder;
458        po.fPickName = fPickName;
459      }
460      fPOList.push_back(po);
461    }
462    else {
463      G4VSceneHandler::RequestPrimitives (solid);
464      fSolidMap [pSolid] = fDisplayListId;
465    }
466    return;
467  }
468
469  // Otherwise invoke base class method...
470  G4VSceneHandler::RequestPrimitives (solid);
471}
472
473G4int G4OpenGLStoredSceneHandler::fSceneIdCount = 0;
474
475G4int  G4OpenGLStoredSceneHandler::fDisplayListId = 0;
476G4bool G4OpenGLStoredSceneHandler::fMemoryForDisplayLists = true;
477G4int  G4OpenGLStoredSceneHandler::fDisplayListLimit = 50000;
478G4int  G4OpenGLStoredSceneHandler::fDisplayListBase = 0;
479
480#endif
Note: See TracBrowser for help on using the repository browser.