Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLViewerBase.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Matevz Tadel, Feb 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 "TGLViewerBase.h"
13
14#include "TGLSceneBase.h"
15#include "TGLSceneInfo.h"
16
17#include "TGLRnrCtx.h"
18#include "TGLCamera.h"
19#include "TGLClip.h"
20#include "TGLOverlay.h"
21#include "TGLSelectBuffer.h"
22#include "TGLSelectRecord.h"
23#include "TGLAnnotation.h"
24#include "TGLUtil.h"
25
26#include "TGLContext.h"
27#include "TGLIncludes.h"
28
29#include "TEnv.h"
30
31#include <algorithm>
32#include <stdexcept>
33
34/** \class TGLViewerBase
35\ingroup opengl
36Base class for GL viewers. Provides a basic scene management and a
37small set of control variables (camera, LOD, style, clip) that are
38used by the scene classes. Renering wrappers are available but
39minimal.
40
41There is no concept of GL-context here ... we just draw
42into whatever is set from outside.
43
44Development notes:
45
46Each viewer automatically creates a TGLRnrCtx and passes it down
47all render functions.
48*/
49
50
51////////////////////////////////////////////////////////////////////////////////
52
54 fRnrCtx (nullptr),
55 fCamera (nullptr),
56 fClip (nullptr),
57 fLOD (TGLRnrCtx::kLODHigh),
58 fStyle (TGLRnrCtx::kFill),
59 fWFLineW (1),
60 fOLLineW (1),
61
62 fResetSceneInfosOnRender (kFALSE),
63 fChanged (kFALSE)
64{
65 // Constructor.
66
67 fRnrCtx = new TGLRnrCtx(this);
68
69 fWFLineW = gEnv->GetValue("OpenGL.WireframeLineScalingFactor", 1.0);
70 fOLLineW = gEnv->GetValue("OpenGL.OutlineLineScalingFactor", 1.0);
71}
72
73////////////////////////////////////////////////////////////////////////////////
74/// Destructor.
75
77{
78 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
79 {
80 (*i)->GetScene()->RemoveViewer(this);
81 delete *i;
82 }
83
85
86 delete fRnrCtx;
87}
88
89////////////////////////////////////////////////////////////////////////////////
90/// Name to print in locking output.
91
92const char* TGLViewerBase::LockIdStr() const
93{
94 return "TGLViewerBase";
95}
96
97/**************************************************************************/
98// Scene & scene-info management
99/**************************************************************************/
100
101////////////////////////////////////////////////////////////////////////////////
102/// Find scene-info corresponding to scene.
103
106{
107 SceneInfoList_i i = fScenes.begin();
108 while (i != fScenes.end() && (*i)->GetScene() != scene) ++i;
109 return i;
110}
111
112////////////////////////////////////////////////////////////////////////////////
113/// Add new scene, appropriate scene-info is created.
114
116{
118 if (i == fScenes.end()) {
119 TGLSceneInfo* sinfo = scene->CreateSceneInfo(this);
120 fScenes.push_back(sinfo);
121 scene->AddViewer(this);
122 Changed();
123 return sinfo;
124 } else {
125 Warning("TGLViewerBase::AddScene", "scene '%s' already in the list.",
126 scene->GetName());
127 return nullptr;
128 }
129}
130
131////////////////////////////////////////////////////////////////////////////////
132/// Remove scene from the viewer, its scene-info is deleted.
133
135{
137 if (i != fScenes.end()) {
138 delete *i;
139 fScenes.erase(i);
140 scene->RemoveViewer(this);
141 Changed();
142 } else {
143 Warning("TGLViewerBase::RemoveScene", "scene '%s' not found.",
144 scene->GetName());
145 }
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Remove all scenes from the viewer, their scene-infos are deleted.
150
152{
153 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
154 {
155 TGLSceneInfo * sinfo = *i;
156 sinfo->GetScene()->RemoveViewer(this);
157 delete sinfo;
158 }
159 fScenes.clear();
160 Changed();
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Remove scene, its scene-info is deleted.
165/// Called from scene that is being destroyed while still holding
166/// viewer references.
167
169{
171 if (i != fScenes.end()) {
172 delete *i;
173 fScenes.erase(i);
174 Changed();
175 } else {
176 Warning("TGLViewerBase::SceneDestructing", "scene not found.");
177 }
178}
179
180////////////////////////////////////////////////////////////////////////////////
181/// Find scene-info corresponding to scene.
182
184{
186 if (i != fScenes.end())
187 return *i;
188 else
189 return nullptr;
190}
191
192////////////////////////////////////////////////////////////////////////////////
193/// Find logical-shape representing object id in the list of scenes.
194/// Return 0 if not found.
195
197{
198 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
199 {
200 TGLLogicalShape *lshp = (*i)->GetScene()->FindLogical(id);
201 if (lshp)
202 return lshp;
203 }
204 return nullptr;
205}
206
207////////////////////////////////////////////////////////////////////////////////
208/// Add overlay element.
209
215
216////////////////////////////////////////////////////////////////////////////////
217/// Remove overlay element.
218
220{
221 OverlayElmVec_i it = std::find(fOverlay.begin(), fOverlay.end(), el);
222 if (it != fOverlay.end())
223 fOverlay.erase(it);
224 Changed();
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Delete overlay elements that are annotations.
229
234
235////////////////////////////////////////////////////////////////////////////////
236/// Delete overlay elements.
237
239{
241 fOverlay.swap(ovl);
242
243 for (OverlayElmVec_i i = ovl.begin(); i != ovl.end(); ++i)
244 {
245 if (role == TGLOverlayElement::kAll || (*i)->GetRole() == role)
246 delete *i;
247 else
248 fOverlay.push_back(*i);
249 }
250
251 Changed();
252}
253
254/**************************************************************************/
255// SceneInfo update / check
256/**************************************************************************/
257
258////////////////////////////////////////////////////////////////////////////////
259/// Force rebuild of view-dependent scene-info structures.
260///
261/// This should be called before calling render (draw/select) if
262/// something that affects camera interest has been changed.
263
265{
266 SceneInfoList_i i = fScenes.begin();
267 while (i != fScenes.end())
268 {
269 (*i)->ResetSceneStamp();
270 ++i;
271 }
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// Merge bounding-boxes of all active registered scenes.
276
278{
279 bbox.SetEmpty();
280 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
281 {
282 TGLSceneInfo * sinfo = *i;
283 if (sinfo->GetActive())
284 {
285 sinfo->SetupTransformsAndBBox(); // !!! transform not done yet, no camera
286 bbox.MergeAligned(sinfo->GetTransformedBBox());
287 }
288 }
289}
290
291/**************************************************************************/
292// Rendering / selection virtuals
293/**************************************************************************/
294
295////////////////////////////////////////////////////////////////////////////////
296/// Setup clip-object. Protected virtual method.
297
299{
300 if (fClip)
301 {
303 }
304}
305
306////////////////////////////////////////////////////////////////////////////////
307/// Initialize render-context, setup camera, GL, render-area.
308/// Check and lock scenes, determine their visibility.
309
311{
313 if (cid == nullptr)
314 {
315 // Assume derived class set it up for us.
316 // This happens due to complex implementation
317 // of gl-in-pad using gGLManager.
318 // In principle we should throw an exception:
319 // throw std::runtime_error("Can not resolve GL context.");
320 }
321 else
322 {
323 if (cid != fRnrCtx->GetGLCtxIdentity())
324 {
325 if (fRnrCtx->GetGLCtxIdentity() != nullptr)
326 Warning("TGLViewerBase::PreRender", "Switching to another GL context; maybe you should use context-sharing.");
328 }
329 }
330
337
339 {
342 }
343
346 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
347 {
348 TGLSceneInfo *sinfo = *i;
349 TGLSceneBase *scene = sinfo->GetScene();
350 if (sinfo->GetActive())
351 {
352 if ( ! fRnrCtx->Selection() || scene->GetSelectable())
353 {
354 if ( ! sinfo->GetScene()->TakeLock(kDrawLock))
355 {
356 Warning("TGLViewerBase::PreRender", "locking of scene '%s' failed, skipping.",
357 sinfo->GetScene()->GetName());
358 continue;
359 }
360 locked_scenes.push_back(sinfo);
361 }
362 sinfo->SetupTransformsAndBBox(); // !!! transform not done yet
363 fOverallBoundingBox.MergeAligned(sinfo->GetTransformedBBox());
364 }
365 }
366
369
370 // Make precursory selection of visible scenes.
371 // Only scene bounding-box .vs. camera frustum check performed.
372 fVisScenes.clear();
374 {
375 TGLSceneInfo * sinfo = *i;
376 const TGLBoundingBox & bbox = sinfo->GetTransformedBBox();
377 Bool_t visp = (!bbox.IsEmpty() && fCamera->FrustumOverlap(bbox) != Rgl::kOutside);
378 sinfo->ViewCheck(visp);
379 if (visp) {
381 sinfo->GetScene()->PreDraw(*fRnrCtx);
382 if (sinfo->IsVisible()) {
383 fVisScenes.push_back(sinfo);
384 } else {
385 sinfo->GetScene()->PostDraw(*fRnrCtx);
386 sinfo->GetScene()->ReleaseLock(kDrawLock);
387 }
388 fRnrCtx->SetSceneInfo(nullptr);
389 } else {
390 sinfo->GetScene()->ReleaseLock(kDrawLock);
391 }
392 }
393}
394
395////////////////////////////////////////////////////////////////////////////////
396/// Call sub-rendering function render_foo on all currently visible
397/// scenes.
398
400{
401 Int_t nScenes = fVisScenes.size();
402
403 for (Int_t i = 0; i < nScenes; ++i)
404 {
406 TGLSceneBase* scene = sinfo->GetScene();
408 glPushName(i);
409 scene->PreRender(*fRnrCtx);
411 scene->PostRender(*fRnrCtx);
412 glPopName();
413 fRnrCtx->SetSceneInfo(nullptr);
414 }
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// Render all scenes. This is done in two main passes:
419/// - render opaque objects from all scenes
420/// - render transparent objects from all scenes
421
427
428////////////////////////////////////////////////////////////////////////////////
429/// Render non-selected objects from all scenes.
430
445
446////////////////////////////////////////////////////////////////////////////////
447/// Render selected objects from all scenes.
448
463
464////////////////////////////////////////////////////////////////////////////////
465/// Render selected objects from all scenes for highlight.
466
483
484////////////////////////////////////////////////////////////////////////////////
485/// Render opaque objects from all scenes.
486
488{
490 {
492 }
493 if (rnr_selected)
494 {
496 }
497
498 TGLUtil::CheckError("TGLViewerBase::RenderOpaque - pre exit check");
499}
500
501////////////////////////////////////////////////////////////////////////////////
502/// Render transparent objects from all scenes.
503
523
524////////////////////////////////////////////////////////////////////////////////
525/// Render overlay objects.
526
528{
529 Int_t nOvl = fOverlay.size();
530 for (Int_t i = 0; i < nOvl; ++i)
531 {
533 if (el->GetState() & state)
534 {
535 if (selection) glPushName(i);
536 el->Render(*fRnrCtx);
537 if (selection) glPopName();
538 }
539 }
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Function called after rendering is finished.
544/// Here we just unlock the scenes.
545
547{
548 for (SceneInfoVec_i i = fVisScenes.begin(); i != fVisScenes.end(); ++i)
549 {
550 TGLSceneInfo* sinfo = *i;
552 sinfo->GetScene()->PostDraw(*fRnrCtx);
553 fRnrCtx->SetSceneInfo(nullptr);
554 sinfo->GetScene()->ReleaseLock(kDrawLock);
555 }
557}
558
559////////////////////////////////////////////////////////////////////////////////
560/// Perform minimal initialization for overlay selection.
561/// Here we assume that scene has already been drawn and that
562/// camera and overall bounding box are ok.
563/// Scenes are not locked.
564
569
570////////////////////////////////////////////////////////////////////////////////
571/// Perform cleanup after overlay selection.
572
576
577/**************************************************************************/
578// High-level functions: drawing and picking.
579/**************************************************************************/
580
581
582//______________________________________________________________________
583//void TGLViewerBase::Select(Int_t selX, Int_t selY, Int_t selRadius)
584//{
585 // Perform render-pass in selection mode.
586 // Process the selection results.
587 // For now only in derived classes.
588//}
589
590////////////////////////////////////////////////////////////////////////////////
591/// Process selection record on buffer-position 'recIdx' and
592/// fill the data into 'rec'.
593///
594/// Returns TRUE if scene was demangled and an object identified.
595/// When FALSE is returned it is still possible that scene has been
596/// identified. Check for this if interested in scene-selection.
597///
598/// The select-buffer is taken form fRnrCtx.
599
601{
603 if (recIdx >= sb->GetNRecords())
604 return kFALSE;
605
606 if (sb->SelectRecord(rec, recIdx) < 1)
607 return kFALSE;
608
609 UInt_t sceneIdx = rec.GetItem(0);
610 if (sceneIdx >= fVisScenes.size())
611 return kFALSE;
612
614 rec.SetSceneInfo(sinfo);
615 return sinfo->GetScene()->ResolveSelectRecord(rec, 1);
616}
617
618////////////////////////////////////////////////////////////////////////////////
619/// Find next select record that can be resolved, starting from
620/// position 'recIdx'.
621/// 'recIdx' is passed as reference and points to found record in the buffer.
622
624{
626
627 while (recIdx < sb->GetNRecords())
628 {
629 if (ResolveSelectRecord(rec, recIdx))
630 return kTRUE;
631 ++recIdx;
632 }
633 return kFALSE;
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Find next select record that can be resolved and whose result is
638/// not transparent, starting from position 'recIdx'.
639/// 'recIdx' is passed as reference and points to found record in the buffer.
640
642{
644
645 while (recIdx < sb->GetNRecords())
646 {
647 if (ResolveSelectRecord(rec, recIdx) && ! rec.GetTransparent())
648 return kTRUE;
649 ++recIdx;
650 }
651 return kFALSE;
652}
653
654////////////////////////////////////////////////////////////////////////////////
655/// Find next overlay-select record that can be resolved, starting from
656/// position 'recIdx'.
657/// 'recIdx' is passed as reference and points to found record in the buffer.
658
660 Int_t & recIdx)
661{
663
664 while (recIdx < sb->GetNRecords())
665 {
666 sb->SelectRecord(rec, recIdx);
667 if (rec.GetItem(0) < fOverlay.size())
668 {
669 rec.SetOvlElement(fOverlay[rec.GetItem(0)]);
670 rec.NextPos();
671 return kTRUE;
672 }
673 ++recIdx;
674 }
675 return kFALSE;
676}
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 Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
const_iterator begin() const
const_iterator end() const
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:490
Concrete class describing an orientated (free) or axis aligned box of 8 vertices.
void SetEmpty()
Set bounding box empty - all vertices at (0,0,0)
Bool_t IsEmpty() const
void MergeAligned(const TGLBoundingBox &other)
Expand current bbox so that it includes other's bbox.
Rgl::EOverlap FrustumOverlap(const TGLBoundingBox &box) const
Calculate overlap (kInside, kOutside, kPartial) of box with camera frustum Camera must have valid fru...
virtual void Apply(const TGLBoundingBox &sceneBox, const TGLRect *pickRect=nullptr) const =0
virtual void Setup(const TGLBoundingBox &bbox)=0
Identifier of a shared GL-context.
Definition TGLContext.h:81
static TGLContextIdentity * GetCurrent()
Find identitfy of current context. Static.
Abstract logical shape - a GL 'drawable' - base for all shapes - faceset sphere etc.
An overlay element.
Definition TGLOverlay.h:23
Selection record for overlay objects.
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition TGLRnrCtx.h:41
void SetSceneInfo(TGLSceneInfo *si)
Definition TGLRnrCtx.h:168
void SetViewerLOD(Short_t LOD)
Definition TGLRnrCtx.h:172
TGLSelectBuffer * GetSelectBuffer() const
Definition TGLRnrCtx.h:231
void SetViewerOLLineW(Float_t w)
Definition TGLRnrCtx.h:192
void SetViewerWFLineW(Float_t w)
Definition TGLRnrCtx.h:188
void SetGLCtxIdentity(TGLContextIdentity *cid)
Definition TGLRnrCtx.h:255
TGLRect * GetPickRectangle()
Return current pick rectangle.
void SetViewerStyle(Short_t sty)
Definition TGLRnrCtx.h:183
void SetViewerClip(TGLClip *p)
Definition TGLRnrCtx.h:197
void SetCamera(TGLCamera *c)
Definition TGLRnrCtx.h:167
Bool_t Selection() const
Definition TGLRnrCtx.h:222
void SetHighlight(Bool_t hil)
Definition TGLRnrCtx.h:219
TGLContextIdentity * GetGLCtxIdentity() const
Definition TGLRnrCtx.h:254
Scene base-class – provides basic interface expected by the TGLViewer or its sub-classes:
virtual void RenderSelOpaque(TGLRnrCtx &rnrCtx)
Render selected opaque elements.
virtual void RenderSelTransp(TGLRnrCtx &rnrCtx)
Render selected transparent elements for highlight.
virtual void RenderTransp(TGLRnrCtx &rnrCtx)
Render transparent elements.
virtual void RenderSelTranspForHighlight(TGLRnrCtx &rnrCtx)
Render selected transparent elements.
virtual void RenderOpaque(TGLRnrCtx &rnrCtx)
Render opaque elements.
virtual void RenderSelOpaqueForHighlight(TGLRnrCtx &rnrCtx)
Render selected opaque elements for highlight.
Base class for extended scene context.
Encapsulates OpenGL select buffer.
Standard selection record including information about containing scene and details ob out selected ob...
static Int_t CheckError(const char *loc)
Check current GL error state, outputting details via ROOT Error method if one.
Definition TGLUtil.cxx:1637
void SceneDestructing(TGLSceneBase *scene)
Remove scene, its scene-info is deleted.
OverlayElmVec_t fOverlay
virtual void RenderTransparent(Bool_t rnr_non_selected=kTRUE, Bool_t rnr_selected=kTRUE)
Render transparent objects from all scenes.
virtual void DeleteOverlayElements(TGLOverlayElement::ERole r)
Delete overlay elements.
virtual void Changed()
virtual void PreRenderOverlaySelection()
Perform minimal initialization for overlay selection.
SceneInfoList_t fScenes
TGLRnrCtx * fRnrCtx
SceneInfoVec_t fVisScenes
const char * LockIdStr() const override
Name to print in locking output.
TGLCamera * fCamera
virtual void RenderSelected()
Render selected objects from all scenes.
void SubRenderScenes(SubRender_foo render_foo)
Call sub-rendering function render_foo on all currently visible scenes.
Bool_t FindClosestOpaqueRecord(TGLSelectRecord &rec, Int_t &recIdx)
Find next select record that can be resolved and whose result is not transparent, starting from posit...
virtual void ResetSceneInfos()
Force rebuild of view-dependent scene-info structures.
TGLSceneInfo * AddScene(TGLSceneBase *scene)
Add new scene, appropriate scene-info is created.
TGLLogicalShape * FindLogicalInScenes(TObject *id)
Find logical-shape representing object id in the list of scenes.
std::vector< TGLOverlayElement * > OverlayElmVec_t
virtual void RemoveOverlayElement(TGLOverlayElement *el)
Remove overlay element.
TGLClip * fClip
virtual void RenderOverlay(Int_t state, Bool_t selection)
Render overlay objects.
SceneInfoVec_t::iterator SceneInfoVec_i
TGLSceneInfo * GetSceneInfo(TGLSceneBase *scene)
Find scene-info corresponding to scene.
virtual void Render()
Render all scenes.
virtual void PostRenderOverlaySelection()
Perform cleanup after overlay selection.
virtual void PreRender()
Initialize render-context, setup camera, GL, render-area.
virtual void PostRender()
Function called after rendering is finished.
virtual void SetupClipObject()
Setup clip-object. Protected virtual method.
SceneInfoList_i FindScene(TGLSceneBase *scene)
Find scene-info corresponding to scene.
Bool_t FindClosestOverlayRecord(TGLOvlSelectRecord &rec, Int_t &recIdx)
Find next overlay-select record that can be resolved, starting from position 'recIdx'.
virtual void MergeSceneBBoxes(TGLBoundingBox &bbox)
Merge bounding-boxes of all active registered scenes.
OverlayElmVec_t::iterator OverlayElmVec_i
void RemoveAllScenes()
Remove all scenes from the viewer, their scene-infos are deleted.
Bool_t fResetSceneInfosOnRender
TGLBoundingBox fOverallBoundingBox
void RemoveScene(TGLSceneBase *scene)
Remove scene from the viewer, its scene-info is deleted.
std::list< TGLSceneInfo * > SceneInfoList_t
virtual void DeleteOverlayAnnotations()
Delete overlay elements that are annotations.
virtual void RenderNonSelected()
Render non-selected objects from all scenes.
Bool_t ResolveSelectRecord(TGLSelectRecord &rec, Int_t recIdx)
Process selection record on buffer-position 'recIdx' and fill the data into 'rec'.
virtual void RenderSelectedForHighlight()
Render selected objects from all scenes for highlight.
virtual void RenderOpaque(Bool_t rnr_non_selected=kTRUE, Bool_t rnr_selected=kTRUE)
Render opaque objects from all scenes.
SceneInfoList_t::iterator SceneInfoList_i
~TGLViewerBase() override
Destructor.
virtual void AddOverlayElement(TGLOverlayElement *el)
Add overlay element.
Bool_t FindClosestRecord(TGLSelectRecord &rec, Int_t &recIdx)
Find next select record that can be resolved, starting from position 'recIdx'.
Mother of all ROOT objects.
Definition TObject.h:41
@ kOutside
Definition TGLUtil.h:38