Logo ROOT   6.14/05
Reference Guide
TGLLogicalShape.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Richard Maunder 25/05/2005
3 
4 #include "TGLLogicalShape.h"
5 #include "TGLPhysicalShape.h"
6 #include "TGLRnrCtx.h"
7 #include "TGLScene.h"
8 #include "TGLCamera.h"
9 #include "TGLSelectRecord.h"
10 #include "TGLContext.h"
11 #include "TGLIncludes.h"
12 
13 #include "TBuffer3D.h"
14 #include "TClass.h"
15 #include "TContextMenu.h"
16 #include "TEnv.h"
17 
18 
19 /** \class TGLLogicalShape
20 \ingroup opengl
21 Abstract logical shape - a GL 'drawable' - base for all shapes -
22 faceset sphere etc. Logical shapes are a unique piece of geometry,
23 described in it's local frame - e.g if we have three spheres in :
24 
25  - Sphere A - Radius r1, center v1
26  - Sphere B - Radius r2, center v2
27  - Sphere C - Radius r1, center v3
28 
29 Spheres A and C can share a common logical sphere of radius r1 - and
30 place them with two physicals with translations of v1 & v2. Sphere B
31 requires a different logical (radius r2), placed with physical with
32 translation v2.
33 
34 Physical shapes know about and can share logicals. Logicals do not
35 about (aside from reference counting) physicals or share them.
36 
37 This sharing of logical shapes greatly reduces memory consumption and
38 scene (re)build times in typical detector geometries which have many
39 repeated objects placements.
40 
41 TGLLogicalShapes have reference counting, performed by the client
42 physical shapes which are using it.
43 
44 Display list information is also stored here, possibly per LOD
45 level. Most classes do not support LOD (only sphere and tube) and
46 therefore reasonable defaults are encoded in the following virtual
47 functions:
48 ~~~ {.cpp}
49  * ELODAxes SupportedLODAxes() { return kLODAxesNone; }
50  * Int_t DLCacheSize() { return 1; }
51  * UInt_t DLOffset(lod); // Transform lod into DL offset.
52  * Short_t QuantizeShapeLOD(); // Quantize lod.
53 ~~~
54 Classes that have per-LOD display-lists than override these functions.
55 'UShort_t fDLValid' is used as a bit-field determining validity of
56 each quantized LOD-level; hopefully one will not have more than 16
57 LOD levels per class.
58 See also: TGLPhysicalShape::CalculateShapeLOD() where LOD is calculated.
59 
60 See base/src/TVirtualViewer3D for description of common external 3D
61 viewer architecture and how external viewer clients use it.
62 */
63 
65 
67 
70 
71 ////////////////////////////////////////////////////////////////////////////////
72 /// Constructor.
73 
75  fRef (0),
76  fFirstPhysical (0),
77  fExternalObj (0),
78  fScene (0),
79  fDLBase (0),
80  fDLSize (1),
81  fDLValid (0),
82  fDLCache (kTRUE),
83  fRefStrong (kFALSE),
84  fOwnExtObj (kFALSE)
85 {
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Constructor with external object.
90 
92  fRef (0),
93  fFirstPhysical (0),
94  fExternalObj (obj),
95  fScene (0),
96  fDLBase (0),
97  fDLSize (1),
98  fDLValid (0),
99  fDLCache (kTRUE),
100  fRefStrong (kFALSE),
102 {
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Constructor from TBuffer3D.
107 
109  fRef (0),
110  fFirstPhysical (0),
111  fExternalObj (buffer.fID),
112  fScene (0),
113  fDLBase (0),
114  fDLSize (1),
115  fDLValid (0),
116  fDLCache (kTRUE),
117  fRefStrong (kFALSE),
119 {
120  // Use the bounding box in buffer if valid
122  fBoundingBox.Set(buffer.fBBVertex);
123  } else if (buffer.SectionsValid(TBuffer3D::kRaw)) {
124  // otherwise use the raw points to generate one
125  fBoundingBox.SetAligned(buffer.NbPnts(), buffer.fPnts);
126  }
127 
128  // If the logical is created without an external object reference,
129  // we create a generic here and delete it during the destruction.
130  if (fExternalObj == 0)
131  {
132  fExternalObj = new TNamed("Generic object", "Internal object created for bookkeeping.");
133  fOwnExtObj = kTRUE;
134  }
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// Destroy logical shape.
139 
141 {
142  // Physicals should have been cleared elsewhere as they are managed
143  // by the scene. But this could change.
144  if (fRef > 0) {
145  Warning("TGLLogicalShape::~TGLLogicalShape", "some physicals still lurking around.");
147  }
148  DLCachePurge();
149  if (fOwnExtObj)
150  {
151  delete fExternalObj;
152  }
153 }
154 
155 
156 /**************************************************************************/
157 // Physical shape ref-counting, replica management
158 /**************************************************************************/
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// Add reference to given physical shape.
162 
164 {
166  fFirstPhysical = phys;
167  ++fRef;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Remove reference to given physical shape, potentially deleting
172 /// *this* object when hitting zero ref-count (if fRefStrong is
173 /// true).
174 
176 {
177  assert(phys != 0);
178 
179  Bool_t found = kFALSE;
180  if (fFirstPhysical == phys) {
182  found = kTRUE;
183  } else {
184  TGLPhysicalShape *shp1 = fFirstPhysical, *shp2;
185  while ((shp2 = shp1->fNextPhysical) != 0) {
186  if (shp2 == phys) {
187  shp1->fNextPhysical = shp2->fNextPhysical;
188  found = kTRUE;
189  break;
190  }
191  shp1 = shp2;
192  }
193  }
194  if (found == kFALSE) {
195  Error("TGLLogicalShape::SubRef", "Attempt to un-ref an unregistered physical.");
196  return;
197  }
198 
199  if (--fRef == 0 && fRefStrong)
200  delete this;
201 }
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 /// Destroy all physicals attached to this logical.
205 
207 {
208  TGLPhysicalShape *curr = fFirstPhysical, *next;
209  while (curr)
210  {
211  next = curr->fNextPhysical;
212  curr->fLogicalShape = 0;
213  --fRef;
214  delete curr;
215  curr = next;
216  }
217  assert (fRef == 0);
218  fFirstPhysical = 0;
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Unreferenced first physical in the list, returning its id and
223 /// making it fit for destruction somewhere else.
224 /// Returns 0 if there are no replicas attached.
225 
227 {
228  if (fFirstPhysical == 0) return 0;
229 
231  UInt_t phid = phys->ID();
233  phys->fLogicalShape = 0;
234  --fRef;
235  return phid;
236 }
237 
238 
239 /**************************************************************************/
240 // Bounding-boxes
241 /**************************************************************************/
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 /// Update bounding-boxed of all dependent physicals.
245 
247 {
249  while (pshp)
250  {
251  pshp->UpdateBoundingBox();
252  pshp = pshp->fNextPhysical;
253  }
254 }
255 
256 
257 /**************************************************************************/
258 // Display-list cache
259 /**************************************************************************/
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Modify capture of draws into display list cache kTRUE - capture,
263 /// kFALSE direct draw. Return kTRUE is state changed, kFALSE if not.
264 
266 {
267  if (cache == fDLCache)
268  return kFALSE;
269 
270  if (fDLCache)
271  DLCachePurge();
272  fDLCache = cache;
273  return kTRUE;
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Returns kTRUE if draws should be display list cached
278 /// kFALSE otherwise.
279 ///
280 /// Here we check that:
281 /// a) fScene is set (Scene manages link to GL-context);
282 /// b) secondary selection is not in progress as different
283 /// render-path is usually taken in this case.
284 ///
285 /// Otherwise we return internal bool.
286 ///
287 /// Override this in sub-class if different behaviour is required.
288 
290 {
291  if (!fDLCache || !fScene ||
292  (rnrCtx.SecSelection() && SupportsSecondarySelect()))
293  {
294  return kFALSE;
295  }
296  return kTRUE;
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Clear all entries for all LODs for this drawable from the
301 /// display list cache but keeping the reserved ids from GL context.
302 
304 {
305  fDLValid = 0;
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Drop all entries for all LODs for this drawable from the display
310 /// list cache, WITHOUT returning the reserved ids to GL context.
311 ///
312 /// This is called by scene if it realized that the GL context was
313 /// destroyed.
314 
316 {
317  fDLBase = 0;
318  fDLValid = 0;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Purge all entries for all LODs for this drawable from the
323 /// display list cache, returning the reserved ids to GL context.
324 ///
325 /// If you override this function:
326 /// 1. call the base-class version from it;
327 /// 2. call it from the destructor of the derived class!
328 
330 {
331  if (fDLBase != 0)
332  {
334  fDLBase = 0;
335  fDLValid = 0;
336  }
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Purge given display-list range.
341 /// Utility function.
342 
344 {
345  if (fScene)
346  {
348  }
349  else
350  {
351  Warning("TGLLogicalShape::PurgeDLRange", "Scene unknown, attempting direct deletion.");
352  glDeleteLists(base, size);
353  }
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Logical shapes usually support only discreet LOD values,
358 /// especially in view of display-list caching.
359 /// This function should be overriden to perform the desired quantization.
360 /// See TGLSphere.
361 
363  Short_t /*combiLOD*/) const
364 {
365  return shapeLOD;
366 }
367 
368 ////////////////////////////////////////////////////////////////////////////////
369 /// Draw the GL drawable, using draw flags. If DL caching is enabled
370 /// (see SetDLCache) then attempt to draw from the cache, if not found
371 /// attempt to capture the draw - done by DirectDraw() - into a new cache entry.
372 /// If not cached just call DirectDraw() for normal non DL cached drawing.
373 
374 void TGLLogicalShape::Draw(TGLRnrCtx& rnrCtx) const
375 {
376  // Debug tracing
377  if (gDebug > 4) {
378  Info("TGLLogicalShape::Draw", "this %ld (class %s) LOD %d", (Long_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
379  }
380 
381 entry_point:
382  // If shape is not cached, or a capture to cache is already in
383  // progress perform a direct draw DL can be nested, but not created
384  // in nested fashion. As we only build DL on draw demands have to
385  // protected against this here.
386  // MT: I can't see how this could happen right now ... with
387  // rendering from a flat drawable-list.
388 
389  if (!fgUseDLs || !ShouldDLCache(rnrCtx) || rnrCtx.IsDLCaptureOpen())
390  {
391  DirectDraw(rnrCtx);
392  return;
393  }
394 
395  if (fDLBase == 0)
396  {
397  fDLBase = glGenLists(fDLSize);
398  if (fDLBase == 0)
399  {
400  Warning("TGLLogicalShape::Draw", "display-list registration failed.");
401  fDLCache = kFALSE;
402  goto entry_point;
403  }
404  }
405 
406  Short_t lod = rnrCtx.ShapeLOD();
407  UInt_t off = DLOffset(lod);
408  if ((1<<off) & fDLValid)
409  {
410  glCallList(fDLBase + off);
411  }
412  else
413  {
414  rnrCtx.OpenDLCapture();
415  glNewList(fDLBase + off, GL_COMPILE_AND_EXECUTE);
416  DirectDraw(rnrCtx);
417  glEndList();
418  rnrCtx.CloseDLCapture();
419  fDLValid |= (1<<off);
420  }
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Draw the logical shape in highlight mode.
425 /// If lvl argument is less than 0 (-1 by default), the index into color-set
426 /// is taken from the physical shape itself.
427 
428 void TGLLogicalShape::DrawHighlight(TGLRnrCtx& rnrCtx, const TGLPhysicalShape* pshp, Int_t lvl) const
429 {
430  if (lvl < 0) lvl = pshp->GetSelected();
431 
432  glColor4ubv(rnrCtx.ColorSet().Selection(lvl).CArr());
434  Draw(rnrCtx);
436 }
437 
438 ////////////////////////////////////////////////////////////////////////////////
439 /// Virtual method called-back after a secondary selection hit
440 /// is recorded (see TGLViewer::HandleButton(), Ctrl-Button1).
441 /// The ptr argument holds the GL pick-record of the closest hit.
442 ///
443 /// This base-class implementation simply prints out the result.
444 
446 {
447  printf("TGLLogicalShape::ProcessSelection %d names on the stack (z1=%g, z2=%g).\n",
448  rec.GetN(), rec.GetMinZ(), rec.GetMaxZ());
449  printf(" Names: ");
450  for (Int_t j=0; j<rec.GetN(); ++j) printf ("%u ", rec.GetItem(j));
451  printf("\n");
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Invoke popup menu or our bound external TObject (if any), using passed
456 /// 'menu' object, at location 'x' 'y'
457 
459 {
460  if (fExternalObj) {
461  menu.Popup(x, y, fExternalObj);
462  }
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Return true if size of this shape should be ignored when determining if
467 /// the object should be drawn. In this base-class we simply return state of
468 /// static flag fgIgnoreSizeForCameraInterest.
469 ///
470 /// Several sub-classes override this virtual function.
471 
473 {
475 }
476 
477 ////////////////////////////////////////////////////////////////////////////////
478 /// Get state of static fgIgnoreSizeForCameraInterest flag.
479 /// When this is true all objects, also very small, will be drawn by GL.
480 
482 {
484 }
485 
486 ////////////////////////////////////////////////////////////////////////////////
487 /// Set state of static fgIgnoreSizeForCameraInterest flag.
488 
490 {
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 // Load GL shape settings from ROOT's TEnv into static data members.
496 
498 {
499  fgUseDLs = gEnv->GetValue("OpenGL.UseDisplayLists", 1);
500  fgUseDLsForVertArrs = gEnv->GetValue("OpenGL.UseDisplayListsForVertexArrays", 1);
501 
502  if (!fgUseDLs || !fgUseDLsForVertArrs)
503  {
504  printf("TGLLogicalShape::SetEnvDefaults() fgUseDLs=%d, fgUseDLsForVertArrs=%d\n",
506  }
507 }
void SetAligned(const TGLVertex3 &lowVertex, const TGLVertex3 &highVertex)
Set ALIGNED box from two low/high vertices.
virtual void DLCacheDrop()
Drop all entries for all LODs for this drawable from the display list cache, WITHOUT returning the re...
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition: TGLRnrCtx.h:40
Bool_t SecSelection() const
Definition: TGLRnrCtx.h:224
virtual void ProcessSelection(TGLRnrCtx &rnrCtx, TGLSelectRecord &rec)
Virtual method called-back after a secondary selection hit is recorded (see TGLViewer::HandleButton()...
virtual Short_t QuantizeShapeLOD(Short_t shapeLOD, Short_t combiLOD) const
Logical shapes usually support only discreet LOD values, especially in view of display-list caching...
void Set(const TGLVertex3 vertex[8])
Set a bounding box from provided 8 vertices.
UInt_t fDLBase
scene where object is stored (can be zero!)
Double_t fBBVertex[8][3]
Definition: TBuffer3D.h:107
void UpdateBoundingBoxesOfPhysicals()
Update bounding-boxed of all dependent physicals.
Int_t fDLSize
display-list id base
UShort_t fDLValid
display-list size for different LODs
UInt_t NbPnts() const
Definition: TBuffer3D.h:80
static void SetEnvDefaults()
void DestroyPhysicals()
Destroy all physicals attached to this logical.
void UpdateBoundingBox()
cache
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void AddRef(TGLPhysicalShape *phys) const
Add reference to given physical shape.
static Bool_t GetIgnoreSizeForCameraInterest()
Get state of static fgIgnoreSizeForCameraInterest flag.
virtual Bool_t SupportsSecondarySelect() const
UChar_t GetSelected() const
const TGLLogicalShape * fLogicalShape
Concrete physical shape - a GL drawable.
TGLScene * fScene
Shape&#39;s bounding box.
Double_t x[n]
Definition: legend1.C:17
void SubRef(TGLPhysicalShape *phys) const
Remove reference to given physical shape, potentially deleting this object when hitting zero ref-coun...
static Bool_t fgUseDLs
Bool_t IsDLCaptureOpen() const
Definition: TGLRnrCtx.h:250
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual UInt_t DLOffset(Short_t) const
const UChar_t * CArr() const
Definition: TGLUtil.h:799
static void SetIgnoreSizeForCameraInterest(Bool_t isfci)
Set state of static fgIgnoreSizeForCameraInterest flag.
Double_t * fPnts
Definition: TBuffer3D.h:112
void Info(const char *location, const char *msgfmt,...)
virtual void Popup(Int_t x, Int_t y, TObject *obj, TVirtualPad *c=0, TVirtualPad *p=0)
Popup context menu at given location in canvas c and pad p for selected object.
Float_t GetMaxZ() const
virtual ~TGLLogicalShape()
Destroy logical shape.
static UInt_t LockColor()
Prevent further color changes.
Definition: TGLUtil.cxx:1630
static UInt_t UnlockColor()
Allow color changes.
Definition: TGLUtil.cxx:1638
void Error(const char *location, const char *msgfmt,...)
virtual void DLCachePurge()
Purge all entries for all LODs for this drawable from the display list cache, returning the reserved ...
Short_t ShapeLOD() const
Definition: TGLRnrCtx.h:177
TObject * fExternalObj
first replica
void CloseDLCapture()
End display list capture.
Definition: TGLRnrCtx.cxx:347
static Bool_t fgUseDLsForVertArrs
global flag for usage of display-lists
Bool_t SectionsValid(UInt_t mask) const
Definition: TBuffer3D.h:67
virtual void DrawHighlight(TGLRnrCtx &rnrCtx, const TGLPhysicalShape *pshp, Int_t lvl=-1) const
Draw the logical shape in highlight mode.
TGLPhysicalShape * fFirstPhysical
physical instance ref counting
TGLPhysicalShape * fNextPhysical
the associated logical shape
Standard selection record including information about containing scene and details ob out selected ob...
This class provides an interface to context sensitive popup menus.
Definition: TContextMenu.h:40
UInt_t UnrefFirstPhysical()
Unreferenced first physical in the list, returning its id and making it fit for destruction somewhere...
unsigned int UInt_t
Definition: RtypesCore.h:42
TGLContextIdentity * GetGLCtxIdentity() const
Definition: TGLScene.h:232
short Short_t
Definition: RtypesCore.h:35
Generic 3D primitive description class.
Definition: TBuffer3D.h:17
Bool_t SetDLCache(Bool_t cached)
Modify capture of draws into display list cache kTRUE - capture, kFALSE direct draw.
void Warning(const char *location, const char *msgfmt,...)
TGLLogicalShape()
global flag for usage of display-lists in shapes that use vertex arrays
virtual void DirectDraw(TGLRnrCtx &rnrCtx) const =0
Abstract logical shape - a GL &#39;drawable&#39; - base for all shapes - faceset sphere etc.
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
Bool_t fOwnExtObj
Strong ref (delete on 0 ref); not in scene.
void OpenDLCapture()
Start display-list capture.
Definition: TGLRnrCtx.cxx:338
UInt_t ID() const
#define ClassImp(name)
Definition: Rtypes.h:359
Bool_t fRefStrong
use display list caching
UInt_t GetItem(Int_t i) const
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
Double_t y[n]
Definition: legend1.C:17
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Draw(TGLRnrCtx &rnrCtx) const
Draw the GL drawable, using draw flags.
void InvokeContextMenu(TContextMenu &menu, UInt_t x, UInt_t y) const
Invoke popup menu or our bound external TObject (if any), using passed &#39;menu&#39; object, at location &#39;x&#39; &#39;y&#39;.
TGLColor & Selection(Int_t i)
Definition: TGLUtil.h:853
Float_t GetMinZ() const
Int_t GetN() const
void PurgeDLRange(UInt_t base, Int_t size) const
External object is a fake.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
TGLBoundingBox fBoundingBox
Also plays the role of ID.
virtual Bool_t IgnoreSizeForOfInterest() const
Return true if size of this shape should be ignored when determining if the object should be drawn...
Bool_t fDLCache
display-list validity bit-field
virtual Bool_t ShouldDLCache(const TGLRnrCtx &rnrCtx) const
Returns kTRUE if draws should be display list cached kFALSE otherwise.
TGLColorSet & ColorSet()
Return reference to current color-set (top of the stack).
Definition: TGLRnrCtx.cxx:278
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
void RegisterDLNameRangeToWipe(UInt_t base, Int_t size)
Remember dl range for deletion in next MakeCurrent or dtor execution.
Definition: TGLContext.cxx:514
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual void DLCacheClear()
Clear all entries for all LODs for this drawable from the display list cache but keeping the reserved...
static Bool_t fgIgnoreSizeForCameraInterest