Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TBuffer3D.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id: TBuffer3D.cxx,v 1.00
2// Author: Olivier Couet 05/05/04
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TBuffer3D.h"
13#include "TBuffer3DTypes.h"
14
15/** \class TBuffer3D
16\ingroup Base
17
18Generic 3D primitive description class.
19See TBuffer3DTypes for producer classes.
20
21### Filling TBuffer3D and Adding to Viewer
22
23The viewers behind the TVirtualViewer3D interface differ greatly in their
24capabilities e.g.
25
26 - Some know how to draw certain shapes natively (e.g. spheres/tubes in OpenGL)
27 - others always require a raw tessellation description of points/lines/segments.
28 - Some need the 3D object positions in the global frame, others can cope with
29 local frames + a translation matrix - which can give considerable performance
30 benefits.
31
32To cope with these situations the object buffer is filled out in negotiation
33with the viewer. TBuffer3D classes are conceptually divided into enumerated
34sections Core, BoundingBox, Raw etc (see TBuffer3D.h for more details).
35
36\image html base_tbuffer3d.png
37
38The `SectionsValid() / SetSectionsValid / ClearSectionsValid()` methods of
39TBuffer3D are used to test/set/clear these section valid flags.
40
41The sections found in TBuffer3D (`Core/BoundingBox/Raw Sizes/Raw`) are sufficient
42to describe any tessellated shape in a generic fashion. An additional
43`ShapeSpecific` section in derived shape specific classes allows a more abstract
44shape description ("a sphere of inner radius x, outer radius y"). This
45enables a viewer which knows how to draw (tessellate) the shape itself to do so,
46which can bring considerable performance and quality benefits, while providing a
47generic fallback suitable for all viewers.
48
49The rules for client negotiation with the viewer are:
50
51 - If suitable specialized TBuffer3D class exists, use it, otherwise use TBuffer3D.
52 - Complete the mandatory Core section.
53 - Complete the ShapeSpecific section if applicable.
54 - Complete the BoundingBox if you can.
55 - Pass this buffer to the viewer using one of the AddObject() methods - see below.
56
57If the viewer requires more sections to be completed (Raw/RawSizes) AddObject()
58will return flags indicating which ones, otherwise it returns kNone. You must
59fill the buffer and mark these sections valid, and pass the buffer again. A
60typical code snippet would be:
61
62~~~ {.cpp}
63TBuffer3DSphere sphereBuffer;
64// Fill out kCore...
65// Fill out kBoundingBox...
66// Fill out kShapeSpecific for TBuffer3DSphere
67// Try first add to viewer
68Int_t reqSections = viewer->AddObject(buffer);
69if (reqSections != TBuffer3D::kNone) {
70 if (reqSections & TBuffer3D::kRawSizes) {
71 // Fill out kRawSizes...
72 }
73 if (reqSections & TBuffer3D::kRaw) {
74 // Fill out kRaw...
75 }
76 // Add second time to viewer - ignore return cannot do more
77 viewer->AddObject(buffer);
78 }
79}
80~~~
81
82`ShapeSpecific`: If the viewer can directly display the buffer without
83filling of the kRaw/kRawSizes section it will not need to request client side
84tessellation.
85
86Currently we provide the following various shape specific classes, which the
87OpenGL viewer can take advantage of (see TBuffer3D.h and TBuffer3DTypes.h)
88
89 - TBuffer3DSphere - solid, hollow and cut spheres*
90 - TBuffer3DTubeSeg - angle tube segment
91 - TBuffer3DCutTube - angle tube segment with plane cut ends.
92
93
94*OpenGL only supports solid spheres at present - cut/hollow ones will be
95requested tessellated.
96
97Anyone is free to add new TBuffer3D classes, but it should be clear that the
98viewers require updating to be able to take advantage of them. The number of
99native shapes in OpenGL will be expanded over time.
100
101`BoundingBox:` You are not obliged to complete this, as any viewer
102requiring one internally (OpenGL) will build one for you if you do not provide.
103However to do this the viewer will force you to provide the raw tessellation, and the
104resulting box will be axis aligned with the overall scene, which is non-ideal
105for rotated shapes.
106
107As we need to support orientated (rotated) bounding boxes, TBuffer3D requires
108the 6 vertices of the box. We also provide a convenience function, SetAABoundingBox(),
109for simpler case of setting an axis aligned bounding box.
110
111### Master/Local Reference Frames
112
113The `Core` section of TBuffer3D contains two members relating to reference
114frames:
115`fLocalFrame` & `fLocalMaster`. `fLocalFrame` indicates if any positions in the
116buffer (bounding box and tessellation vertexes) are in local or master (world frame).
117`fLocalMaster` is a standard 4x4 translation matrix (OpenGL column major ordering)
118for placing the object into the 3D master frame.
119
120If `fLocalFrame` is kFALSE, `fLocalMaster` should contain an identity matrix. This
121is set by default, and can be reset using `SetLocalMasterIdentity()` function.
122
123Logical & Physical Objects.
124There are two cases of object addition:
125
126 - Add this object as a single independent entity in the world reference frame.
127 - Add a physical placement (copy) of this logical object (described in local
128 reference frame).
129
130The second case is very typical in geometry packages, GEANT4, where we have
131very large number repeated placements of relatively few logical (unique) shapes.
132Some viewers (OpenGL only at present) are able to take advantage of this by
133identifying unique logical shapes from the `fID` logical ID member of
134TBuffer3D. If repeated addition of the same `fID` is found, the shape
135is cached already - and the costly tessellation does not need to be sent again.
136The viewer can also perform internal GL specific caching with considerable
137performance gains in these cases.
138
139For this to work correctly the logical object in must be described in TBuffer3D
140in the local reference frame, complete with the local/master translation. The
141viewer indicates this through the interface method
142
143~~~ {.cpp}
144PreferLocalFrame()
145~~~
146
147If this returns kTRUE you can make repeated calls to AddObject(), with TBuffer3D
148containing the same fID, and different `fLocalMaster` placements.
149
150For viewers supporting logical/physical objects, the TBuffer3D content refers
151to the properties of logical object, with the `fLocalMaster` transform and the
152`fColor` and `fTransparency` attributes, which can be varied for each physical
153object.
154
155As a minimum requirement all clients must be capable of filling the raw tessellation
156of the object buffer, in the master reference frame. Conversely viewers must
157always be capable of displaying the object described by this buffer.
158
159### Scene Rebuilds
160
161It should be understood that AddObject is not an explicit command to the viewer
162 - it may for various reasons decide to ignore it:
163
164 - It already has the object internally cached .
165 - The object falls outside some 'interest' limits of the viewer camera.
166 - The object is too small to be worth drawing.
167
168In all these cases AddObject() returns kNone, as it does for successful addition,
169simply indicating it does not require you to provide further information about
170this object. You should not try to make any assumptions about what the viewer
171did with it.
172
173This enables the viewer to be connected to a client which sends potentially
174millions of objects, and only accept those that are of interest at a certain
175time, caching the relatively small number of CPU/memory costly logical shapes,
176and retaining/discarding the physical placements as required. The viewer may
177decide to force the client to rebuild (republish) the scene (via
178a TPad repaint at present), and thus collect these objects if the
179internal viewer state changes. It does this presently by forcing a repaint
180on the attached TPad object - hence the reason for putting all publishing to
181the viewer in the attached pad objects Paint() method. We will likely remove
182this requirement in the future, indicating the rebuild request via a normal
183ROOT signal, which the client can detect.
184
185### Physical IDs
186
187TVirtualViewer3D provides for two methods of object addition:virtual Int_t AddObject(const
188TBuffer3D & buffer, Bool_t * addChildren = 0)
189
190~~~ {.cpp}
191virtual Int_t AddObject(UInt_t physicalID, const TBuffer3D & buffer, Bool_t * addChildren = 0)
192~~~
193
194If you use the first (simple) case a viewer using logical/physical pairs
195SetSectionsValid(TBuffer3D::kBoundingBox); will generate IDs for each physical
196object internally. In the second you can specify a unique identifier from the
197client, which allows the viewer to be more efficient. It can now cache both logical
198and physical objects, and only discard physical objects no longer of interest as
199part of scene rebuilds.
200
201### Child Objects
202
203In many geometries there is a rigid containment hierarchy, and so if the viewer
204is not interested in a certain object due to limits/size then it will also
205not be interest in any of the contained branch of descendents. Both AddObject()
206methods have an addChildren parameter. The viewer will complete this (if passed)
207indicating if children (contained within the one just sent) are worth adding.
208
209### Recycling TBuffer3D
210
211Once add AddObject() has been called, the contents are copied to the viewer
212internally. You are free to destroy this object, or recycle it for the next
213object if suitable.
214*/
215
217
218////////////////////////////////////////////////////////////////////////////////
219/// Destructor.
220/// Construct from supplied shape type and raw sizes
221
223 UInt_t reqPnts, UInt_t reqPntsCapacity,
224 UInt_t reqSegs, UInt_t reqSegsCapacity,
225 UInt_t reqPols, UInt_t reqPolsCapacity) :
226 fType(type)
227{
228 Init();
229 SetRawSizes(reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity);
230}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Destructor.
234
236{
237 if (fPnts) delete [] fPnts;
238 if (fSegs) delete [] fSegs;
239 if (fPols) delete [] fPols;
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// Initialise buffer.
244
246{
247 fID = nullptr;
248 fColor = 0;
249 // Set fLocalMaster in section kCore to identity
250 fTransparency = 0;
254
255 // Reset bounding box
256 for (UInt_t v=0; v<8; v++) {
257 for (UInt_t i=0; i<3; i++) {
258 fBBVertex[v][i] = 0.0;
259 }
260 }
261 // Set fLocalMaster in section kCore to identity
262
263 // Set kRaw tessellation section of buffer with supplied sizes
264 fPnts = nullptr;
265 fSegs = nullptr;
266 fPols = nullptr;
267
268 fNbPnts = 0;
269 fNbSegs = 0;
270 fNbPols = 0;
271 fPntsCapacity = 0;
272 fSegsCapacity = 0;
273 fPolsCapacity = 0;
274 // Set fLocalMaster in section kCore to identity
275
276 // Wipe output section.
277 fPhysicalID = 0;
278
279 // Set kRaw tessellation section of buffer with supplied sizes
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// Clear any sections marked valid.
285
287{
288 fSections = 0U;
289 SetRawSizes(0, 0, 0, 0, 0, 0);
290}
291
292////////////////////////////////////////////////////////////////////////////////
293/// Set kRaw tessellation section of buffer with supplied sizes.
294/// Set fLocalMaster in section kCore to identity
295
297{
298 for (UInt_t i=0; i<16; i++) {
299 if (i%5) {
300 fLocalMaster[i] = 0.0;
301 }
302 else {
303 fLocalMaster[i] = 1.0;
304 }
305 }
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Set fBBVertex in kBoundingBox section to a axis aligned (local) BB
310/// using supplied origin and box half lengths.
311///~~~ {.cpp}
312/// 7-------6
313/// /| /|
314/// 3-------2 |
315/// | 4-----|-5
316/// |/ |/
317/// 0-------1
318///~~~
319
320void TBuffer3D::SetAABoundingBox(const Double_t origin[3], const Double_t halfLengths[3])
321{
322 // Vertex 0
323 fBBVertex[0][0] = origin[0] - halfLengths[0]; // x
324 fBBVertex[0][1] = origin[1] - halfLengths[1]; // y
325 fBBVertex[0][2] = origin[2] - halfLengths[2]; // z
326 // Vertex 1
327 fBBVertex[1][0] = origin[0] + halfLengths[0]; // x
328 fBBVertex[1][1] = origin[1] - halfLengths[1]; // y
329 fBBVertex[1][2] = origin[2] - halfLengths[2]; // z
330 // Vertex 2
331 fBBVertex[2][0] = origin[0] + halfLengths[0]; // x
332 fBBVertex[2][1] = origin[1] + halfLengths[1]; // y
333 fBBVertex[2][2] = origin[2] - halfLengths[2]; // z
334 // Vertex 3
335 fBBVertex[3][0] = origin[0] - halfLengths[0]; // x
336 fBBVertex[3][1] = origin[1] + halfLengths[1]; // y
337 fBBVertex[3][2] = origin[2] - halfLengths[2]; // z
338 // Vertex 4
339 fBBVertex[4][0] = origin[0] - halfLengths[0]; // x
340 fBBVertex[4][1] = origin[1] - halfLengths[1]; // y
341 fBBVertex[4][2] = origin[2] + halfLengths[2]; // z
342 // Vertex 5
343 fBBVertex[5][0] = origin[0] + halfLengths[0]; // x
344 fBBVertex[5][1] = origin[1] - halfLengths[1]; // y
345 fBBVertex[5][2] = origin[2] + halfLengths[2]; // z
346 // Vertex 6
347 fBBVertex[6][0] = origin[0] + halfLengths[0]; // x
348 fBBVertex[6][1] = origin[1] + halfLengths[1]; // y
349 fBBVertex[6][2] = origin[2] + halfLengths[2]; // z
350 // Vertex 7
351 fBBVertex[7][0] = origin[0] - halfLengths[0]; // x
352 fBBVertex[7][1] = origin[1] + halfLengths[1]; // y
353 fBBVertex[7][2] = origin[2] + halfLengths[2]; // z
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Set kRaw tessellation section of buffer with supplied sizes.
358
360 UInt_t reqSegs, UInt_t reqSegsCapacity,
361 UInt_t reqPols, UInt_t reqPolsCapacity)
362{
363 Bool_t allocateOK = kTRUE;
364
365 fNbPnts = reqPnts;
366 fNbSegs = reqSegs;
367 fNbPols = reqPols;
368
369 if (reqPntsCapacity > fPntsCapacity) {
370 delete [] fPnts;
371 fPnts = new Double_t[reqPntsCapacity];
372 if (fPnts) {
373 fPntsCapacity = reqPntsCapacity;
374 } else {
376 allocateOK = kFALSE;
377 }
378 }
379 if (reqSegsCapacity > fSegsCapacity) {
380 delete [] fSegs;
381 fSegs = new Int_t[reqSegsCapacity];
382 if (fSegs) {
383 fSegsCapacity = reqSegsCapacity;
384 } else {
386 allocateOK = kFALSE;
387 }
388 }
389 if (reqPolsCapacity > fPolsCapacity) {
390 delete [] fPols;
391 fPols = new Int_t[reqPolsCapacity];
392 if (fPols) {
393 fPolsCapacity = reqPolsCapacity;
394 } else {
396 allocateOK = kFALSE;
397 }
398 }
399
400 return allocateOK;
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Constructor.
405
407 UInt_t reqSegs, UInt_t reqSegsCapacity,
408 UInt_t reqPols, UInt_t reqPolsCapacity) :
409 TBuffer3D(TBuffer3DTypes::kSphere, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
410 fRadiusInner(0.0), fRadiusOuter(0.0),
411 fThetaMin(0.0), fThetaMax(180.0),
412 fPhiMin(0.0), fPhiMax(360.0)
413{
414}
415
416////////////////////////////////////////////////////////////////////////////////
417/// Test if buffer represents a solid uncut sphere.
418
420{
421 if (fRadiusInner != 0.0 ||
422 fThetaMin != 0.0 ||
423 fThetaMax != 180.0 ||
424 fPhiMin != 0.0 ||
425 fPhiMax != 360.0 ) {
426 return kFALSE;
427 } else {
428 return kTRUE;
429 }
430}
431
432////////////////////////////////////////////////////////////////////////////////
433/// Constructor.
434
436 UInt_t reqSegs, UInt_t reqSegsCapacity,
437 UInt_t reqPols, UInt_t reqPolsCapacity) :
438 TBuffer3D(TBuffer3DTypes::kTube, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
439 fRadiusInner(0.0), fRadiusOuter(1.0), fHalfLength(1.0)
440{
441}
442
443////////////////////////////////////////////////////////////////////////////////
444/// Constructor.
445
447 UInt_t reqPnts, UInt_t reqPntsCapacity,
448 UInt_t reqSegs, UInt_t reqSegsCapacity,
449 UInt_t reqPols, UInt_t reqPolsCapacity) :
450 TBuffer3D(type, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
451 fRadiusInner(0.0), fRadiusOuter(1.0), fHalfLength(1.0)
452{
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Constructor.
457
459 UInt_t reqSegs, UInt_t reqSegsCapacity,
460 UInt_t reqPols, UInt_t reqPolsCapacity) :
461 TBuffer3DTube(TBuffer3DTypes::kTubeSeg, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
462 fPhiMin(0.0), fPhiMax(360.0)
463{
464}
465
466////////////////////////////////////////////////////////////////////////////////
467/// Constructor.
468
470 UInt_t reqPnts, UInt_t reqPntsCapacity,
471 UInt_t reqSegs, UInt_t reqSegsCapacity,
472 UInt_t reqPols, UInt_t reqPolsCapacity) :
473 TBuffer3DTube(type, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
474 fPhiMin(0.0), fPhiMax(360.0)
475{
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Constructor.
480
482 UInt_t reqSegs, UInt_t reqSegsCapacity,
483 UInt_t reqPols, UInt_t reqPolsCapacity) :
484 TBuffer3DTubeSeg(TBuffer3DTypes::kCutTube, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity)
485{
486 fLowPlaneNorm[0] = 0.0; fLowPlaneNorm[0] = 0.0; fLowPlaneNorm[0] = -1.0;
487 fHighPlaneNorm[0] = 0.0; fHighPlaneNorm[0] = 0.0; fHighPlaneNorm[0] = 1.0;
488}
489
490//CS specific
492
493////////////////////////////////////////////////////////////////////////////////
494/// Return CS level.
495
497{
498 return fgCSLevel;
499}
500
501////////////////////////////////////////////////////////////////////////////////
502/// Increment CS level.
503
505{
506 ++fgCSLevel;
507}
508
509////////////////////////////////////////////////////////////////////////////////
510/// Decrement CS level.
511
513{
514 return --fgCSLevel;
515}
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
const Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:364
int type
Definition TGX11.cxx:121
Double_t fLowPlaneNorm[3]
Definition TBuffer3D.h:223
Double_t fHighPlaneNorm[3]
Definition TBuffer3D.h:224
TBuffer3DCutTube(const TBuffer3DTubeSeg &)=delete
TBuffer3DSphere(const TBuffer3DSphere &)=delete
Double_t fRadiusInner
Definition TBuffer3D.h:143
Double_t fThetaMin
Definition TBuffer3D.h:145
Double_t fPhiMin
Definition TBuffer3D.h:147
Double_t fThetaMax
Definition TBuffer3D.h:146
Bool_t IsSolidUncut() const
Test if buffer represents a solid uncut sphere.
Double_t fPhiMax
Definition TBuffer3D.h:148
Tube segment description class - see TBuffer3DTypes for producer classes.
Definition TBuffer3D.h:184
TBuffer3DTubeSeg(const TBuffer3DTubeSeg &)
Complete tube description class - see TBuffer3DTypes for producer classes.
Definition TBuffer3D.h:156
TBuffer3DTube(const TBuffer3DTube &)=delete
Generic 3D primitive description class.
Definition TBuffer3D.h:18
void SetLocalMasterIdentity()
Set kRaw tessellation section of buffer with supplied sizes.
Int_t * fPols
Definition TBuffer3D.h:114
UInt_t fPntsCapacity
Definition TBuffer3D.h:26
UInt_t fNbPols
Definition TBuffer3D.h:24
UInt_t fNbPnts
Definition TBuffer3D.h:22
Double_t fLocalMaster[16]
Definition TBuffer3D.h:92
static UInt_t DecCSLevel()
Decrement CS level.
static UInt_t GetCSLevel()
Return CS level.
void ClearSectionsValid()
Clear any sections marked valid.
UInt_t fPolsCapacity
Definition TBuffer3D.h:28
Int_t * fSegs
Definition TBuffer3D.h:113
void Init()
Initialise buffer.
Bool_t fLocalFrame
Definition TBuffer3D.h:90
Int_t fColor
Definition TBuffer3D.h:88
static UInt_t fgCSLevel
Definition TBuffer3D.h:39
UInt_t fPhysicalID
Definition TBuffer3D.h:118
static void IncCSLevel()
Increment CS level.
UInt_t fSections
Definition TBuffer3D.h:30
UInt_t fSegsCapacity
Definition TBuffer3D.h:27
Short_t fTransparency
Definition TBuffer3D.h:89
void SetAABoundingBox(const Double_t origin[3], const Double_t halfLengths[3])
Set fBBVertex in kBoundingBox section to a axis aligned (local) BB using supplied origin and box half...
Bool_t fReflection
Definition TBuffer3D.h:91
TObject * fID
Definition TBuffer3D.h:87
TBuffer3D(const TBuffer3D &)=delete
UInt_t fNbSegs
Definition TBuffer3D.h:23
virtual ~TBuffer3D()
Destructor.
Bool_t SetRawSizes(UInt_t reqPnts, UInt_t reqPntsCapacity, UInt_t reqSegs, UInt_t reqSegsCapacity, UInt_t reqPols, UInt_t reqPolsCapacity)
Set kRaw tessellation section of buffer with supplied sizes.
Double_t * fPnts
Definition TBuffer3D.h:112
Double_t fBBVertex[8][3]
Definition TBuffer3D.h:107