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