Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLScenePad.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Matevz Tadel, Jun 2007
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 "TGLScenePad.h"
13
14#include "TGLViewer.h"
15#include "TGLLogicalShape.h"
16#include "TGLPhysicalShape.h"
17#include "TGLObject.h"
18#include "TGLStopwatch.h"
19#include "TBuffer3D.h"
20#include "TBuffer3DTypes.h"
21#include "TPolyMarker3D.h"
22#include "TColor.h"
23#include "TROOT.h"
24#include "TH3.h"
25
26#include "TGLFaceSet.h"
27#include "TGLPolyLine.h"
28#include "TGLPolyMarker.h"
29#include "TGLCylinder.h"
30#include "TGLSphere.h"
31
32#include "TVirtualPad.h"
33#include "TAtt3D.h"
34#include "TClass.h"
35#include "TList.h"
36#include "TMath.h"
37
38#include "TGLPlot3D.h"
39
40
41/** \class TGLScenePad
42\ingroup opengl
43Implements VirtualViewer3D interface and fills the base-class
44visualization structures from pad contents.
45*/
46
48
49////////////////////////////////////////////////////////////////////////////////
50
53 TGLScene(),
54
55 fPad (pad),
56 fInternalPIDs (kFALSE),
57 fNextInternalPID (1), // 0 reserved
58 fLastPID (0), // 0 reserved
59 fAcceptedPhysicals (0),
60 fComposite (nullptr),
61 fCSLevel (0),
62 fSmartRefresh (kFALSE)
63{
64 // Constructor.
65}
66
67
68/******************************************************************************/
69// Histo import and Sub-pad traversal
70/******************************************************************************/
71
72////////////////////////////////////////////////////////////////////////////////
73/// Scale and rotate a histo object to mimic placement in canvas.
74
76{
77 Double_t how = ((Double_t) gPad->GetWh()) / gPad->GetWw();
78
79 Double_t lw = gPad->GetAbsWNDC();
80 Double_t lh = gPad->GetAbsHNDC() * how;
81 Double_t lm = TMath::Min(lw, lh);
82
83 const TGLBoundingBox& bb = log->BoundingBox();
84
85 // Timur always packs histos in a square: let's just take x-diff.
86 Double_t size = TMath::Sqrt(3) * (bb.XMax() - bb.XMin());
87 Double_t scale = lm / size;
88 TGLVector3 scaleVec(scale, scale, scale);
89
90 Double_t tx = gPad->GetAbsXlowNDC() + lw;
91 Double_t ty = gPad->GetAbsYlowNDC() * how + lh;
92 TGLVector3 transVec(0, ty, tx); // For viewer convention (starts looking along -x).
93
94 // XXXX plots no longer centered at 0. Or they never were?
95 // Impossible to translate and scale them as they should be, it
96 // seems. This requires further investigation, eventually.
97 //
98 // bb.Dump();
99 // printf("lm=%f, size=%f, scale=%f, tx=%f, ty=%f\n",
100 // lm, size, scale, tx, ty);
101 //
102 // TGLVector3 c(bb.Center().Arr());
103 // c.Negate();
104 // c.Dump();
105 // mat.Translate(c);
106
107 TGLMatrix mat;
108 mat.Scale(scaleVec);
109 mat.Translate(transVec);
110 mat.RotateLF(3, 2, TMath::PiOver2());
111 mat.RotateLF(1, 3, TMath::DegToRad()*gPad->GetTheta());
112 mat.RotateLF(1, 2, TMath::DegToRad()*(gPad->GetPhi() - 90));
113 Float_t rgba[4] = {1.f, 1.f, 1.f, 1.f};
114 if (histoColor) {
115 rgba[0] = histoColor[0];
116 rgba[1] = histoColor[1];
117 rgba[2] = histoColor[2];
118 rgba[3] = histoColor[3];
119 }
120 TGLPhysicalShape* phys = new TGLPhysicalShape(fNextInternalPID++, *log, mat, false, rgba);
121 AdoptPhysical(*phys);
122
123 // Part of XXXX above.
124 // phys->BoundingBox().Dump();
125}
126
127namespace {
128
129////////////////////////////////////////////////////////////////////////////////
130///TTree::Draw can create polymarker + empty TH3 (to draw as a frame around marker).
131///Unfortunately, this is not good for GL - this will be two unrelated
132///objects in two unrelated coordinate systems.
133///So, this function checks list contents, and if it founds empty TH3 and polymarker,
134///the must be combined as one object.
135///Later we'll reconsider the design.
136
137Bool_t HasPolymarkerAndFrame(const TList *lst)
138{
139 Bool_t gotEmptyTH3 = kFALSE;
140 Bool_t gotMarker = kFALSE;
141
142 TObjOptLink *lnk = lst ? (TObjOptLink*)lst->FirstLink() : nullptr;
143 for (; lnk; lnk = (TObjOptLink*)lnk->Next()) {
144 const TObject *obj = lnk->GetObject();
145 if (const TH3 *th3 = dynamic_cast<const TH3*>(obj)) {
146 if(!th3->GetEntries())
147 gotEmptyTH3 = kTRUE;
148 } else if (dynamic_cast<const TPolyMarker3D *>(obj))
149 gotMarker = kTRUE;
150 }
151
152 return gotMarker && gotEmptyTH3;
153}
154
155}
156
157
158
159////////////////////////////////////////////////////////////////////////////////
160/// Iterate over pad-primitives and import them.
161
163{
164 TVirtualPad *padsav = gPad;
165 TVirtualViewer3D *vv3dsav = pad->GetViewer3D();
166 gPad = pad;
167 pad->SetViewer3D(this);
168
169 TList *prims = pad->GetListOfPrimitives();
170
171 if (HasPolymarkerAndFrame(prims)) {
172 ComposePolymarker(prims);
173 } else {
174 TObjOptLink *lnk = (prims) ? (TObjOptLink*)prims->FirstLink() : nullptr;
175 for (; lnk; lnk = (TObjOptLink*)lnk->Next())
176 ObjectPaint(lnk->GetObject(), lnk->GetOption());
177 }
178
179 pad->SetViewer3D(vv3dsav);
180 gPad = padsav;
181}
182
183
184////////////////////////////////////////////////////////////////////////////////
185/// Override of virtual TVirtualViewer3D::ObjectPaint().
186/// Special handling of 2D/3D histograms to activate Timur's
187/// histo-painters.
188
190{
191 TGLPlot3D* log = TGLPlot3D::CreatePlot(obj, opt, gPad);
192 if (log)
193 {
194 AdoptLogical(*log);
195 AddHistoPhysical(log);
196 }
197 else if (obj->InheritsFrom(TAtt3D::Class()))
198 {
199 // Handle 3D primitives here.
200 obj->Paint(opt);
201 }
202 else if (obj->InheritsFrom(TVirtualPad::Class()))
203 {
204 SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
205 }
206 else
207 {
208 // Handle 2D primitives here.
209 obj->Paint(opt);
210 }
211}
212
213////////////////////////////////////////////////////////////////////////////////
214/// Entry point for requesting update of scene's contents from
215/// gl-viewer.
216
218{
220 fSmartRefresh = viewer->GetSmartRefresh();
221
222 PadPaint(fPad);
223
224 fSmartRefresh = sr;
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Entry point for updating scene contents via VirtualViewer3D
229/// interface.
230/// For now this is handled by TGLViewer as it remains
231/// the 'Viewer3D' of given pad.
232
234{
235 if (pad != fPad)
236 {
237 Error("TGLScenePad::PadPaint", "Mismatch between pad argument and data-member!");
238 return;
239 }
240
241 BeginScene();
243 EndScene();
244}
245
246
247//==============================================================================
248// VV3D
249//==============================================================================
250
251////////////////////////////////////////////////////////////////////////////////
252/// Start building of the scene.
253/// Old contents is dropped, unless smart-refresh is in active. Then
254/// the object supporting it are kept in a cache and possibly reused.
255///
256/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
257/// for description of viewer architecture.
258
260{
261 if (gDebug>2) {
262 Info("TGLScenePad::BeginScene", "entering.");
263 }
264
265 if ( ! BeginUpdate()) {
266 Error("TGLScenePad::BeginScene", "could not take scene lock.");
267 return;
268 }
269
270 UInt_t destroyedLogicals = 0;
271 UInt_t destroyedPhysicals = 0;
272
273 TGLStopwatch stopwatch;
274 if (gDebug > 2) {
275 stopwatch.Start();
276 }
277
278 // Rebuilds can potentially invalidate all logical and
279 // physical shapes.
280 // Physicals must be removed first.
281 destroyedPhysicals = DestroyPhysicals();
282 if (fSmartRefresh) {
283 destroyedLogicals = BeginSmartRefresh();
284 } else {
285 destroyedLogicals = DestroyLogicals();
286 }
287
288 // Potentially using external physical IDs
290
291 // Reset internal physical ID counter
293 fLastPID = 0;
294
295 // Reset tracing info
297
298 if (gDebug > 2) {
299 Info("TGLScenePad::BeginScene", "destroyed %d physicals %d logicals in %f msec",
300 destroyedPhysicals, destroyedLogicals, stopwatch.End());
301 DumpMapSizes();
302 }
303}
304
305////////////////////////////////////////////////////////////////////////////////
306/// End building of the scene.
307/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
308/// for description of viewer architecture
309
311{
312 if (fSmartRefresh) {
314 }
315
316 EndUpdate();
317
318 if (gDebug > 2) {
319 Info("TGLScenePad::EndScene", "Accepted %d physicals", fAcceptedPhysicals);
320 DumpMapSizes();
321 }
322}
323
324////////////////////////////////////////////////////////////////////////////////
325/// Add an object to the viewer, using internal physical IDs
326/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
327/// for description of viewer architecture
328
329Int_t TGLScenePad::AddObject(const TBuffer3D& buffer, Bool_t* addChildren)
330{
331 // If this is called we are generating internal physical IDs
333 Int_t sections = AddObject(fNextInternalPID, buffer, addChildren);
334 return sections;
335}
336
337////////////////////////////////////////////////////////////////////////////////
338/// Add an object to the scene, using an external physical ID
339/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
340/// for description of viewer architecture
341
342Int_t TGLScenePad::AddObject(UInt_t physicalID, const TBuffer3D& buffer, Bool_t* addChildren)
343{
344 // TODO: Break this up and make easier to understand. This is
345 // pretty convoluted due to the large number of cases it has to
346 // deal with:
347 // i) existing physical and/or logical;
348 // ii) external provider may or may not supply bounding box;
349 // iii) local/global reference frame;
350 // iv) deferred filling of some sections of the buffer;
351 // v) internal or external physical IDs;
352 // vi) composite components as special case.
353 //
354 // The buffer filling means the function is re-entrant which adds
355 // to complication.
356
357 if (physicalID == 0) {
358 Error("TGLScenePad::AddObject", "0 physical ID reserved");
359 return TBuffer3D::kNone;
360 }
361
362 // Internal and external physical IDs cannot be mixed in a scene build
363 if (fInternalPIDs && physicalID != fNextInternalPID) {
364 Error("TGLScenePad::AddObject", "invalid next physical ID - mix of internal + external IDs?");
365 return TBuffer3D::kNone;
366 }
367
368 // We always take all children ... interest is viewer dependent.
369 if (addChildren)
370 *addChildren = kTRUE;
371
372 // Scene should be modify locked
373 if (CurrentLock() != kModifyLock) {
374 Error("TGLScenePad::AddObject", "expected scene to be modify-locked.");
375 return TBuffer3D::kNone;
376 }
377
378 // Note that 'object' here is really a physical/logical pair described
379 // in buffer + physical ID.
380
381 // If adding component to a current partial composite do this now
382 if (fComposite) {
383 RootCsg::TBaseMesh *newMesh = RootCsg::ConvertToMesh(buffer);
384 // Solaris CC can't create stl pair with enumerate type
385 fCSTokens.push_back(std::make_pair(static_cast<UInt_t>(TBuffer3D::kCSNoOp), newMesh));
386 return TBuffer3D::kNone;
387 }
388
389 // TODO: Could be a data member - save possible double lookup?
390 TGLPhysicalShape *physical = FindPhysical(physicalID);
391 TGLLogicalShape *logical = nullptr;
392
393 // If we have a valid (non-zero) ID, see if the logical is already cached.
394 // If it is not, try to create a direct renderer object.
395 if (buffer.fID)
396 {
397 logical = FindLogical(buffer.fID);
398 if (!logical)
399 logical = AttemptDirectRenderer(buffer.fID);
400 }
401
402 // First attempt to add this physical.
403 if (physicalID != fLastPID)
404 {
405 // Existing physical.
406 // MT comment: I don't think this should ever happen.
407 if (physical)
408 {
409 // If we have physical we should have logical cached, too.
410 if (!logical) {
411 Error("TGLScenePad::AddObject", "cached physical with no associated cached logical");
412 }
413
414 // Since we already have logical no need for further checks.
415 // Done ... prepare for next object.
416 if (fInternalPIDs)
418
419 return TBuffer3D::kNone;
420 }
421
422 // Need any extra sections in buffer?
423 Bool_t includeRaw = (logical == nullptr);
424 Int_t extraSections = ValidateObjectBuffer(buffer, includeRaw);
425 if (extraSections != TBuffer3D::kNone)
426 return extraSections;
427
428 fLastPID = physicalID;
429 }
430
431 if (fLastPID != physicalID) {
432 Error("TGLScenePad::AddObject", "internal physical ID tracking error?");
433 }
434
435 // Being here means we need to add a physical, maybe logical as well.
436 if (physical) {
437 Error("TGLScenePad::AddObject", "expecting to require physical");
438 return TBuffer3D::kNone;
439 }
440
441 // Create logical if required.
442 if (!logical)
443 {
444 logical = CreateNewLogical(buffer);
445 if (!logical) {
446 Error("TGLScenePad::AddObject", "failed to create logical");
447 return TBuffer3D::kNone;
448 }
449 // Add logical to scene
450 AdoptLogical(*logical);
451 }
452
453 // Create the physical, bind it to the logical and add it to the scene.
454 physical = CreateNewPhysical(physicalID, buffer, *logical);
455
456 if (physical)
457 {
458 AdoptPhysical(*physical);
459 buffer.fPhysicalID = physicalID;
461 if (gDebug>3 && fAcceptedPhysicals%1000 == 0) {
462 Info("TGLScenePad::AddObject", "added %d physicals", fAcceptedPhysicals);
463 }
464 }
465 else
466 {
467 Error("TGLScenePad::AddObject", "failed to create physical");
468 }
469
470 // Done ... prepare for next object.
471 if (fInternalPIDs)
473
474 return TBuffer3D::kNone;
475}
476
477////////////////////////////////////////////////////////////////////////////////
478/// Open new composite container.
479/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
480/// for description of viewer architecture.
481
483{
484 if (fComposite) {
485 Error("TGLScenePad::OpenComposite", "composite already open");
486 return kFALSE;
487 }
488 UInt_t extraSections = AddObject(buffer, addChildren);
489 if (extraSections != TBuffer3D::kNone) {
490 Error("TGLScenePad::OpenComposite", "expected top level composite to not require extra buffer sections");
491 }
492
493 // If composite was created it is of interest - we want the rest of the
494 // child components
495 if (fComposite) {
496 return kTRUE;
497 } else {
498 return kFALSE;
499 }
500}
501
502////////////////////////////////////////////////////////////////////////////////
503/// Close composite container
504/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
505/// for description of viewer architecture
506
508{
509 // If we have a partially complete composite build it now
510 if (fComposite) {
511 // TODO: Why is this member and here - only used in BuildComposite()
512 fCSLevel = 0;
513
514 RootCsg::TBaseMesh *resultMesh = BuildComposite();
515 fComposite->SetFromMesh(resultMesh);
516 delete resultMesh;
517 for (UInt_t i = 0; i < fCSTokens.size(); ++i) delete fCSTokens[i].second;
518 fCSTokens.clear();
519 fComposite = nullptr;
520 }
521}
522
523////////////////////////////////////////////////////////////////////////////////
524/// Add composite operation used to combine objects added via AddObject
525/// TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
526/// for description of viewer architecture
527
529{
530 fCSTokens.push_back(std::make_pair(operation, (RootCsg::TBaseMesh *)nullptr));
531}
532
533
534// Protected methods
535
536////////////////////////////////////////////////////////////////////////////////
537/// Validate if the passed 'buffer' contains all sections we require to add object.
538/// Returns Int_t combination of TBuffer::ESection flags still required - or
539/// TBuffer3D::kNone if buffer is valid.
540/// If 'includeRaw' is kTRUE check for kRaw/kRawSizes - skip otherwise.
541/// See base/src/TVirtualViewer3D.cxx for description of viewer architecture
542
544{
545 // kCore: Should always be filled
546 if (!buffer.SectionsValid(TBuffer3D::kCore)) {
547 Error("TGLScenePad::ValidateObjectBuffer", "kCore section of buffer should be filled always");
548 return TBuffer3D::kNone;
549 }
550
551 // Need to check raw (kRaw/kRawSizes)?
552 if (!includeRaw) {
553 return TBuffer3D::kNone;
554 }
555
556 // kRawSizes / kRaw: These are on demand based on shape type
557 Bool_t needRaw = kFALSE;
558
559 // We need raw tesselation in these cases:
560 //
561 // 1. Shape type is NOT kSphere / kTube / kTubeSeg / kCutTube / kComposite
562 if (buffer.Type() != TBuffer3DTypes::kSphere &&
563 buffer.Type() != TBuffer3DTypes::kTube &&
564 buffer.Type() != TBuffer3DTypes::kTubeSeg &&
565 buffer.Type() != TBuffer3DTypes::kCutTube &&
567 {
568 needRaw = kTRUE;
569 }
570 // 2. Sphere type is kSPHE, but the sphere is hollow and/or cut - we
571 // do not support native drawing of these currently
572 else if (buffer.Type() == TBuffer3DTypes::kSphere)
573 {
574 const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
575 if (sphereBuffer) {
576 if (!sphereBuffer->IsSolidUncut()) {
577 needRaw = kTRUE;
578 }
579 } else {
580 Error("TGLScenePad::ValidateObjectBuffer", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
581 return TBuffer3D::kNone;
582 }
583 }
584 // 3. kBoundingBox is not filled - we generate a bounding box from
585 else if (!buffer.SectionsValid(TBuffer3D::kBoundingBox))
586 {
587 needRaw = kTRUE;
588 }
589 // 4. kShapeSpecific is not filled - except in case of top level composite
590 else if (!buffer.SectionsValid(TBuffer3D::kShapeSpecific) &&
592 {
593 needRaw = kTRUE;
594 }
595 // 5. We are a component (not the top level) of a composite shape
596 else if (fComposite)
597 {
598 needRaw = kTRUE;
599 }
600 // 6. The shape is scaled
601 else if (buffer.fScaled)
602 {
603 needRaw = kTRUE;
604 }
605
606 if (needRaw && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
608 } else {
609 return TBuffer3D::kNone;
610 }
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Create and return a new TGLLogicalShape from the supplied buffer
615
617{
618 TGLLogicalShape * newLogical = nullptr;
619
620 if (buffer.fColor == 1) // black -> light-brown; std behaviour for geom
621 const_cast<TBuffer3D&>(buffer).fColor = 42;
622
623 switch (buffer.Type())
624 {
626 newLogical = new TGLPolyLine(buffer);
627 break;
629 newLogical = new TGLPolyMarker(buffer);
630 break;
632 {
633 const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
634 if (sphereBuffer)
635 {
636 // We can only draw solid uncut spheres natively at present.
637 // If somebody already passed the raw buffer, they probably want us to use it.
638 if (sphereBuffer->IsSolidUncut() && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw))
639 {
640 newLogical = new TGLSphere(*sphereBuffer);
641 } else {
642 newLogical = new TGLFaceSet(buffer);
643 }
644 } else {
645 Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
646 }
647 break;
648 }
652 {
653 const TBuffer3DTube * tubeBuffer = dynamic_cast<const TBuffer3DTube *>(&buffer);
654 if (tubeBuffer)
655 {
656 // If somebody already passed the raw buffer, they probably want us to use it.
658 newLogical = new TGLCylinder(*tubeBuffer);
659 } else {
660 newLogical = new TGLFaceSet(buffer);
661 }
662 } else {
663 Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kTube/kTubeSeg/kCutTube' to TBuffer3DTube");
664 }
665 break;
666 }
668 {
669 // Create empty faceset and record partial complete composite object
670 // Will be populated with mesh in CloseComposite()
671 if (fComposite)
672 {
673 Error("TGLScenePad::CreateNewLogical", "composite already open");
674 }
675 fComposite = new TGLFaceSet(buffer);
676 newLogical = fComposite;
677 break;
678 }
679 default:
680 newLogical = new TGLFaceSet(buffer);
681 break;
682 }
683
684 return newLogical;
685}
686
687////////////////////////////////////////////////////////////////////////////////
688/// Create and return a new TGLPhysicalShape with id 'ID', using
689/// 'buffer' placement information (translation etc), and bound to
690/// suppled 'logical'
691
694 const TGLLogicalShape& logical) const
695{
696 // Extract indexed color from buffer
697 // TODO: Still required? Better use proper color triplet in buffer?
698 Int_t colorIndex = buffer.fColor;
699 if (colorIndex < 0) colorIndex = 42;
700 Float_t rgba[4];
701 TGLScene::RGBAFromColorIdx(rgba, colorIndex, buffer.fTransparency);
702 return new TGLPhysicalShape(ID, logical, buffer.fLocalMaster,
703 buffer.fReflection, rgba);
704}
705
706
707////////////////////////////////////////////////////////////////////////////////
708
710{
711 TPolyMarker3D *pm = nullptr;
712 TH3 *th3 = nullptr;
713 TObjOptLink *lnk = (TObjOptLink*)lst->FirstLink();
714 for (; lnk; lnk = (TObjOptLink*)lnk->Next()) {
715 TObject *obj = lnk->GetObject();
716 if (TPolyMarker3D *dPm = dynamic_cast<TPolyMarker3D*>(obj)) {
717 if(!pm)
718 pm = dPm;
719 } else if (TH3 *dTH3 = dynamic_cast<TH3*>(obj)) {
720 if(!th3 && !dTH3->GetEntries())
721 th3 = dTH3;
722 } else
723 ObjectPaint(obj, lnk->GetOption());
724
725 if (pm && th3) {
726 //Create a new TH3 plot, containing polymarker.
728 AdoptLogical(*log);
729 //Try to extract polymarker's color and
730 //create a physical shape with correct color.
731 const Color_t cInd = pm->GetMarkerColor();
732 if (TColor *c = gROOT->GetColor(cInd)) {
733 Float_t rgba[4] = {0.f, 0.f, 0.f, 1.};
734 c->GetRGB(rgba[0], rgba[1], rgba[2]);
735 AddHistoPhysical(log, rgba);
736 } else
737 AddHistoPhysical(log);
738
739 //Composition was added into gl-viewer.
740 pm = nullptr;
741 th3 = nullptr;
742 }
743 }
744}
745
746////////////////////////////////////////////////////////////////////////////////
747/// Build and return composite shape mesh
748
749RootCsg::TBaseMesh* TGLScenePad::BuildComposite()
750{
751 const CSPart_t &currToken = fCSTokens[fCSLevel];
752 UInt_t opCode = currToken.first;
753
754 if (opCode != TBuffer3D::kCSNoOp) {
755 ++fCSLevel;
756 RootCsg::TBaseMesh *left = BuildComposite();
757 RootCsg::TBaseMesh *right = BuildComposite();
758 //RootCsg::TBaseMesh *result = 0;
759 switch (opCode) {
761 return RootCsg::BuildUnion(left, right);
763 return RootCsg::BuildIntersection(left, right);
765 return RootCsg::BuildDifference(left, right);
766 default:
767 Error("BuildComposite", "Wrong operation code %d\n", opCode);
768 return nullptr;
769 }
770 } else return fCSTokens[fCSLevel++].second;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// Try to construct an appropriate logical-shape sub-class based
775/// on id'class, following convention that SomeClassGL is a suitable
776/// renderer for class SomeClass.
777
779{
780 TClass* cls = TGLObject::GetGLRenderer(id->IsA());
781 if (cls == nullptr)
782 return nullptr;
783
784 TGLObject* rnr = reinterpret_cast<TGLObject*>(cls->New());
785 if (rnr) {
786 Bool_t status;
787 try
788 {
789 status = rnr->SetModel(id);
790 }
791 catch (std::exception&)
792 {
793 status = kFALSE;
794 }
795 if (!status)
796 {
797 Warning("TGLScenePad::AttemptDirectRenderer", "failed initializing direct rendering.");
798 delete rnr;
799 return nullptr;
800 }
801 rnr->SetBBox();
802 AdoptLogical(*rnr);
803 }
804 return rnr;
805}
#define c(i)
Definition RSha256.hxx:101
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
short Color_t
Definition RtypesCore.h:92
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Int_t gDebug
Definition TROOT.cxx:595
#define gROOT
Definition TROOT.h:406
#define gPad
static TClass * Class()
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
Sphere description class - see TBuffer3DTypes for producer classes Supports hollow and cut spheres.
Definition TBuffer3D.h:130
Bool_t IsSolidUncut() const
Test if buffer represents a solid uncut sphere.
Complete tube description class - see TBuffer3DTypes for producer classes.
Definition TBuffer3D.h:157
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t Type() const
Definition TBuffer3D.h:85
Bool_t SectionsValid(UInt_t mask) const
Definition TBuffer3D.h:67
@ kBoundingBox
Definition TBuffer3D.h:51
@ kShapeSpecific
Definition TBuffer3D.h:52
@ kCSDifference
Definition TBuffer3D.h:43
@ kCSIntersection
Definition TBuffer3D.h:43
Double_t fLocalMaster[16]
Definition TBuffer3D.h:93
Bool_t fScaled
Definition TBuffer3D.h:92
Int_t fColor
Definition TBuffer3D.h:88
UInt_t fPhysicalID
Definition TBuffer3D.h:119
Short_t fTransparency
Definition TBuffer3D.h:89
Bool_t fReflection
Definition TBuffer3D.h:91
TObject * fID
Definition TBuffer3D.h:87
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
The color creation and management class.
Definition TColor.h:21
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1839
Concrete class describing an orientated (free) or axis aligned box of 8 vertices.
Double_t XMin() const
Double_t XMax() const
Implements a native ROOT-GL cylinder that can be rendered at different levels of detail.
Definition TGLCylinder.h:22
Implements a native ROOT-GL representation of an arbitrary set of polygons.
Definition TGLFaceSet.h:23
void SetFromMesh(const RootCsg::TBaseMesh *m)
Should only be done on an empty faceset object.
ELock CurrentLock() const
Definition TGLLockable.h:61
Abstract logical shape - a GL 'drawable' - base for all shapes - faceset sphere etc.
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition TGLUtil.h:598
void Scale(const TGLVector3 &scale)
Set matrix axis scales to 'scale'.
Definition TGLUtil.cxx:834
void RotateLF(Int_t i1, Int_t i2, Double_t amount)
Rotate in local frame.
Definition TGLUtil.cxx:897
void Translate(const TGLVector3 &vect)
Shift matrix translation components by 'vect' in parent frame.
Definition TGLUtil.cxx:802
Base-class for direct OpenGL renderers.
Definition TGLObject.h:22
virtual void SetBBox()=0
virtual Bool_t SetModel(TObject *obj, const Option_t *opt=nullptr)=0
static TClass * GetGLRenderer(TClass *isa)
Return direct-rendering GL class for class isa.
Concrete physical shape - a GL drawable.
Description of TGLPlot3D.
Definition TGLPlot3D.h:23
static TGLPlot3D * CreatePlot(TH3 *h, TPolyMarker3D *pm)
Create GL plot for specified TH3 and polymarker.
Definition TGLPlot3D.cxx:87
To draw a 3D polyline in a GL window.
Definition TGLPolyLine.h:24
To draw a 3D polymarker in a GL window.
Implements VirtualViewer3D interface and fills the base-class visualization structures from pad conte...
Definition TGLScenePad.h:26
TGLLogicalShape * CreateNewLogical(const TBuffer3D &buffer) const
Create and return a new TGLLogicalShape from the supplied buffer.
Bool_t fSmartRefresh
Definition TGLScenePad.h:56
std::vector< CSPart_t > fCSTokens
Definition TGLScenePad.h:51
RootCsg::TBaseMesh * BuildComposite()
Build and return composite shape mesh.
void EndScene() override
End building of the scene.
void CloseComposite() override
Close composite container TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D....
Bool_t OpenComposite(const TBuffer3D &buffer, Bool_t *addChildren=nullptr) override
Open new composite container.
Int_t AddObject(const TBuffer3D &buffer, Bool_t *addChildren=nullptr) override
Add an object to the viewer, using internal physical IDs TVirtualViewer3D interface overload - see ba...
void PadPaint(TVirtualPad *pad) override
Entry point for updating scene contents via VirtualViewer3D interface.
Bool_t fInternalPIDs
Definition TGLScenePad.h:36
TGLPhysicalShape * CreateNewPhysical(UInt_t physicalID, const TBuffer3D &buffer, const TGLLogicalShape &logical) const
Create and return a new TGLPhysicalShape with id 'ID', using 'buffer' placement information (translat...
void BeginScene() override
Start building of the scene.
TGLLogicalShape * AttemptDirectRenderer(TObject *id)
Try to construct an appropriate logical-shape sub-class based on id'class, following convention that ...
virtual void PadPaintFromViewer(TGLViewer *viewer)
Entry point for requesting update of scene's contents from gl-viewer.
void SubPadPaint(TVirtualPad *pad)
Iterate over pad-primitives and import them.
UInt_t fLastPID
next internal physical ID (from 1 - 0 reserved)
Definition TGLScenePad.h:38
Int_t ValidateObjectBuffer(const TBuffer3D &buffer, Bool_t includeRaw) const
Validate if the passed 'buffer' contains all sections we require to add object.
Int_t fAcceptedPhysicals
last physical ID that was processed in AddObject()
Definition TGLScenePad.h:39
void ComposePolymarker(const TList *padPrimitives)
void ObjectPaint(TObject *obj, Option_t *opt="") override
Override of virtual TVirtualViewer3D::ObjectPaint().
void AddCompositeOp(UInt_t operation) override
Add composite operation used to combine objects added via AddObject TVirtualViewer3D interface overlo...
TVirtualPad * fPad
Definition TGLScenePad.h:33
TGLFaceSet * fComposite
Definition TGLScenePad.h:49
UInt_t fCSLevel
Paritally created composite.
Definition TGLScenePad.h:50
void AddHistoPhysical(TGLLogicalShape *log, const Float_t *histColor=nullptr)
Scale and rotate a histo object to mimic placement in canvas.
TGLScenePad(const TGLScenePad &)=delete
std::pair< UInt_t, RootCsg::TBaseMesh * > CSPart_t
Definition TGLScenePad.h:48
UInt_t fNextInternalPID
using internal physical IDs
Definition TGLScenePad.h:37
TGLScene provides management and rendering of ROOT's default 3D /object representation as logical and...
Definition TGLScene.h:29
virtual TGLPhysicalShape * FindPhysical(UInt_t phid) const
Find and return physical shape identified by unique 'ID'.
virtual Bool_t BeginUpdate()
Put scene in update mode, return true if lock acquired.
virtual void AdoptPhysical(TGLPhysicalShape &shape)
Adopt dynamically created physical 'shape' - add to internal map and take responsibility for deleting...
virtual void EndUpdate(Bool_t minorChange=kTRUE, Bool_t sceneChanged=kTRUE, Bool_t updateViewers=kTRUE)
Exit scene update mode.
virtual Int_t DestroyPhysicals()
Destroy physical shapes.
virtual void AdoptLogical(TGLLogicalShape &shape)
Adopt dynamically created logical 'shape' - add to internal map and take responsibility for deleting.
void EndSmartRefresh()
Wipes logicals in refresh-cache.
static void RGBAFromColorIdx(Float_t rgba[4], Color_t ci, Char_t transp=0)
Fill rgba color from ROOT color-index ci and transparency (0->100).
virtual Int_t DestroyLogicals()
Destroy all logical shapes in scene.
void DumpMapSizes() const
Print sizes of logical and physical-shape maps.
TGLLogicalShape * FindLogical(TObject *logid) const override
Find and return logical shape identified by unique logid.
UInt_t BeginSmartRefresh()
Moves logicals that support smart-refresh to intermediate cache.
Implements a native ROOT-GL sphere that can be rendered at different levels of detail.
Definition TGLSphere.h:22
Stopwatch object for timing GL work.
void Start()
Start timing.
Double_t End()
End timing, return total time since Start(), in milliseconds.
3 component (x/y/z) vector class.
Definition TGLUtil.h:248
Base GL viewer object - used by both standalone and embedded (in pad) GL.
Definition TGLViewer.h:55
Bool_t GetSmartRefresh() const
Definition TGLViewer.h:229
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
A doubly linked list.
Definition TList.h:38
virtual TObjLink * FirstLink() const
Definition TList.h:102
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:962
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:607
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:950
A 3D polymarker.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual TList * GetListOfPrimitives() const =0
virtual TVirtualViewer3D * GetViewer3D(Option_t *type="")=0
virtual void SetViewer3D(TVirtualViewer3D *)
static TClass * Class()
Abstract 3D shapes viewer.
constexpr Double_t PiOver2()
Definition TMath.h:51
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:79
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:662
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
auto * th3
Definition textalign.C:22