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;
253 fScaled = kFALSE;
255
256 // Reset bounding box
257 for (UInt_t v=0; v<8; v++) {
258 for (UInt_t i=0; i<3; i++) {
259 fBBVertex[v][i] = 0.0;
260 }
261 }
262 // Set fLocalMaster in section kCore to identity
263
264 // Set kRaw tessellation section of buffer with supplied sizes
265 fPnts = nullptr;
266 fSegs = nullptr;
267 fPols = nullptr;
268
269 fNbPnts = 0;
270 fNbSegs = 0;
271 fNbPols = 0;
272 fPntsCapacity = 0;
273 fSegsCapacity = 0;
274 fPolsCapacity = 0;
275 // Set fLocalMaster in section kCore to identity
276
277 // Wipe output section.
278 fPhysicalID = 0;
279
280 // Set kRaw tessellation section of buffer with supplied sizes
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// Clear any sections marked valid.
286
288{
289 fSections = 0U;
290 SetRawSizes(0, 0, 0, 0, 0, 0);
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// Set kRaw tessellation section of buffer with supplied sizes.
295/// Set fLocalMaster in section kCore to identity
296
298{
299 for (UInt_t i=0; i<16; i++) {
300 if (i%5) {
301 fLocalMaster[i] = 0.0;
302 }
303 else {
304 fLocalMaster[i] = 1.0;
305 }
306 }
307}
308
309////////////////////////////////////////////////////////////////////////////////
310/// Set fBBVertex in kBoundingBox section to a axis aligned (local) BB
311/// using supplied origin and box half lengths.
312///~~~ {.cpp}
313/// 7-------6
314/// /| /|
315/// 3-------2 |
316/// | 4-----|-5
317/// |/ |/
318/// 0-------1
319///~~~
320
321void TBuffer3D::SetAABoundingBox(const Double_t origin[3], const Double_t halfLengths[3])
322{
323 // Vertex 0
324 fBBVertex[0][0] = origin[0] - halfLengths[0]; // x
325 fBBVertex[0][1] = origin[1] - halfLengths[1]; // y
326 fBBVertex[0][2] = origin[2] - halfLengths[2]; // z
327 // Vertex 1
328 fBBVertex[1][0] = origin[0] + halfLengths[0]; // x
329 fBBVertex[1][1] = origin[1] - halfLengths[1]; // y
330 fBBVertex[1][2] = origin[2] - halfLengths[2]; // z
331 // Vertex 2
332 fBBVertex[2][0] = origin[0] + halfLengths[0]; // x
333 fBBVertex[2][1] = origin[1] + halfLengths[1]; // y
334 fBBVertex[2][2] = origin[2] - halfLengths[2]; // z
335 // Vertex 3
336 fBBVertex[3][0] = origin[0] - halfLengths[0]; // x
337 fBBVertex[3][1] = origin[1] + halfLengths[1]; // y
338 fBBVertex[3][2] = origin[2] - halfLengths[2]; // z
339 // Vertex 4
340 fBBVertex[4][0] = origin[0] - halfLengths[0]; // x
341 fBBVertex[4][1] = origin[1] - halfLengths[1]; // y
342 fBBVertex[4][2] = origin[2] + halfLengths[2]; // z
343 // Vertex 5
344 fBBVertex[5][0] = origin[0] + halfLengths[0]; // x
345 fBBVertex[5][1] = origin[1] - halfLengths[1]; // y
346 fBBVertex[5][2] = origin[2] + halfLengths[2]; // z
347 // Vertex 6
348 fBBVertex[6][0] = origin[0] + halfLengths[0]; // x
349 fBBVertex[6][1] = origin[1] + halfLengths[1]; // y
350 fBBVertex[6][2] = origin[2] + halfLengths[2]; // z
351 // Vertex 7
352 fBBVertex[7][0] = origin[0] - halfLengths[0]; // x
353 fBBVertex[7][1] = origin[1] + halfLengths[1]; // y
354 fBBVertex[7][2] = origin[2] + halfLengths[2]; // z
355}
356
357////////////////////////////////////////////////////////////////////////////////
358/// Set kRaw tessellation section of buffer with supplied sizes.
359
361 UInt_t reqSegs, UInt_t reqSegsCapacity,
362 UInt_t reqPols, UInt_t reqPolsCapacity)
363{
364 Bool_t allocateOK = kTRUE;
365
366 fNbPnts = reqPnts;
367 fNbSegs = reqSegs;
368 fNbPols = reqPols;
369
370 if (reqPntsCapacity > fPntsCapacity) {
371 delete [] fPnts;
372 fPnts = new Double_t[reqPntsCapacity];
373 if (fPnts) {
374 fPntsCapacity = reqPntsCapacity;
375 } else {
377 allocateOK = kFALSE;
378 }
379 }
380 if (reqSegsCapacity > fSegsCapacity) {
381 delete [] fSegs;
382 fSegs = new Int_t[reqSegsCapacity];
383 if (fSegs) {
384 fSegsCapacity = reqSegsCapacity;
385 } else {
387 allocateOK = kFALSE;
388 }
389 }
390 if (reqPolsCapacity > fPolsCapacity) {
391 delete [] fPols;
392 fPols = new Int_t[reqPolsCapacity];
393 if (fPols) {
394 fPolsCapacity = reqPolsCapacity;
395 } else {
397 allocateOK = kFALSE;
398 }
399 }
400
401 return allocateOK;
402}
403
404////////////////////////////////////////////////////////////////////////////////
405/// Constructor.
406
408 UInt_t reqSegs, UInt_t reqSegsCapacity,
409 UInt_t reqPols, UInt_t reqPolsCapacity) :
410 TBuffer3D(TBuffer3DTypes::kSphere, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
411 fRadiusInner(0.0), fRadiusOuter(0.0),
412 fThetaMin(0.0), fThetaMax(180.0),
413 fPhiMin(0.0), fPhiMax(360.0)
414{
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// Test if buffer represents a solid uncut sphere.
419
421{
422 if (fRadiusInner != 0.0 ||
423 fThetaMin != 0.0 ||
424 fThetaMax != 180.0 ||
425 fPhiMin != 0.0 ||
426 fPhiMax != 360.0 ) {
427 return kFALSE;
428 } else {
429 return kTRUE;
430 }
431}
432
433////////////////////////////////////////////////////////////////////////////////
434/// Constructor.
435
437 UInt_t reqSegs, UInt_t reqSegsCapacity,
438 UInt_t reqPols, UInt_t reqPolsCapacity) :
439 TBuffer3D(TBuffer3DTypes::kTube, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
440 fRadiusInner(0.0), fRadiusOuter(1.0), fHalfLength(1.0)
441{
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// Constructor.
446
448 UInt_t reqPnts, UInt_t reqPntsCapacity,
449 UInt_t reqSegs, UInt_t reqSegsCapacity,
450 UInt_t reqPols, UInt_t reqPolsCapacity) :
451 TBuffer3D(type, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
452 fRadiusInner(0.0), fRadiusOuter(1.0), fHalfLength(1.0)
453{
454}
455
456////////////////////////////////////////////////////////////////////////////////
457/// Constructor.
458
460 UInt_t reqSegs, UInt_t reqSegsCapacity,
461 UInt_t reqPols, UInt_t reqPolsCapacity) :
462 TBuffer3DTube(TBuffer3DTypes::kTubeSeg, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
463 fPhiMin(0.0), fPhiMax(360.0)
464{
465}
466
467////////////////////////////////////////////////////////////////////////////////
468/// Constructor.
469
471 UInt_t reqPnts, UInt_t reqPntsCapacity,
472 UInt_t reqSegs, UInt_t reqSegsCapacity,
473 UInt_t reqPols, UInt_t reqPolsCapacity) :
474 TBuffer3DTube(type, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity),
475 fPhiMin(0.0), fPhiMax(360.0)
476{
477}
478
479////////////////////////////////////////////////////////////////////////////////
480/// Constructor.
481
483 UInt_t reqSegs, UInt_t reqSegsCapacity,
484 UInt_t reqPols, UInt_t reqPolsCapacity) :
485 TBuffer3DTubeSeg(TBuffer3DTypes::kCutTube, reqPnts, reqPntsCapacity, reqSegs, reqSegsCapacity, reqPols, reqPolsCapacity)
486{
487 fLowPlaneNorm[0] = 0.0; fLowPlaneNorm[0] = 0.0; fLowPlaneNorm[0] = -1.0;
488 fHighPlaneNorm[0] = 0.0; fHighPlaneNorm[0] = 0.0; fHighPlaneNorm[0] = 1.0;
489}
490
491//CS specific
493
494////////////////////////////////////////////////////////////////////////////////
495/// Return CS level.
496
498{
499 return fgCSLevel;
500}
501
502////////////////////////////////////////////////////////////////////////////////
503/// Increment CS level.
504
506{
507 ++fgCSLevel;
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Decrement CS level.
512
514{
515 return --fgCSLevel;
516}
unsigned int UInt_t
Definition RtypesCore.h:46
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Double_t fLowPlaneNorm[3]
Definition TBuffer3D.h:224
Double_t fHighPlaneNorm[3]
Definition TBuffer3D.h:225
TBuffer3DCutTube(const TBuffer3DTubeSeg &)=delete
TBuffer3DSphere(const TBuffer3DSphere &)=delete
Double_t fRadiusInner
Definition TBuffer3D.h:144
Double_t fThetaMin
Definition TBuffer3D.h:146
Double_t fPhiMin
Definition TBuffer3D.h:148
Double_t fThetaMax
Definition TBuffer3D.h:147
Bool_t IsSolidUncut() const
Test if buffer represents a solid uncut sphere.
Double_t fPhiMax
Definition TBuffer3D.h:149
Tube segment description class - see TBuffer3DTypes for producer classes.
Definition TBuffer3D.h:185
TBuffer3DTubeSeg(const TBuffer3DTubeSeg &)
Complete tube description class - see TBuffer3DTypes for producer classes.
Definition TBuffer3D.h:157
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:115
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:93
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:114
void Init()
Initialise buffer.
Bool_t fLocalFrame
Definition TBuffer3D.h:90
Bool_t fScaled
Definition TBuffer3D.h:92
Int_t fColor
Definition TBuffer3D.h:88
static UInt_t fgCSLevel
Definition TBuffer3D.h:39
UInt_t fPhysicalID
Definition TBuffer3D.h:119
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:113
Double_t fBBVertex[8][3]
Definition TBuffer3D.h:108