Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveScene.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 "TEveScene.h"
13 #include "TEveViewer.h"
14 #include "TEveManager.h"
15 #include "TEveTrans.h"
16 #include "TEvePad.h"
17 
18 #include "TGLScenePad.h"
19 #include "TGLLogicalShape.h"
20 #include "TGLPhysicalShape.h"
21 
22 #include "TList.h"
23 #include "TExMap.h"
24 
25 /** \class TEveScene
26 \ingroup TEve
27 Eve representation of TGLScene.
28 The GLScene is owned by this class - it is created on construction
29 time and deleted at destruction.
30 
31 Normally all objects are positioned directly in global scene-space.
32 By setting the fHierarchical flag, positions of children get
33 calculated by multiplying the transformation matrices of all parents.
34 */
35 
36 ClassImp(TEveScene);
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Constructor.
40 
41 TEveScene::TEveScene(const char* n, const char* t) :
42  TEveElementList(n, t),
43  fPad (0),
44  fGLScene(0),
45  fChanged (kFALSE),
46  fSmartRefresh (kTRUE),
47  fHierarchical (kFALSE)
48 {
49  fPad = new TEvePad;
50  fPad->GetListOfPrimitives()->Add(this);
51  fGLScene = new TGLScenePad(fPad);
52  fGLScene->SetName(n);
53  fGLScene->SetAutoDestruct(kFALSE);
54  fGLScene->SetSmartRefresh(kTRUE);
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Constructor.
59 
60 TEveScene::TEveScene(TGLScenePad* gl_scene, const char* n, const char* t) :
61  TEveElementList(n, t),
62  fPad (0),
63  fGLScene(gl_scene),
64  fChanged (kFALSE),
65  fSmartRefresh (kTRUE),
66  fHierarchical (kFALSE)
67 {
68  fPad = new TEvePad;
69  fPad->GetListOfPrimitives()->Add(this);
70  fGLScene->SetPad(fPad);
71  fGLScene->SetName(n);
72  fGLScene->SetAutoDestruct(kFALSE);
73  fGLScene->SetSmartRefresh(kTRUE);
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Destructor.
78 
79 TEveScene::~TEveScene()
80 {
81  fDestructing = kStandard;
82 
83  gEve->GetViewers()->SceneDestructing(this);
84  gEve->GetScenes()->RemoveElement(this);
85  delete fGLScene;
86  delete fPad;
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Virtual from TEveElement; here we simply append this scene to
91 /// the list.
92 
93 void TEveScene::CollectSceneParents(List_t& scenes)
94 {
95  scenes.push_back(this);
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// Repaint the scene.
100 
101 void TEveScene::Repaint(Bool_t dropLogicals)
102 {
103  if (dropLogicals) fGLScene->SetSmartRefresh(kFALSE);
104  fGLScene->PadPaint(fPad);
105  if (dropLogicals) fGLScene->SetSmartRefresh(kTRUE);
106  fChanged = kFALSE;
107 
108  // Hack to propagate selection state to physical shapes.
109  //
110  // Should actually be published in PadPaint() following a direct
111  // AddObject() call, but would need some other stuff for that.
112  // Optionally, this could be exported via the TAtt3D and everything
113  // would be sweet.
114 
115  TGLScene::LogicalShapeMap_t& logs = fGLScene->RefLogicalShapes();
116  TEveElement* elm;
117  for (TGLScene::LogicalShapeMapIt_t li = logs.begin(); li != logs.end(); ++li)
118  {
119  elm = dynamic_cast<TEveElement*>(li->first);
120  if (elm && li->second->Ref() == 1)
121  {
122  TGLPhysicalShape* pshp = const_cast<TGLPhysicalShape*>(li->second->GetFirstPhysical());
123  pshp->Select(elm->GetSelectedLevel());
124  }
125  }
126 
127  // Fix positions for hierarchical scenes.
128  if (fHierarchical)
129  {
130  RetransHierarchically();
131  }
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Entry point for hierarchical transformation update.
136 /// Calls the recursive variant on all children.
137 
138 void TEveScene::RetransHierarchically()
139 {
140  fGLScene->BeginUpdate();
141 
142  RetransHierarchicallyRecurse(this, RefMainTrans());
143 
144  fGLScene->EndUpdate();
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 /// Set transformation matrix for physical shape of element el in
149 /// the GL-scene and recursively descend into children (if enabled).
150 
151 void TEveScene::RetransHierarchicallyRecurse(TEveElement* el, const TEveTrans& tp)
152 {
153  static const TEveException eh("TEveScene::RetransHierarchicallyRecurse ");
154 
155  TEveTrans t(tp);
156  if (el->HasMainTrans())
157  t *= el->RefMainTrans();
158 
159  if (el->GetRnrSelf() && el != this)
160  {
161  fGLScene->UpdatePhysioLogical(el->GetRenderObject(eh), t.Array(), 0);
162  }
163 
164  if (el->GetRnrChildren())
165  {
166  for (List_i i = el->BeginChildren(); i != el->EndChildren(); ++i)
167  {
168  if ((*i)->GetRnrAnything())
169  RetransHierarchicallyRecurse(*i, t);
170  }
171  }
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Set scene's name.
176 
177 void TEveScene::SetName(const char* n)
178 {
179  TEveElementList::SetName(n);
180  fGLScene->SetName(n);
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Paint the scene. Iterate over children and calls PadPaint().
185 
186 void TEveScene::Paint(Option_t* option)
187 {
188  if (GetRnrState())
189  {
190  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
191  (*i)->PadPaint(option);
192  }
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Remove element from the scene.
197 /// It is not an error if the element is not found in the scene.
198 
199 void TEveScene::DestroyElementRenderers(TEveElement* element)
200 {
201  static const TEveException eh("TEveScene::DestroyElementRenderers ");
202 
203  fGLScene->BeginUpdate();
204  Bool_t changed = fGLScene->DestroyLogical(element->GetRenderObject(eh), kFALSE);
205  fGLScene->EndUpdate(changed, changed);
206 }
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 /// Remove element represented by object rnrObj from the scene.
210 /// It is not an error if the element is not found in the scene.
211 
212 void TEveScene::DestroyElementRenderers(TObject* rnrObj)
213 {
214  fGLScene->BeginUpdate();
215  Bool_t changed = fGLScene->DestroyLogical(rnrObj, kFALSE);
216  fGLScene->EndUpdate(changed, changed);
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Return icon for scene.
221 
222 const TGPicture* TEveScene::GetListTreeIcon(Bool_t)
223 {
224  return TEveElement::fgListTreeIcons[2];
225 }
226 
227 /** \class TEveSceneList
228 \ingroup TEve
229 List of Scenes providing common operations on TEveScene collections.
230 */
231 
232 ClassImp(TEveSceneList);
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Constructor.
236 
237 TEveSceneList::TEveSceneList(const char* n, const char* t) :
238  TEveElementList(n, t)
239 {
240  SetChildClass(TEveScene::Class());
241 }
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 /// Destroy all scenes and their contents.
245 /// Tho object with non-zero deny-destroy will still survive.
246 
247 void TEveSceneList::DestroyScenes()
248 {
249  List_i i = fChildren.begin();
250  while (i != fChildren.end())
251  {
252  TEveScene* s = (TEveScene*) *(i++);
253  s->DestroyElements();
254  s->DestroyOrWarn();
255  }
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Repaint scenes that are tagged as changed.
260 
261 void TEveSceneList::RepaintChangedScenes(Bool_t dropLogicals)
262 {
263  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
264  {
265  TEveScene* s = (TEveScene*) *i;
266  if (s->IsChanged())
267  {
268  s->Repaint(dropLogicals);
269  }
270  }
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Repaint all scenes.
275 
276 void TEveSceneList::RepaintAllScenes(Bool_t dropLogicals)
277 {
278  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
279  {
280  ((TEveScene*) *i)->Repaint(dropLogicals);
281  }
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Loop over all scenes and remove all instances of element from them.
286 
287 void TEveSceneList::DestroyElementRenderers(TEveElement* element)
288 {
289  static const TEveException eh("TEveSceneList::DestroyElementRenderers ");
290 
291  TObject* obj = element->GetRenderObject(eh);
292  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
293  {
294  ((TEveScene*)*i)->DestroyElementRenderers(obj);
295  }
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Loop over all scenes and update them accordingly:
300 /// 1. if scene is marked as changed, it is repainted;
301 /// 2. otherwise iteration is done over the set of stamped elements and
302 /// their physical/logical shapes are updated accordingly.
303 ///
304 /// This allows much finer update granularity without resetting of
305 /// complex GL-viewer and GL-scene state.
306 
307 void TEveSceneList::ProcessSceneChanges(Bool_t dropLogicals, TExMap* stampMap)
308 {
309  // We need changed elements sorted by their "render object" as we do
310  // parallel iteration over this list and the list of logical shapes
311  // in every scene.
312 
313  static const TEveException eh("TEveSceneList::ProcessSceneChanges ");
314 
315  typedef std::map<TObject*, TEveElement*> mObjectElement_t;
316  typedef mObjectElement_t::iterator mObjectElement_i;
317 
318  mObjectElement_t changed_objects;
319  {
320  Long64_t key, value;
321  TExMapIter stamped_elements(stampMap);
322  while (stamped_elements.Next(key, value))
323  {
324  TEveElement *el = reinterpret_cast<TEveElement*>(key);
325  changed_objects.insert(std::make_pair(el->GetRenderObject(eh), el));
326  }
327  }
328 
329  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
330  {
331  TEveScene* s = (TEveScene*) *i;
332 
333  if (s->IsChanged())
334  {
335  s->Repaint(dropLogicals);
336  }
337  else
338  {
339  Bool_t updateViewers = kFALSE;
340  Bool_t incTimeStamp = kFALSE;
341  Bool_t transbboxChg = kFALSE;
342 
343  s->GetGLScene()->BeginUpdate();
344 
345  // Process stamps.
346  TGLScene::LogicalShapeMap_t &logs = s->GetGLScene()->RefLogicalShapes();
347  TGLScene::LogicalShapeMapIt_t li = logs.begin();
348 
349  mObjectElement_i ei = changed_objects.begin();
350 
351  while (li != logs.end() && ei != changed_objects.end())
352  {
353  if (li->first == ei->first)
354  {
355  if (li->second->Ref() != 1)
356  Warning("TEveSceneList::ProcessSceneChanges",
357  "Expect one physical, cnt=%u.", li->second->Ref());
358 
359  TGLLogicalShape *lshp = li->second;
360  TGLPhysicalShape *pshp = const_cast<TGLPhysicalShape*>(lshp->GetFirstPhysical());
361  TEveElement *el = ei->second;
362  UChar_t bits = el->GetChangeBits();
363 
364  if (bits & kCBColorSelection)
365  {
366  pshp->Select(el->GetSelectedLevel());
367  pshp->SetDiffuseColor(el->GetMainColor(),
368  el->GetMainTransparency());
369  }
370 
371  if (bits & kCBTransBBox)
372  {
373  if (el->HasMainTrans())
374  pshp->SetTransform(el->PtrMainTrans()->Array());
375  lshp->UpdateBoundingBox();
376  incTimeStamp = kTRUE;
377  transbboxChg = kTRUE;
378  }
379 
380  if (bits & kCBObjProps)
381  {
382  lshp->DLCacheClear();
383  }
384 
385  ++li; ++ei;
386  updateViewers = kTRUE;
387  }
388  else if (li->first < ei->first)
389  {
390  ++li;
391  }
392  else
393  {
394  ++ei;
395  }
396  }
397 
398  s->GetGLScene()->EndUpdate(updateViewers, incTimeStamp, updateViewers);
399 
400  // Fix positions for hierarchical scenes.
401  if (s->GetHierarchical() && transbboxChg)
402  {
403  s->RetransHierarchically();
404  }
405  }
406  }
407 }