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
51
52////////////////////////////////////////////////////////////////////////////////
53
55 fRnrCtx (nullptr),
56 fCamera (nullptr),
57 fClip (nullptr),
58 fLOD (TGLRnrCtx::kLODHigh),
59 fStyle (TGLRnrCtx::kFill),
60 fWFLineW (1),
61 fOLLineW (1),
62
63 fResetSceneInfosOnRender (kFALSE),
64 fChanged (kFALSE)
65{
66 // Constructor.
67
68 fRnrCtx = new TGLRnrCtx(this);
69
70 fWFLineW = gEnv->GetValue("OpenGL.WireframeLineScalingFactor", 1.0);
71 fOLLineW = gEnv->GetValue("OpenGL.OutlineLineScalingFactor", 1.0);
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Destructor.
76
78{
79 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
80 {
81 (*i)->GetScene()->RemoveViewer(this);
82 delete *i;
83 }
84
86
87 delete fRnrCtx;
88}
89
90////////////////////////////////////////////////////////////////////////////////
91/// Name to print in locking output.
92
93const char* TGLViewerBase::LockIdStr() const
94{
95 return "TGLViewerBase";
96}
97
98/**************************************************************************/
99// Scene & scene-info management
100/**************************************************************************/
101
102////////////////////////////////////////////////////////////////////////////////
103/// Find scene-info corresponding to scene.
104
107{
108 SceneInfoList_i i = fScenes.begin();
109 while (i != fScenes.end() && (*i)->GetScene() != scene) ++i;
110 return i;
111}
112
113////////////////////////////////////////////////////////////////////////////////
114/// Add new scene, appropriate scene-info is created.
115
117{
119 if (i == fScenes.end()) {
120 TGLSceneInfo* sinfo = scene->CreateSceneInfo(this);
121 fScenes.push_back(sinfo);
122 scene->AddViewer(this);
123 Changed();
124 return sinfo;
125 } else {
126 Warning("TGLViewerBase::AddScene", "scene '%s' already in the list.",
127 scene->GetName());
128 return nullptr;
129 }
130}
131
132////////////////////////////////////////////////////////////////////////////////
133/// Remove scene from the viewer, its scene-info is deleted.
134
136{
138 if (i != fScenes.end()) {
139 delete *i;
140 fScenes.erase(i);
141 scene->RemoveViewer(this);
142 Changed();
143 } else {
144 Warning("TGLViewerBase::RemoveScene", "scene '%s' not found.",
145 scene->GetName());
146 }
147}
148
149////////////////////////////////////////////////////////////////////////////////
150/// Remove all scenes from the viewer, their scene-infos are deleted.
151
153{
154 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
155 {
156 TGLSceneInfo * sinfo = *i;
157 sinfo->GetScene()->RemoveViewer(this);
158 delete sinfo;
159 }
160 fScenes.clear();
161 Changed();
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// Remove scene, its scene-info is deleted.
166/// Called from scene that is being destroyed while still holding
167/// viewer references.
168
170{
172 if (i != fScenes.end()) {
173 delete *i;
174 fScenes.erase(i);
175 Changed();
176 } else {
177 Warning("TGLViewerBase::SceneDestructing", "scene not found.");
178 }
179}
180
181////////////////////////////////////////////////////////////////////////////////
182/// Find scene-info corresponding to scene.
183
185{
187 if (i != fScenes.end())
188 return *i;
189 else
190 return nullptr;
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Find logical-shape representing object id in the list of scenes.
195/// Return 0 if not found.
196
198{
199 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
200 {
201 TGLLogicalShape *lshp = (*i)->GetScene()->FindLogical(id);
202 if (lshp)
203 return lshp;
204 }
205 return nullptr;
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Add overlay element.
210
216
217////////////////////////////////////////////////////////////////////////////////
218/// Remove overlay element.
219
221{
222 OverlayElmVec_i it = std::find(fOverlay.begin(), fOverlay.end(), el);
223 if (it != fOverlay.end())
224 fOverlay.erase(it);
225 Changed();
226}
227
228////////////////////////////////////////////////////////////////////////////////
229/// Delete overlay elements that are annotations.
230
235
236////////////////////////////////////////////////////////////////////////////////
237/// Delete overlay elements.
238
240{
242 fOverlay.swap(ovl);
243
244 for (OverlayElmVec_i i = ovl.begin(); i != ovl.end(); ++i)
245 {
246 if (role == TGLOverlayElement::kAll || (*i)->GetRole() == role)
247 delete *i;
248 else
249 fOverlay.push_back(*i);
250 }
251
252 Changed();
253}
254
255/**************************************************************************/
256// SceneInfo update / check
257/**************************************************************************/
258
259////////////////////////////////////////////////////////////////////////////////
260/// Force rebuild of view-dependent scene-info structures.
261///
262/// This should be called before calling render (draw/select) if
263/// something that affects camera interest has been changed.
264
266{
267 SceneInfoList_i i = fScenes.begin();
268 while (i != fScenes.end())
269 {
270 (*i)->ResetSceneStamp();
271 ++i;
272 }
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// Merge bounding-boxes of all active registered scenes.
277
279{
280 bbox.SetEmpty();
281 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
282 {
283 TGLSceneInfo * sinfo = *i;
284 if (sinfo->GetActive())
285 {
286 sinfo->SetupTransformsAndBBox(); // !!! transform not done yet, no camera
287 bbox.MergeAligned(sinfo->GetTransformedBBox());
288 }
289 }
290}
291
292/**************************************************************************/
293// Rendering / selection virtuals
294/**************************************************************************/
295
296////////////////////////////////////////////////////////////////////////////////
297/// Setup clip-object. Protected virtual method.
298
300{
301 if (fClip)
302 {
304 }
305}
306
307////////////////////////////////////////////////////////////////////////////////
308/// Initialize render-context, setup camera, GL, render-area.
309/// Check and lock scenes, determine their visibility.
310
312{
314 if (cid == nullptr)
315 {
316 // Assume derived class set it up for us.
317 // This happens due to complex implementation
318 // of gl-in-pad using gGLManager.
319 // In principle we should throw an exception:
320 // throw std::runtime_error("Can not resolve GL context.");
321 }
322 else
323 {
324 if (cid != fRnrCtx->GetGLCtxIdentity())
325 {
326 if (fRnrCtx->GetGLCtxIdentity() != nullptr)
327 Warning("TGLViewerBase::PreRender", "Switching to another GL context; maybe you should use context-sharing.");
329 }
330 }
331
338
340 {
343 }
344
347 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
348 {
349 TGLSceneInfo *sinfo = *i;
350 TGLSceneBase *scene = sinfo->GetScene();
351 if (sinfo->GetActive())
352 {
353 if ( ! fRnrCtx->Selection() || scene->GetSelectable())
354 {
355 if ( ! sinfo->GetScene()->TakeLock(kDrawLock))
356 {
357 Warning("TGLViewerBase::PreRender", "locking of scene '%s' failed, skipping.",
358 sinfo->GetScene()->GetName());
359 continue;
360 }
361 locked_scenes.push_back(sinfo);
362 }
363 sinfo->SetupTransformsAndBBox(); // !!! transform not done yet
364 fOverallBoundingBox.MergeAligned(sinfo->GetTransformedBBox());
365 }
366 }
367
370
371 // Make precursory selection of visible scenes.
372 // Only scene bounding-box .vs. camera frustum check performed.
373 fVisScenes.clear();
375 {
376 TGLSceneInfo * sinfo = *i;
377 const TGLBoundingBox & bbox = sinfo->GetTransformedBBox();
378 Bool_t visp = (!bbox.IsEmpty() && fCamera->FrustumOverlap(bbox) != Rgl::kOutside);
379 sinfo->ViewCheck(visp);
380 if (visp) {
382 sinfo->GetScene()->PreDraw(*fRnrCtx);
383 if (sinfo->IsVisible()) {
384 fVisScenes.push_back(sinfo);
385 } else {
386 sinfo->GetScene()->PostDraw(*fRnrCtx);
387 sinfo->GetScene()->ReleaseLock(kDrawLock);
388 }
389 fRnrCtx->SetSceneInfo(nullptr);
390 } else {
391 sinfo->GetScene()->ReleaseLock(kDrawLock);
392 }
393 }
394}
395
396////////////////////////////////////////////////////////////////////////////////
397/// Call sub-rendering function render_foo on all currently visible
398/// scenes.
399
401{
402 Int_t nScenes = fVisScenes.size();
403
404 for (Int_t i = 0; i < nScenes; ++i)
405 {
407 TGLSceneBase* scene = sinfo->GetScene();
409 glPushName(i);
410 scene->PreRender(*fRnrCtx);
412 scene->PostRender(*fRnrCtx);
413 glPopName();
414 fRnrCtx->SetSceneInfo(nullptr);
415 }
416}
417
418////////////////////////////////////////////////////////////////////////////////
419/// Render all scenes. This is done in two main passes:
420/// - render opaque objects from all scenes
421/// - render transparent objects from all scenes
422
428
429////////////////////////////////////////////////////////////////////////////////
430/// Render non-selected objects from all scenes.
431
446
447////////////////////////////////////////////////////////////////////////////////
448/// Render selected objects from all scenes.
449
464
465////////////////////////////////////////////////////////////////////////////////
466/// Render selected objects from all scenes for highlight.
467
484
485////////////////////////////////////////////////////////////////////////////////
486/// Render opaque objects from all scenes.
487
489{
491 {
493 }
494 if (rnr_selected)
495 {
497 }
498
499 TGLUtil::CheckError("TGLViewerBase::RenderOpaque - pre exit check");
500}
501
502////////////////////////////////////////////////////////////////////////////////
503/// Render transparent objects from all scenes.
504
524
525////////////////////////////////////////////////////////////////////////////////
526/// Render overlay objects.
527
529{
530 Int_t nOvl = fOverlay.size();
531 for (Int_t i = 0; i < nOvl; ++i)
532 {
534 if (el->GetState() & state)
535 {
536 if (selection) glPushName(i);
537 el->Render(*fRnrCtx);
538 if (selection) glPopName();
539 }
540 }
541}
542
543////////////////////////////////////////////////////////////////////////////////
544/// Function called after rendering is finished.
545/// Here we just unlock the scenes.
546
548{
549 for (SceneInfoVec_i i = fVisScenes.begin(); i != fVisScenes.end(); ++i)
550 {
551 TGLSceneInfo* sinfo = *i;
553 sinfo->GetScene()->PostDraw(*fRnrCtx);
554 fRnrCtx->SetSceneInfo(nullptr);
555 sinfo->GetScene()->ReleaseLock(kDrawLock);
556 }
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Perform minimal initialization for overlay selection.
562/// Here we assume that scene has already been drawn and that
563/// camera and overall bounding box are ok.
564/// Scenes are not locked.
565
570
571////////////////////////////////////////////////////////////////////////////////
572/// Perform cleanup after overlay selection.
573
577
578/**************************************************************************/
579// High-level functions: drawing and picking.
580/**************************************************************************/
581
582
583//______________________________________________________________________
584//void TGLViewerBase::Select(Int_t selX, Int_t selY, Int_t selRadius)
585//{
586 // Perform render-pass in selection mode.
587 // Process the selection results.
588 // For now only in derived classes.
589//}
590
591////////////////////////////////////////////////////////////////////////////////
592/// Process selection record on buffer-position 'recIdx' and
593/// fill the data into 'rec'.
594///
595/// Returns TRUE if scene was demangled and an object identified.
596/// When FALSE is returned it is still possible that scene has been
597/// identified. Check for this if interested in scene-selection.
598///
599/// The select-buffer is taken form fRnrCtx.
600
602{
604 if (recIdx >= sb->GetNRecords())
605 return kFALSE;
606
607 if (sb->SelectRecord(rec, recIdx) < 1)
608 return kFALSE;
609
610 UInt_t sceneIdx = rec.GetItem(0);
611 if (sceneIdx >= fVisScenes.size())
612 return kFALSE;
613
615 rec.SetSceneInfo(sinfo);
616 return sinfo->GetScene()->ResolveSelectRecord(rec, 1);
617}
618
619////////////////////////////////////////////////////////////////////////////////
620/// Find next select record that can be resolved, starting from
621/// position 'recIdx'.
622/// 'recIdx' is passed as reference and points to found record in the buffer.
623
625{
627
628 while (recIdx < sb->GetNRecords())
629 {
630 if (ResolveSelectRecord(rec, recIdx))
631 return kTRUE;
632 ++recIdx;
633 }
634 return kFALSE;
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Find next select record that can be resolved and whose result is
639/// not transparent, starting from position 'recIdx'.
640/// 'recIdx' is passed as reference and points to found record in the buffer.
641
643{
645
646 while (recIdx < sb->GetNRecords())
647 {
648 if (ResolveSelectRecord(rec, recIdx) && ! rec.GetTransparent())
649 return kTRUE;
650 ++recIdx;
651 }
652 return kFALSE;
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Find next overlay-select record that can be resolved, starting from
657/// position 'recIdx'.
658/// 'recIdx' is passed as reference and points to found record in the buffer.
659
661 Int_t & recIdx)
662{
664
665 while (recIdx < sb->GetNRecords())
666 {
667 sb->SelectRecord(rec, recIdx);
668 if (rec.GetItem(0) < fOverlay.size())
669 {
670 rec.SetOvlElement(fOverlay[rec.GetItem(0)]);
671 rec.NextPos();
672 return kTRUE;
673 }
674 ++recIdx;
675 }
676 return kFALSE;
677}
#define GL_TRUE
Definition GL_glu.h:262
#define GL_FALSE
Definition GL_glu.h:261
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
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:229
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:491
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:1646
Base class for GL viewers.
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