Logo ROOT   6.12/07
Reference Guide
TGLScene.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Matevz Tadel, Feb 2007
3 // Author: Richard Maunder 25/05/2005
4 // Parts taken from original TGLRender by Timur Pocheptsov
5 
6 /*************************************************************************
7  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
8  * All rights reserved. *
9  * *
10  * For the licensing terms see $ROOTSYS/LICENSE. *
11  * For the list of contributors see $ROOTSYS/README/CREDITS. *
12  *************************************************************************/
13 
14 #include "TGLScene.h"
15 #include "TGLRnrCtx.h"
16 #include "TGLObject.h"
17 #include "TGLSelectRecord.h"
18 #include "TGLLogicalShape.h"
19 #include "TGLPhysicalShape.h"
20 #include "TGLCamera.h"
21 #include "TGLContext.h"
22 #include "TGLIncludes.h"
23 
24 #include <TColor.h>
25 #include <TROOT.h>
26 #include <TClass.h>
27 
28 #include <algorithm>
29 
30 //==============================================================================
31 // TGLScene::TSceneInfo
32 //==============================================================================
33 
34 //______________________________________________________________________
35 //
36 // Extend TGLSceneInfo for needs of TGLScene:
37 //
38 // 1. DrawElement vectors for opaque/transparent shapes which cache
39 // physicals that pass the clip tests (frustum and additional
40 // clip-object);
41 //
42 // 2. Statistics / debug information
43 //
44 
45 ////////////////////////////////////////////////////////////////////////////////
46 /// Constructor.
47 
49  TGLSceneInfo (view, scene),
50  fMinorStamp (0),
51  fOpaqueCnt (0),
52  fTranspCnt (0),
53  fAsPixelCnt (0)
54 {
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Destructor.
59 
61 {
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Clear given vec and if it grew too large compared to the size of
66 /// shape-of-interest also resize it.
67 
69  Int_t maxSize)
70 {
71  if (vec.capacity() > (size_t) maxSize) {
72  DrawElementVec_t foo;
73  foo.reserve((size_t) maxSize);
74  vec.swap(foo);
75  } else {
76  vec.clear();
77  }
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// Clear given vec and if it grew too large compared to the size of
82 /// shape-of-interest also resize it.
83 
85  Int_t maxSize)
86 {
87  if (vec.capacity() > (size_t) maxSize) {
89  foo.reserve((size_t) maxSize);
90  vec.swap(foo);
91  } else {
92  vec.clear();
93  }
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Clear DrawElementVector fVisibleElement and optionally resize it
98 /// so that it doesn't take more space then required by all the
99 /// elements in the scene's draw-list.
100 
102 {
103  Int_t maxSize = (Int_t) fShapesOfInterest.size();
104 
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// Clear DrawElementPtrVectors and optionally resize them so that
110 /// they don't take more space then required by all the elements in
111 /// the scene's draw-list.
112 
114 {
115  Int_t maxSize = (Int_t) fShapesOfInterest.size();
116 
121 
122  fMinorStamp = 0;
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Quantize LODs for given render-context.
127 
129 {
130  for (DrawElementVec_i i = fVisibleElements.begin(); i != fVisibleElements.end(); ++i)
131  i->fPhysical->QuantizeShapeLOD(i->fPixelLOD, ctx.CombiLOD(), i->fFinalLOD);
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Prepare for drawing - fill DrawElementPtrVectors from the
136 /// contents of fVisibleElements if there was some change.
137 
139 {
140  if (fMinorStamp < fScene->GetMinorStamp())
141  {
142  fOpaqueElements.clear();
143  fTranspElements.clear();
144  fSelOpaqueElements.clear();
145  fSelTranspElements.clear();
146 
147  for (DrawElementVec_i i = fVisibleElements.begin(); i != fVisibleElements.end(); ++i)
148  {
149  if (i->fPhysical->IsSelected())
150  {
151  if (i->fPhysical->IsTransparent())
152  fSelTranspElements.push_back(&*i);
153  else
154  fSelOpaqueElements.push_back(&*i);
155  } else {
156  if (i->fPhysical->IsTransparent())
157  fTranspElements.push_back(&*i);
158  else
159  fOpaqueElements.push_back(&*i);
160  }
161  }
163  }
164 }
165 
166 ////////////////////////////////////////////////////////////////////////////////
167 /// Clean-up after drawing, nothing to be done here.
168 
170 {
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Reset draw statistics.
175 
177 {
178  fOpaqueCnt = 0;
179  fTranspCnt = 0;
180  fAsPixelCnt = 0;
181  fByShapeCnt.clear();
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Update draw stats, for newly drawn 'shape'
186 
188  Short_t lod)
189 {
190  // Update opaque/transparent draw count
191  if (shape.IsTransparent()) {
192  ++fTranspCnt;
193  } else {
194  ++fOpaqueCnt;
195  }
196 
197  if (lod == TGLRnrCtx::kLODPixel) {
198  ++fAsPixelCnt;
199  }
200 
201  // By type only done at higher debug level.
202  if (gDebug>3) {
203  // Update the stats
204  TClass* logIsA = shape.GetLogical()->IsA();
205  std::map<TClass*, UInt_t>::iterator it = fByShapeCnt.find(logIsA);
206  if (it == fByShapeCnt.end()) {
207  //do not need to check insert(.....).second, because it was stats.end() before
208  it = fByShapeCnt.insert(std::make_pair(logIsA, 0u)).first;
209  }
210 
211  it->second++;
212  }
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Output draw stats to Info stream.
217 
219 {
220  if (gDebug>2)
221  {
222  TString out;
223  // Draw/container counts
224  out += Form("Drew scene (%s / %i LOD) - %i (Op %i Trans %i) %i pixel\n",
227  out += Form("\tInner phys nums: physicals=%d, of_interest=%lu, visible=%lu, op=%lu, trans=%lu",
231 
232  // By shape type counts
233  if (gDebug>3)
234  {
235  out += "\n\tStatistics by shape:\n";
236  std::map<TClass*, UInt_t>::const_iterator it = fByShapeCnt.begin();
237  while (it != fByShapeCnt.end()) {
238  out += Form("\t%-20s %u\n", it->first->GetName(), it->second);
239  ++it;
240  }
241  }
242  Info("TGLScene::DumpDrawStats()", "%s",out.Data());
243  }
244 }
245 
246 
247 /** \class TGLScene
248 \ingroup opengl
249 TGLScene provides management and rendering of ROOT's default 3D
250 /object representation as logical and physical shapes.
251 
252 A GL scene is the container for all the viewable objects (shapes)
253 loaded into the viewer. It consists of two main stl::maps containing
254 the TGLLogicalShape and TGLPhysicalShape collections, and interface
255 functions enabling viewers to manage objects in these. The physical
256 shapes defined the placement of copies of the logical shapes - see
257 TGLLogicalShape/TGLPhysicalShape for more information on relationship
258 
259 The scene can be drawn by owning viewer, passing camera, draw style
260 & quality (LOD), clipping etc - see Draw(). The scene can also be
261 drawn for selection in similar fashion - see Select(). The scene
262 keeps track of a single selected physical - which can be modified by
263 viewers.
264 
265 The scene maintains a lazy calculated bounding box for the total
266 scene extents, axis aligned round TGLPhysicalShape shapes.
267 
268 Currently a scene is owned exclusively by one viewer - however it is
269 intended that it could easily be shared by multiple viewers - for
270 efficiency and synchronisation reasons. Hence viewer variant objects
271 camera, clips etc being owned by viewer and passed at draw/select
272 */
273 
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 
279  TGLSceneBase(),
280  fGLCtxIdentity(0),
284 {
285  if (fSceneID == 1)
287 }
288 
289 ////////////////////////////////////////////////////////////////////////////////
290 /// Destroy scene objects
291 
293 {
297  DestroyLogicals();
298  if (fGLCtxIdentity)
301 }
302 
303 /**************************************************************************/
304 // GLCtxIdentity
305 /**************************************************************************/
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 /// Release all GL resources for current context identity.
309 /// Requires iteration over all logical shapes.
310 
312 {
313  if (fGLCtxIdentity == 0) return;
314 
315  if (fGLCtxIdentity->IsValid())
316  {
317  // Purge logical's DLs
318  LogicalShapeMapIt_t lit = fLogicalShapes.begin();
319  while (lit != fLogicalShapes.end()) {
320  lit->second->DLCachePurge();
321  ++lit;
322  }
323  }
324  else
325  {
326  // Drop logical's DLs
327  LogicalShapeMapIt_t lit = fLogicalShapes.begin();
328  while (lit != fLogicalShapes.end()) {
329  lit->second->DLCacheDrop();
330  ++lit;
331  }
332  }
334  fGLCtxIdentity = 0;
335 }
336 
337 /**************************************************************************/
338 // SceneInfo management
339 /**************************************************************************/
340 
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Create a scene-info instance appropriate for this scene class.
344 /// Here we instantiate the inner class TSceneInfo that includes
345 /// camera/clipping specific draw-list containers.
346 
348 {
349  return new TSceneInfo(view, this);
350 }
351 
352 ////////////////////////////////////////////////////////////////////////////////
353 /// Compare 'shape1' and 'shape2' bounding box volumes - return kTRUE if
354 /// 'shape1' bigger than 'shape2'.
355 
357  const TGLPhysicalShape* shape2)
358 {
359  return (shape1->BoundingBox().Volume() > shape2->BoundingBox().Volume());
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 /// Compare 'shape1' and 'shape2' bounding box volumes - return kTRUE if
364 /// 'shape1' bigger than 'shape2'.
365 
367  const TGLPhysicalShape* shape2)
368 {
369  return (shape1->BoundingBox().Diagonal() > shape2->BoundingBox().Diagonal());
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Major change in scene, need to rebuild all-element draw-vector and
374 /// sort it.
375 ///
376 /// Sort the TGLPhysical draw list by shape bounding box diagonal, from
377 /// large to small. This makes dropout of shapes with time limited
378 /// Draw() calls must less noticeable. As this does not use projected
379 /// size it only needs to be done after a scene content change - not
380 /// every time scene drawn (potential camera/projection change).
381 
383 {
384  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
385  if (sinfo == 0 || sinfo->GetScene() != this) {
386  Error("TGLScene::RebuildSceneInfo", "Scene mismatch.");
387  return;
388  }
389 
391 
392  if (sinfo->fShapesOfInterest.capacity() > fPhysicalShapes.size()) {
393  ShapeVec_t foo;
394  foo.reserve(fPhysicalShapes.size());
395  sinfo->fShapesOfInterest.swap(foo);
396  } else {
397  sinfo->fShapesOfInterest.clear();
398  }
399 
401  while (pit != fPhysicalShapes.end())
402  {
403  TGLPhysicalShape * pshp = pit->second;
404  const TGLLogicalShape * lshp = pshp->GetLogical();
405  if (rnrCtx.GetCamera()->OfInterest(pshp->BoundingBox(),
406  lshp->IgnoreSizeForOfInterest()))
407  {
408  sinfo->fShapesOfInterest.push_back(pshp);
409  }
410  ++pit;
411  }
412 
413  std::sort(sinfo->fShapesOfInterest.begin(), sinfo->fShapesOfInterest.end(),
415 
416  sinfo->ClearAfterRebuild();
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// Fill scene-info with information needed for rendering, take into
421 /// account the render-context (viewer state, camera, clipping).
422 /// Here we have to iterate over all the physical shapes and select
423 /// the visible ones. While at it, opaque and transparent shapes are
424 /// divided into two groups.
425 
427 {
428  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
429  if (sinfo == 0 || sinfo->GetScene() != this) {
430  Error("TGLScene::UpdateSceneInfo", "Scene mismatch.");
431  return;
432  }
433 
434  // Clean-up/reset, update of transformation matrices and clipping
435  // planes done in base-class.
437 
438  if (!sinfo->IsVisible())
439  return;
440 
441  sinfo->fVisibleElements.clear();
442 
443  // Check individual physicals, build DrawElementList.
444 
445  Int_t checkCount = 0;
446  Bool_t timerp = rnrCtx.IsStopwatchRunning();
447  sinfo->ResetUpdateTimeouted();
448 
449  for (ShapeVec_i phys=sinfo->fShapesOfInterest.begin();
450  phys!=sinfo->fShapesOfInterest.end();
451  ++phys, ++checkCount)
452  {
453  const TGLPhysicalShape * drawShape = *phys;
454 
455  // TODO: Do small skipping first? Probably cheaper than frustum check
456  // Profile relative costs? The frustum check could be done implicitly
457  // from the LOD as we project all 8 vertices of the BB onto viewport
458 
459  // Work out if we need to draw this shape - assume we do first
460  Bool_t drawNeeded = kTRUE;
461 
462  // Draw test against passed clipping planes.
463  // Do before camera clipping on assumption clip planes remove
464  // more objects.
465  if (sinfo->ClipMode() == TGLSceneInfo::kClipOutside)
466  {
467  // Draw not needed if outside any of the planes.
468  std::vector<TGLPlane>::iterator pi = sinfo->ClipPlanes().begin();
469  while (pi != sinfo->ClipPlanes().end())
470  {
471  if (drawShape->BoundingBox().Overlap(*pi) == Rgl::kOutside)
472  {
473  drawNeeded = kFALSE;
474  break;
475  }
476  ++pi;
477  }
478  }
479  else if (sinfo->ClipMode() == TGLSceneInfo::kClipInside)
480  {
481  // Draw not needed if inside all the planes.
482  std::vector<TGLPlane>::iterator pi = sinfo->ClipPlanes().begin();
483  size_t cnt = 0;
484  while (pi != sinfo->ClipPlanes().end())
485  {
486  Rgl::EOverlap ovlp = drawShape->BoundingBox().Overlap(*pi);
487  if (ovlp == Rgl::kOutside)
488  break;
489  else if (ovlp == Rgl::kInside)
490  ++cnt;
491  ++pi;
492  }
493  if (cnt == sinfo->ClipPlanes().size())
494  drawNeeded = kFALSE;
495  }
496 
497  // Test against camera frustum planes (here mode is Outside
498  // implicitly).
499  if (drawNeeded)
500  {
501  std::vector<TGLPlane>::iterator pi = sinfo->FrustumPlanes().begin();
502  while (pi != sinfo->FrustumPlanes().end())
503  {
504  if (drawShape->BoundingBox().Overlap(*pi) == Rgl::kOutside)
505  {
506  drawNeeded = kFALSE;
507  break;
508  }
509  ++pi;
510  }
511  }
512 
513  // Draw? Then calculate lod and store ...
514  if (drawNeeded)
515  {
516  DrawElement_t de(drawShape);
517  drawShape->CalculateShapeLOD(rnrCtx, de.fPixelSize, de.fPixelLOD);
518  sinfo->fVisibleElements.push_back(de);
519  }
520 
521  // Terminate the traversal if over scene rendering limit.
522  // Only test every 5000 objects as this is somewhat costly.
523  if (timerp && (checkCount % 5000) == 0 && rnrCtx.HasStopwatchTimedOut())
524  {
525  sinfo->UpdateTimeouted();
526  if (rnrCtx.ViewerLOD() == TGLRnrCtx::kLODHigh)
527  Warning("TGLScene::UpdateSceneInfo",
528  "Timeout reached, not all elements processed.");
529  break;
530  }
531  }
532 
533  sinfo->ClearAfterUpdate();
534 
535  // !!! MT Transparents should be sorted by their eye z-coordinate.
536  // Need combined matrices in scene-info to do this.
537  // Even more ... should z-sort contributions from ALL scenes!
538 }
539 
540 ////////////////////////////////////////////////////////////////////////////////
541 /// Setup LOD-dependant values in scene-info.
542 /// We have to perform LOD quantization for all draw-elements.
543 
545 {
546  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
547  if (sinfo == 0 || sinfo->GetScene() != this) {
548  Error("TGLScene::LodifySceneInfo", "Scene mismatch.");
549  return;
550  }
551 
553 
554  sinfo->Lodify(rnrCtx);
555 }
556 
557 
558 /**************************************************************************/
559 // Rendering
560 /**************************************************************************/
561 
562 ////////////////////////////////////////////////////////////////////////////////
563 /// Initialize rendering.
564 /// Pass to base-class where most work is done.
565 /// Check if GL-ctx is shared with the previous one; if not
566 /// wipe display-lists of all logicals.
567 
569 {
570  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
571  if (sinfo == 0 || sinfo->GetScene() != this) {
572  TGLSceneInfo* si = rnrCtx.GetSceneInfo();
573  Error("TGLScene::PreDraw", "%s", Form("SceneInfo mismatch (0x%lx, '%s').",
574  (ULong_t)si, si ? si->IsA()->GetName() : "<>"));
575  return;
576  }
577 
578  // Setup ctx, check if Update/Lodify needed.
579  TGLSceneBase::PreDraw(rnrCtx);
580 
581  TGLContextIdentity* cid = rnrCtx.GetGLCtxIdentity();
582  if (cid != fGLCtxIdentity)
583  {
585  fGLCtxIdentity = cid;
587  }
588  else
589  {
592  {
593  // Clear logical's DLs
594  LogicalShapeMapIt_t lit = fLogicalShapes.begin();
595  while (lit != fLogicalShapes.end()) {
596  lit->second->DLCacheClear();
597  ++lit;
598  }
599  }
600  }
603 
604  sinfo->PreDraw();
605 
606  // Reset-scene-info counters.
607  sinfo->ResetDrawStats();
608 }
609 
610 ////////////////////////////////////////////////////////////////////////////////
611 /// Render opaque elements.
612 
614 {
615  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
616  if (!sinfo->fOpaqueElements.empty())
617  RenderAllPasses(rnrCtx, sinfo->fOpaqueElements, kTRUE);
618 }
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 /// Render transparent elements.
622 
624 {
625  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
626  if (!sinfo->fTranspElements.empty())
627  RenderAllPasses(rnrCtx, sinfo->fTranspElements, kTRUE);
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Render selected opaque elements.
632 
634 {
635  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
636  if ( ! sinfo->fSelOpaqueElements.empty())
637  RenderAllPasses(rnrCtx, sinfo->fSelOpaqueElements, kFALSE);
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Render selected transparent elements.
642 
644 {
645  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
646  if (!sinfo->fSelTranspElements.empty())
647  RenderAllPasses(rnrCtx, sinfo->fSelTranspElements, kFALSE);
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////
651 /// Render selected opaque elements for highlight.
652 
654 {
655  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
656  if ( ! sinfo->fSelOpaqueElements.empty())
657  RenderHighlight(rnrCtx, sinfo->fSelOpaqueElements);
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 /// Render selected transparent elements for highlight.
662 
664 {
665  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
666  if (!sinfo->fSelTranspElements.empty())
667  RenderHighlight(rnrCtx, sinfo->fSelTranspElements);
668 }
669 
670 ////////////////////////////////////////////////////////////////////////////////
671 
673  DrawElementPtrVec_t& elVec)
674 {
675  DrawElementPtrVec_t svec(1);
676 
677  glEnable(GL_STENCIL_TEST);
678  for (DrawElementPtrVec_i i = elVec.begin(); i != elVec.end(); ++i)
679  {
680  svec[0] = *i;
681 
682  glStencilFunc(GL_ALWAYS, 0x1, 0x1);
683  glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
684  glClear(GL_STENCIL_BUFFER_BIT);
685 
686  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
687 
688  RenderAllPasses(rnrCtx, svec, kFALSE);
689 
690  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
691 
692  glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
693  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
694 
695  rnrCtx.SetHighlightOutline(kTRUE);
696  RenderAllPasses(rnrCtx, svec, kFALSE);
697  rnrCtx.SetHighlightOutline(kFALSE);
698  }
699  glDisable(GL_STENCIL_TEST);
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Called after the rendering is finished.
704 /// In debug mode draw statistics is dumped.
705 /// Parent's PostDraw is called for GL cleanup.
706 
708 {
709  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
710 
711  if (gDebug)
712  sinfo->DumpDrawStats();
713 
714  sinfo->PostDraw();
715 
716  TGLSceneBase::PostDraw(rnrCtx);
717 }
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// Do full rendering of scene.
721 ///
722 /// First draw the opaques, then the transparents. For each we do
723 /// the number of passes required by draw mode and clipping setup.
724 
726  DrawElementPtrVec_t& elVec,
727  Bool_t check_timeout)
728 {
729  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
730  assert(sinfo != 0);
731 
732  Short_t sceneStyle = rnrCtx.SceneStyle();
733 
734  // Setup GL for current draw style - fill, wireframe, outline
735  Int_t reqPasses = 1; // default
736 
737  Short_t rnrPass[2];
738  rnrPass[0] = rnrPass[1] = TGLRnrCtx::kPassUndef;
739 
740  switch (sceneStyle)
741  {
742  case TGLRnrCtx::kFill:
743  case TGLRnrCtx::kOutline:
744  {
745  glEnable(GL_LIGHTING);
746  if (sinfo->ShouldClip())
747  {
748  // Clip object - two sided lighting, two side polygons, don't cull (BACK) faces
749  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
750  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
751  glDisable(GL_CULL_FACE);
752  }
753  // No clip - default single side lighting,
754  // front polygons, cull (BACK) faces ok
755  if (sceneStyle == TGLRnrCtx::kOutline && ! (rnrCtx.Selection() || rnrCtx.Highlight()))
756  {
757  reqPasses = 2; // Outline needs two full draws
758  rnrPass[0] = TGLRnrCtx::kPassOutlineFill;
759  rnrPass[1] = TGLRnrCtx::kPassOutlineLine;
760  }
761  else
762  {
763  rnrPass[0] = TGLRnrCtx::kPassFill;
764  }
765  break;
766  }
768  {
769  rnrPass[0] = TGLRnrCtx::kPassWireFrame;
770  glDisable(GL_LIGHTING);
771  glDisable(GL_CULL_FACE);
772  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
773  break;
774  }
775  default:
776  {
777  assert(kFALSE);
778  }
779  }
780 
781  for (Int_t i = 0; i < reqPasses; ++i)
782  {
783  // For outline two full draws (fill + wireframe) required.
784  // Do it this way to avoid costly GL state swaps on per drawable basis
785 
786  Short_t pass = rnrPass[i];
787  rnrCtx.SetDrawPass(pass);
788 
789  if (pass == TGLRnrCtx::kPassOutlineFill)
790  {
791  // First pass - filled polygons
792  glEnable(GL_POLYGON_OFFSET_FILL);
793  glPolygonOffset(0.5f, 0.5f);
794  }
795  else if (pass == TGLRnrCtx::kPassOutlineLine)
796  {
797  // Second pass - outline (wireframe)
799  glDisable(GL_POLYGON_OFFSET_FILL);
800  glDisable(GL_LIGHTING);
801 
802  // We are only showing back faces with clipping as a
803  // better solution than completely invisible faces.
804  // *Could* cull back faces and only outline on front like this:
805  // glEnable(GL_CULL_FACE);
806  // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
807  // However this means clipped back edges not shown - so do inside and out....
808  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
809  }
810  else if (pass == TGLRnrCtx::kPassWireFrame)
811  {
813  }
814 
815  // If no clip object no plane sets to extract/pass
816  if ( ! sinfo->ShouldClip())
817  {
818  RenderElements(rnrCtx, elVec, check_timeout);
819  }
820  else
821  {
822  // Get the clip plane set from the clipping object
823  TGLPlaneSet_t & planeSet = sinfo->ClipPlanes();
824 
825  if (gDebug > 3)
826  {
827  Info("TGLScene::RenderAllPasses()",
828  "%ld active clip planes", (Long_t)planeSet.size());
829  }
830  // Limit to smaller of plane set size or GL implementation plane support
831  Int_t maxGLPlanes;
832  glGetIntegerv(GL_MAX_CLIP_PLANES, &maxGLPlanes);
833  UInt_t maxPlanes = maxGLPlanes;
834  UInt_t planeInd;
835  if (planeSet.size() < maxPlanes) {
836  maxPlanes = planeSet.size();
837  }
838 
839  if (sinfo->ClipMode() == TGLSceneInfo::kClipOutside)
840  {
841  // Clip away scene outside of the clip object.
842  // Load all clip planes (up to max) at once.
843  for (UInt_t ii=0; ii<maxPlanes; ii++) {
844  glClipPlane(GL_CLIP_PLANE0+ii, planeSet[ii].CArr());
845  glEnable(GL_CLIP_PLANE0+ii);
846  }
847 
848  // Draw scene once with full time slot, physicals have been
849  // clipped during UpdateSceneInfo, so no need to repeat that.
850  RenderElements(rnrCtx, elVec, check_timeout);
851  }
852  else
853  {
854  // Clip away scene inside of the clip object.
855  // This requires number-of-clip-planes passes and can not
856  // be entirely pre-computed (non-relevant planes are removed).
857  std::vector<TGLPlane> activePlanes;
858  for (planeInd=0; planeInd<maxPlanes; planeInd++)
859  {
860  activePlanes.push_back(planeSet[planeInd]);
861  TGLPlane& p = activePlanes.back();
862  p.Negate();
863  glClipPlane(GL_CLIP_PLANE0+planeInd, p.CArr());
864  glEnable(GL_CLIP_PLANE0+planeInd);
865 
866  // Draw scene with active planes, allocating fraction of time
867  // for total planes.
868  RenderElements(rnrCtx, elVec, check_timeout, &activePlanes);
869 
870  p.Negate();
871  glClipPlane(GL_CLIP_PLANE0+planeInd, p.CArr());
872  }
873  }
874  // Ensure all clip planes turned off again
875  for (planeInd=0; planeInd<maxPlanes; planeInd++) {
876  glDisable(GL_CLIP_PLANE0+planeInd);
877  }
878  }
879  } // end for reqPasses
880 
881  // Reset gl modes to defaults
882  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
883  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
884  glEnable(GL_CULL_FACE);
885  glEnable(GL_LIGHTING);
886 }
887 
888 ////////////////////////////////////////////////////////////////////////////////
889 /// Render DrawElements in elementVec with given timeout.
890 /// If clipPlanes is non-zero, test each element against its
891 /// clipping planes.
892 
894  DrawElementPtrVec_t& elVec,
895  Bool_t check_timeout,
896  const TGLPlaneSet_t* clipPlanes)
897 {
898  TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
899  assert(sinfo != 0);
900 
901  Int_t drawCount = 0;
902 
903  for (DrawElementPtrVec_i i = elVec.begin(); i != elVec.end(); ++i)
904  {
905  const TGLPhysicalShape * drawShape = (*i)->fPhysical;
906 
907  Bool_t drawNeeded = kTRUE;
908 
909  // If clipping planes are passed as argument, we test against them.
910  if (clipPlanes && IsOutside(drawShape->BoundingBox(), *clipPlanes))
911  drawNeeded = kFALSE;
912 
913  // Draw?
914  if (drawNeeded)
915  {
916  rnrCtx.SetShapeLOD((*i)->fFinalLOD);
917  rnrCtx.SetShapePixSize((*i)->fPixelSize);
918  glPushName(drawShape->ID());
919  drawShape->Draw(rnrCtx);
920  glPopName();
921  ++drawCount;
922  sinfo->UpdateDrawStats(*drawShape, rnrCtx.ShapeLOD());
923  }
924 
925  // Terminate the draw if over opaque fraction timeout.
926  // Only test every 2000 objects as this is somewhat costly.
927  if (check_timeout && (drawCount % 2000) == 0 &&
928  rnrCtx.HasStopwatchTimedOut())
929  {
930  if (rnrCtx.ViewerLOD() == TGLRnrCtx::kLODHigh)
931  Warning("TGLScene::RenderElements",
932  "Timeout reached, not all elements rendered.");
933  break;
934  }
935  }
936 }
937 
938 
939 /**************************************************************************/
940 // Selection
941 /**************************************************************************/
942 
943 ////////////////////////////////////////////////////////////////////////////////
944 /// Process selection record rec.
945 /// 'curIdx' is the item position where the scene should start
946 /// its processing.
947 /// Return TRUE if an object has been identified or FALSE otherwise.
948 /// The scene-info member of the record is already set by the caller.
949 
951 {
952  if (curIdx >= rec.GetN())
953  return kFALSE;
954 
955  TGLPhysicalShape* pshp = FindPhysical(rec.GetItem(curIdx));
956  if (pshp)
957  {
958  rec.SetTransparent(pshp->IsTransparent());
959  rec.SetPhysShape(pshp);
960  rec.SetLogShape(const_cast<TGLLogicalShape*>(pshp->GetLogical()));
961  rec.SetObject(pshp->GetLogical()->GetExternal());
962  rec.SetSpecific(0);
963  return kTRUE;
964  }
965  return kFALSE;
966 }
967 
968 
969 /**************************************************************************/
970 // Bounding-box
971 /**************************************************************************/
972 
973 ////////////////////////////////////////////////////////////////////////////////
974 /// Encapsulates all physical shapes bounding box with axes aligned box.
975 /// Validity checked in the base-class.
976 
978 {
979  Double_t xMin, xMax, yMin, yMax, zMin, zMax;
980  xMin = xMax = yMin = yMax = zMin = zMax = 0.0;
981  PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
982  const TGLPhysicalShape * physicalShape;
983  while (physicalShapeIt != fPhysicalShapes.end())
984  {
985  physicalShape = physicalShapeIt->second;
986  if (!physicalShape)
987  {
988  assert(kFALSE);
989  continue;
990  }
991  const TGLBoundingBox& box = physicalShape->BoundingBox();
992  if (physicalShapeIt == fPhysicalShapes.begin()) {
993  xMin = box.XMin(); xMax = box.XMax();
994  yMin = box.YMin(); yMax = box.YMax();
995  zMin = box.ZMin(); zMax = box.ZMax();
996  } else {
997  if (box.XMin() < xMin) { xMin = box.XMin(); }
998  if (box.XMax() > xMax) { xMax = box.XMax(); }
999  if (box.YMin() < yMin) { yMin = box.YMin(); }
1000  if (box.YMax() > yMax) { yMax = box.YMax(); }
1001  if (box.ZMin() < zMin) { zMin = box.ZMin(); }
1002  if (box.ZMax() > zMax) { zMax = box.ZMax(); }
1003  }
1004  ++physicalShapeIt;
1005  }
1006  fBoundingBox.SetAligned(TGLVertex3(xMin,yMin,zMin), TGLVertex3(xMax,yMax,zMax));
1008 }
1009 
1010 /**************************************************************************/
1011 // Logical shapes
1012 /**************************************************************************/
1013 
1014 ////////////////////////////////////////////////////////////////////////////////
1015 /// Adopt dynamically created logical 'shape' - add to internal map
1016 /// and take responsibility for deleting.
1017 
1019 {
1020  if (fLock != kModifyLock) {
1021  Error("TGLScene::AdoptLogical", "expected ModifyLock");
1022  return;
1023  }
1024 
1025  shape.fScene = this;
1026  fLogicalShapes.insert(LogicalShapeMapValueType_t(shape.ID(), &shape));
1027 }
1028 
1029 ////////////////////////////////////////////////////////////////////////////////
1030 /// Destroy logical shape defined by unique 'ID'.
1031 /// Returns kTRUE if found/destroyed - kFALSE otherwise.
1032 ///
1033 /// If mustFind is true, an error is reported if the logical is not
1034 /// found.
1035 
1037 {
1038  if (fLock != kModifyLock) {
1039  Error("TGLScene::DestroyLogical", "expected ModifyLock");
1040  return kFALSE;
1041  }
1042 
1043  LogicalShapeMapIt_t lit = fLogicalShapes.find(logid);
1044 
1045  if (lit == fLogicalShapes.end()) {
1046  if (mustFind)
1047  Error("TGLScene::DestroyLogical", "logical not found in map.");
1048  return kFALSE;
1049  }
1050 
1051  TGLLogicalShape * logical = lit->second;
1052  UInt_t phid;
1053  while ((phid = logical->UnrefFirstPhysical()) != 0)
1054  {
1055  PhysicalShapeMapIt_t pit = fPhysicalShapes.find(phid);
1056  if (pit != fPhysicalShapes.end())
1058  else
1059  Warning("TGLScene::DestroyLogical", "an attached physical not found in map.");
1060  }
1061  assert(logical->Ref() == 0);
1062  fLogicalShapes.erase(lit);
1063  delete logical;
1065  IncTimeStamp();
1066  return kTRUE;
1067 }
1068 
1069 ////////////////////////////////////////////////////////////////////////////////
1070 /// Destroy all logical shapes in scene.
1071 /// Return number of destroyed logicals.
1072 
1074 {
1075  if (fLock != kModifyLock) {
1076  Error("TGLScene::DestroyLogicals", "expected ModifyLock");
1077  return 0;
1078  }
1079 
1080  Int_t count = 0;
1081  LogicalShapeMapIt_t logicalShapeIt = fLogicalShapes.begin();
1082  const TGLLogicalShape * logicalShape;
1083  while (logicalShapeIt != fLogicalShapes.end()) {
1084  logicalShape = logicalShapeIt->second;
1085  if (logicalShape) {
1086  if (logicalShape->Ref() == 0) {
1087  fLogicalShapes.erase(logicalShapeIt++);
1088  delete logicalShape;
1089  ++count;
1090  continue;
1091  } else {
1092  assert(kFALSE);
1093  }
1094  } else {
1095  assert(kFALSE);
1096  }
1097  ++logicalShapeIt;
1098  }
1099 
1100  return count;
1101 }
1102 
1103 ////////////////////////////////////////////////////////////////////////////////
1104 /// Find and return logical shape identified by unique logid.
1105 /// Returns 0 if not found.
1106 
1108 {
1109  LogicalShapeMapCIt_t lit = fLogicalShapes.find(logid);
1110  if (lit != fLogicalShapes.end()) {
1111  return lit->second;
1112  } else {
1113  if (fInSmartRefresh)
1114  return FindLogicalSmartRefresh(logid);
1115  else
1116  return 0;
1117  }
1118 }
1119 
1120 
1121 /**************************************************************************/
1122 // Physical shapes
1123 /**************************************************************************/
1124 
1125 ////////////////////////////////////////////////////////////////////////////////
1126 /// Adopt dynamically created physical 'shape' - add to internal map and take
1127 /// responsibility for deleting
1128 
1130 {
1131  if (fLock != kModifyLock) {
1132  Error("TGLScene::AdoptPhysical", "expected ModifyLock");
1133  return;
1134  }
1135  // TODO: Very inefficient check - disable
1136  assert(fPhysicalShapes.find(shape.ID()) == fPhysicalShapes.end());
1137 
1138  fPhysicalShapes.insert(PhysicalShapeMapValueType_t(shape.ID(), &shape));
1139 
1141  IncTimeStamp();
1142 }
1143 
1144 ////////////////////////////////////////////////////////////////////////////////
1145 /// Virtual function to destroy a physical. Sub-classes might have
1146 /// special checks to perform.
1147 /// Caller should also invalidate the draw-list.
1148 
1150 {
1151  delete pit->second;
1152  fPhysicalShapes.erase(pit);
1153 }
1154 
1155 ////////////////////////////////////////////////////////////////////////////////
1156 /// Destroy physical shape defined by unique 'ID'.
1157 /// Returns kTRUE if found/destroyed - kFALSE otherwise.
1158 
1160 {
1161  if (fLock != kModifyLock) {
1162  Error("TGLScene::DestroyPhysical", "expected ModifyLock.");
1163  return kFALSE;
1164  }
1165 
1166  PhysicalShapeMapIt_t pit = fPhysicalShapes.find(phid);
1167 
1168  if (pit == fPhysicalShapes.end()) {
1169  Error("TGLScene::DestroyPhysical::UpdatePhysical", "physical not found.");
1170  return kFALSE;
1171  }
1172 
1174 
1176 
1177  return kTRUE;
1178 }
1179 
1180 ////////////////////////////////////////////////////////////////////////////////
1181 /// Destroy physical shapes.
1182 
1184 {
1185  if (fLock != kModifyLock) {
1186  Error("TGLScene::DestroyPhysicals", "expected ModifyLock");
1187  return 0;
1188  }
1189 
1190  // Loop over logicals -- it is much more efficient that way.
1191 
1192  UInt_t count = 0;
1193 
1194  LogicalShapeMapIt_t lit = fLogicalShapes.begin();
1195  while (lit != fLogicalShapes.end())
1196  {
1197  TGLLogicalShape *lshp = lit->second;
1198  if (lshp && lshp->Ref() != 0)
1199  {
1200  count += lshp->Ref();
1201  lshp->DestroyPhysicals();
1202  }
1203  ++lit;
1204  }
1205 
1206  assert (count == fPhysicalShapes.size());
1207  fPhysicalShapes.clear();
1208 
1209  if (count > 0) {
1211  IncTimeStamp();
1212  }
1213 
1214  return count;
1215 }
1216 
1217 ////////////////////////////////////////////////////////////////////////////////
1218 /// Find and return physical shape identified by unique 'ID'.
1219 /// Returns 0 if not found.
1220 
1222 {
1223  PhysicalShapeMapCIt_t pit = fPhysicalShapes.find(phid);
1224  return (pit != fPhysicalShapes.end()) ? pit->second : 0;
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// Returns the maximum used physical id.
1229 /// Returns 0 if empty.
1230 
1232 {
1233  if (fPhysicalShapes.empty()) return 0;
1234  return (--fPhysicalShapes.end())->first;
1235 }
1236 
1237 
1238 /**************************************************************************/
1239 // Update methods
1240 /**************************************************************************/
1241 
1242 ////////////////////////////////////////////////////////////////////////////////
1243 /// Put scene in update mode, return true if lock acquired.
1244 
1246 {
1247  Bool_t ok = TakeLock(kModifyLock);
1248  return ok;
1249 }
1250 
1251 ////////////////////////////////////////////////////////////////////////////////
1252 /// Exit scene update mode.
1253 ///
1254 /// If sceneChanged is true (default), the scene timestamp is
1255 /// increased and basic draw-lists etc will be rebuild on next draw
1256 /// request. If you only changed colors or some other visual
1257 /// parameters that do not affect object bounding-box or
1258 /// transformation matrix, you can set it to false.
1259 ///
1260 /// If updateViewers is true (default), the viewers using this scene
1261 /// will be tagged as changed. If sceneChanged is true the
1262 /// updateViewers should be true as well, unless you take care of
1263 /// the viewers elsewhere or in some other way.
1264 
1265 void TGLScene::EndUpdate(Bool_t minorChange, Bool_t sceneChanged, Bool_t updateViewers)
1266 {
1267  if (minorChange)
1268  IncMinorStamp();
1269 
1270  if (sceneChanged)
1271  IncTimeStamp();
1272 
1274 
1275  if (updateViewers)
1277 }
1278 
1279 ////////////////////////////////////////////////////////////////////////////////
1280 /// Drop display-lists for the logical (assume TGLObject/direct rendering).
1281 /// Re-calculate the bounding box (also for all physicals).
1282 
1284 {
1285  if (fLock != kModifyLock) {
1286  Error("TGLScene::UpdateLogical", "expected ModifyLock");
1287  return;
1288  }
1289 
1290  TGLLogicalShape* log = FindLogical(logid);
1291 
1292  if (log == 0) {
1293  Error("TGLScene::UpdateLogical", "logical not found");
1294  return;
1295  }
1296 
1297  log->DLCacheClear();
1298  log->UpdateBoundingBox();
1299 }
1300 
1301 ////////////////////////////////////////////////////////////////////////////////
1302 /// Reposition/recolor physical shape.
1303 
1305 {
1306  if (fLock != kModifyLock) {
1307  Error("TGLScene::UpdatePhysical", "expected ModifyLock");
1308  return;
1309  }
1310 
1311  TGLPhysicalShape* phys = FindPhysical(phid);
1312 
1313  if (phys == 0) {
1314  Error("TGLScene::UpdatePhysical", "physical not found");
1315  return;
1316  }
1317 
1318  if (trans) phys->SetTransform(trans);
1319  if (col) phys->SetDiffuseColor(col);
1320 }
1321 
1322 ////////////////////////////////////////////////////////////////////////////////
1323 /// Reposition/recolor physical shape.
1324 
1325 void TGLScene::UpdatePhysical(UInt_t phid, Double_t* trans, Color_t cidx, UChar_t transp)
1326 {
1327  if (fLock != kModifyLock) {
1328  Error("TGLScene::UpdatePhysical", "expected ModifyLock");
1329  return;
1330  }
1331 
1332  TGLPhysicalShape* phys = FindPhysical(phid);
1333 
1334  if (phys == 0) {
1335  Error("TGLScene::UpdatePhysical", "physical not found");
1336  return;
1337  }
1338 
1339  if (trans)
1340  phys->SetTransform(trans);
1341  if (cidx >= 0) {
1342  Float_t rgba[4];
1343  RGBAFromColorIdx(rgba, cidx, transp);
1344  phys->SetDiffuseColor(rgba);
1345  }
1346 }
1347 
1348 ////////////////////////////////////////////////////////////////////////////////
1349 /// Reposition/recolor physical for given logical (assume TGLObject and
1350 /// a single physical).
1351 
1353 {
1354  if (fLock != kModifyLock) {
1355  Error("TGLScene::UpdatePhysioLogical", "expected ModifyLock");
1356  return;
1357  }
1358 
1359  TGLLogicalShape* log = FindLogical(logid);
1360 
1361  if (log == 0) {
1362  Error("TGLScene::UpdatePhysioLogical", "logical not found");
1363  return;
1364  }
1365 
1366  if (log->Ref() != 1) {
1367  Warning("TGLScene::UpdatePhysioLogical", "expecting a single physical (%d).", log->Ref());
1368  }
1369 
1370  TGLPhysicalShape* phys = log->fFirstPhysical;
1371  if (trans) phys->SetTransform(trans);
1372  if (col) phys->SetDiffuseColor(col);
1373 }
1374 
1375 ////////////////////////////////////////////////////////////////////////////////
1376 /// Reposition/recolor physical for given logical (assume TGLObject and
1377 /// a single physical).
1378 
1380 {
1381  if (fLock != kModifyLock) {
1382  Error("TGLScene::UpdatePhysioLogical", "expected ModifyLock");
1383  return;
1384  }
1385 
1386  TGLLogicalShape* log = FindLogical(logid);
1387 
1388  if (log == 0) {
1389  Error("TGLScene::UpdatePhysioLogical", "logical not found");
1390  return;
1391  }
1392 
1393  if (log->Ref() != 1) {
1394  Warning("TGLScene::UpdatePhysioLogical", "expecting a single physical (%d).", log->Ref());
1395  }
1396 
1397  TGLPhysicalShape* phys = log->fFirstPhysical;
1398  if (trans)
1399  phys->SetTransform(trans);
1400  if (cidx >= 0) {
1401  Float_t rgba[4];
1402  RGBAFromColorIdx(rgba, cidx, transp);
1403  phys->SetDiffuseColor(rgba);
1404  }
1405 }
1406 
1407 
1408 /**************************************************************************/
1409 // Smart refresh
1410 /**************************************************************************/
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// Moves logicals that support smart-refresh to intermediate cache.
1414 /// Destroys the others and returns the number of destroyed ones.
1415 
1417 {
1419  // Remove all logicals that don't survive a refresh.
1420  UInt_t count = 0;
1422  while (i != fSmartRefreshCache.end()) {
1423  if (i->second->KeepDuringSmartRefresh() == kFALSE) {
1424  LogicalShapeMapIt_t j = i++;
1425  delete j->second;
1426  fSmartRefreshCache.erase(j);
1427  ++count;
1428  } else {
1429  ++i;
1430  }
1431  }
1433  return count;
1434 }
1435 
1436 ////////////////////////////////////////////////////////////////////////////////
1437 /// Wipes logicals in refresh-cache.
1438 
1440 {
1442 
1444  while (i != fSmartRefreshCache.end()) {
1445  delete i->second;
1446  ++i;
1447  }
1448  fSmartRefreshCache.clear();
1449 }
1450 
1451 ////////////////////////////////////////////////////////////////////////////////
1452 /// Find and return logical shape identified by unique 'ID' in refresh-cache.
1453 /// Returns 0 if not found.
1454 
1456 {
1458  if (it != fSmartRefreshCache.end())
1459  {
1460  TGLLogicalShape* l_shape = it->second;
1461  fSmartRefreshCache.erase(it);
1462  if (l_shape->IsA() != TGLObject::GetGLRenderer(ID->IsA()))
1463  {
1464  Warning("TGLScene::FindLogicalSmartRefresh", "Wrong renderer-type found in cache.");
1465  delete l_shape;
1466  return 0;
1467  }
1468  // printf("TGLScene::SmartRefresh found cached: %p '%s' [%s] for %p\n",
1469  // l_shape, l_shape->GetExternal()->GetName(),
1470  // l_shape->GetExternal()->IsA()->GetName(), (void*) ID);
1471  LogicalShapeMap_t* lsm = const_cast<LogicalShapeMap_t*>(&fLogicalShapes);
1472  lsm->insert(LogicalShapeMapValueType_t(l_shape->ID(), l_shape));
1473  l_shape->DLCacheClear();
1474  l_shape->UpdateBoundingBox();
1475  return l_shape;
1476  } else {
1477  return 0;
1478  }
1479 }
1480 
1481 
1482 /**************************************************************************/
1483 // Helpers
1484 /**************************************************************************/
1485 
1486 ////////////////////////////////////////////////////////////////////////////////
1487 /// Return memory cost of scene.
1488 /// Warning: NOT CORRECT at present - doesn't correctly calculate size.
1489 /// of logical shapes with dynamic internal contents.
1490 
1492 {
1493  UInt_t size = sizeof(*this);
1494 
1495  printf("Size: Scene Only %u\n", size);
1496 
1497  LogicalShapeMapCIt_t logicalShapeIt = fLogicalShapes.begin();
1498  const TGLLogicalShape * logicalShape;
1499  while (logicalShapeIt != fLogicalShapes.end()) {
1500  logicalShape = logicalShapeIt->second;
1501  size += sizeof(*logicalShape);
1502  ++logicalShapeIt;
1503  }
1504 
1505  printf("Size: Scene + Logical Shapes %u\n", size);
1506 
1507  PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
1508  const TGLPhysicalShape * physicalShape;
1509  while (physicalShapeIt != fPhysicalShapes.end()) {
1510  physicalShape = physicalShapeIt->second;
1511  size += sizeof(*physicalShape);
1512  ++physicalShapeIt;
1513  }
1514 
1515  printf("Size: Scene + Logical Shapes + Physical Shapes %u\n", size);
1516 
1517  return size;
1518 }
1519 
1520 ////////////////////////////////////////////////////////////////////////////////
1521 /// Print sizes of logical and physical-shape maps.
1522 
1524 {
1525  printf("Scene: %u Logicals / %u Physicals\n",
1526  (UInt_t) fLogicalShapes.size(), (UInt_t) fPhysicalShapes.size());
1527 }
1528 
1529 ////////////////////////////////////////////////////////////////////////////////
1530 /// Fill rgba color from ROOT color-index ci and transparency (0->100).
1531 
1533 {
1534  TColor* c = gROOT->GetColor(ci);
1535  if(c) c->GetRGB(rgba[0], rgba[1], rgba[2]);
1536  else rgba[0] = rgba[1] = rgba[2] = 0.5;
1537  rgba[3] = 1.0f - transp/100.0f;
1538 }
1539 
1540 ////////////////////////////////////////////////////////////////////////////////
1541 /// Check if box is outside of all planes.
1542 
1544  const TGLPlaneSet_t & planes)
1545 {
1546  for (TGLPlaneSet_ci p=planes.begin(); p!=planes.end(); ++p)
1547  if (box.Overlap(*p) == Rgl::kOutside)
1548  return kTRUE;
1549  return kFALSE;
1550 }
void SetAligned(const TGLVertex3 &lowVertex, const TGLVertex3 &highVertex)
Set ALIGNED box from two low/high vertices.
Bool_t Highlight() const
Definition: TGLRnrCtx.h:218
DrawElementPtrVec_t fTranspElements
Definition: TGLScene.h:96
ShapeVec_t::iterator ShapeVec_i
Definition: TGLScene.h:75
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition: TGLRnrCtx.h:40
Double_t ZMax() const
std::vector< DrawElement_t > DrawElementVec_t
Definition: TGLScene.h:67
static Bool_t ComparePhysicalVolumes(const TGLPhysicalShape *shape1, const TGLPhysicalShape *shape2)
Compare &#39;shape1&#39; and &#39;shape2&#39; bounding box volumes - return kTRUE if &#39;shape1&#39; bigger than &#39;shape2&#39;...
Definition: TGLScene.cxx:356
virtual void EndUpdate(Bool_t minorChange=kTRUE, Bool_t sceneChanged=kTRUE, Bool_t updateViewers=kTRUE)
Exit scene update mode.
Definition: TGLScene.cxx:1265
virtual void UpdatePhysioLogical(TObject *logid, Double_t *trans, UChar_t *col)
Reposition/recolor physical for given logical (assume TGLObject and a single physical).
Definition: TGLScene.cxx:1352
std::map< TObject *, TGLLogicalShape * > LogicalShapeMap_t
Definition: TGLScene.h:43
static constexpr double pi
Bool_t ReleaseLock(ELock lock) const
Release current lock, make sure it the same as the &#39;lock&#39; argument.
Definition: TGLLockable.cxx:51
TGLLogicalShape * FindLogicalSmartRefresh(TObject *ID) const
Find and return logical shape identified by unique &#39;ID&#39; in refresh-cache.
Definition: TGLScene.cxx:1455
virtual ~TGLScene()
Destroy scene objects.
Definition: TGLScene.cxx:292
void IncTimeStamp()
Definition: TGLSceneBase.h:114
LogicalShapeMap_t::iterator LogicalShapeMapIt_t
Definition: TGLScene.h:45
float Float_t
Definition: RtypesCore.h:53
PhysicalShapeMap_t::value_type PhysicalShapeMapValueType_t
Definition: TGLScene.h:50
Bool_t Selection() const
Definition: TGLRnrCtx.h:222
virtual void RenderTransp(TGLRnrCtx &rnrCtx)
Render transparent elements.
Definition: TGLScene.cxx:623
void ClearDrawElementVec(DrawElementVec_t &vec, Int_t maxSize)
Clear given vec and if it grew too large compared to the size of shape-of-interest also resize it...
Definition: TGLScene.cxx:68
static Bool_t ComparePhysicalDiagonals(const TGLPhysicalShape *shape1, const TGLPhysicalShape *shape2)
Compare &#39;shape1&#39; and &#39;shape2&#39; bounding box volumes - return kTRUE if &#39;shape1&#39; bigger than &#39;shape2&#39;...
Definition: TGLScene.cxx:366
virtual ~TSceneInfo()
Destructor.
Definition: TGLScene.cxx:60
Identifier of a shared GL-context.
Definition: TGLContext.h:80
void SetPhysShape(TGLPhysicalShape *pshp)
std::vector< TGLPlane >::const_iterator TGLPlaneSet_ci
Definition: TGLUtil.h:572
virtual void RenderSelOpaqueForHighlight(TGLRnrCtx &rnrCtx)
Render selected opaque elements for highlight.
Definition: TGLScene.cxx:653
Scene base-class – provides basic interface expected by the TGLViewer or its sub-classes: ...
Definition: TGLSceneBase.h:32
void ResetUpdateTimeouted()
Definition: TGLSceneInfo.h:155
#define gROOT
Definition: TROOT.h:402
virtual void UpdateLogical(TObject *logid)
Drop display-lists for the logical (assume TGLObject/direct rendering).
Definition: TGLScene.cxx:1283
virtual void RenderOpaque(TGLRnrCtx &rnrCtx)
Render opaque elements.
Definition: TGLScene.cxx:613
static void SetEnvDefaults()
TGLSceneBase * GetScene() const
Definition: TGLSceneInfo.h:83
PhysicalShapeMap_t::const_iterator PhysicalShapeMapCIt_t
Definition: TGLScene.h:52
Basic string class.
Definition: TString.h:125
Double_t YMax() const
UInt_t fSceneID
Definition: TGLSceneBase.h:41
void DestroyPhysicals()
Destroy all physicals attached to this logical.
TGLSceneInfo * GetSceneInfo()
Definition: TGLRnrCtx.h:158
Double_t XMin() const
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
LogicalShapeMap_t fSmartRefreshCache
Definition: TGLScene.h:138
LogicalShapeMap_t::value_type LogicalShapeMapValueType_t
Definition: TGLScene.h:44
Bool_t OfInterest(const TGLBoundingBox &box, Bool_t ignoreSize) const
Calculate if the an object defined by world frame bounding box is &#39;of interest&#39; to the camera...
Definition: TGLCamera.cxx:578
virtual UInt_t GetMaxPhysicalID()
Returns the maximum used physical id.
Definition: TGLScene.cxx:1231
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition: TColor.h:50
TGLBoundingBox fBoundingBox
Definition: TGLSceneBase.h:55
virtual Bool_t ResolveSelectRecord(TGLSelectRecord &rec, Int_t curIdx)
Process selection record rec.
Definition: TGLScene.cxx:950
void SetShapeLOD(Short_t LOD)
Definition: TGLRnrCtx.h:178
void ClearAfterUpdate()
Clear DrawElementPtrVectors and optionally resize them so that they don&#39;t take more space then requir...
Definition: TGLScene.cxx:113
TGLContextIdentity * GetGLCtxIdentity() const
Definition: TGLRnrCtx.h:254
LogicalShapeMap_t fLogicalShapes
Definition: TGLScene.h:127
Base class for GL viewers.
Definition: TGLViewerBase.h:36
Concrete physical shape - a GL drawable.
PhysicalShapeMap_t::iterator PhysicalShapeMapIt_t
Definition: TGLScene.h:51
virtual void RenderSelTranspForHighlight(TGLRnrCtx &rnrCtx)
Render selected transparent elements for highlight.
Definition: TGLScene.cxx:663
virtual TSceneInfo * CreateSceneInfo(TGLViewerBase *view)
Create a scene-info instance appropriate for this scene class.
Definition: TGLScene.cxx:347
TGLScene * fScene
Shape&#39;s bounding box.
virtual TGLLogicalShape * FindLogical(TObject *logid) const
Find and return logical shape identified by unique logid.
Definition: TGLScene.cxx:1107
virtual void AdoptPhysical(TGLPhysicalShape &shape)
Adopt dynamically created physical &#39;shape&#39; - add to internal map and take responsibility for deleting...
Definition: TGLScene.cxx:1129
void SetTransparent(Bool_t t)
std::vector< TGLPlane > & FrustumPlanes()
Definition: TGLSceneInfo.h:107
std::vector< TGLPlane > & ClipPlanes()
Definition: TGLSceneInfo.h:108
virtual void CalcBoundingBox() const
Encapsulates all physical shapes bounding box with axes aligned box.
Definition: TGLScene.cxx:977
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:82
static Float_t GetPointSizeScale()
Get global point-size scale.
Definition: TGLUtil.cxx:1844
const TGLBoundingBox & BoundingBox() const
virtual void UpdatePhysical(UInt_t phid, Double_t *trans, UChar_t *col)
Reposition/recolor physical shape.
Definition: TGLScene.cxx:1304
UInt_t BeginSmartRefresh()
Moves logicals that support smart-refresh to intermediate cache.
Definition: TGLScene.cxx:1416
void PostDraw()
Clean-up after drawing, nothing to be done here.
Definition: TGLScene.cxx:169
TGLCamera * GetCamera()
Definition: TGLRnrCtx.h:156
Bool_t IsTransparent() const
virtual void UpdateSceneInfo(TGLRnrCtx &ctx)
Fill scene-info with information needed for rendering, take into account the render-context (viewer s...
void IncMinorStamp()
Definition: TGLSceneBase.h:117
void DumpMapSizes() const
Print sizes of logical and physical-shape maps.
Definition: TGLScene.cxx:1523
void Info(const char *location, const char *msgfmt,...)
std::map< TClass *, UInt_t > fByShapeCnt
Definition: TGLScene.h:117
void UpdateDrawStats(const TGLPhysicalShape &shape, Short_t lod)
Update draw stats, for newly drawn &#39;shape&#39;.
Definition: TGLScene.cxx:187
static const char * StyleName(Short_t style)
Return string describing the style.
Definition: TGLRnrCtx.cxx:453
Float_t fLastLineWidthScale
Definition: TGLScene.h:142
PhysicalShapeMap_t fPhysicalShapes
Definition: TGLScene.h:128
TGLContextIdentity * fGLCtxIdentity
Definition: TGLScene.h:133
virtual Bool_t DestroyLogical(TObject *logid, Bool_t mustFind=kTRUE)
Destroy logical shape defined by unique &#39;ID&#39;.
Definition: TGLScene.cxx:1036
void Error(const char *location, const char *msgfmt,...)
void ClearAfterRebuild()
Clear DrawElementVector fVisibleElement and optionally resize it so that it doesn&#39;t take more space t...
Definition: TGLScene.cxx:101
void DumpDrawStats()
Output draw stats to Info stream.
Definition: TGLScene.cxx:218
ELock fLock
Definition: TGLLockable.h:32
DrawElementPtrVec_t fSelTranspElements
Definition: TGLScene.h:98
short Color_t
Definition: RtypesCore.h:79
const Double_t * CArr() const
Definition: TGLUtil.h:562
Short_t ShapeLOD() const
Definition: TGLRnrCtx.h:177
Short_t CombiLOD() const
Definition: TGLRnrCtx.h:175
Double_t Diagonal() const
Bool_t IsValid() const
Definition: TGLContext.h:99
TGLSceneBase * fScene
Definition: TGLSceneInfo.h:39
TObject * GetExternal() const
virtual void RebuildSceneInfo(TGLRnrCtx &ctx)
Fill scene-info with very basic information that is practically view independent. ...
void SetShapePixSize(Float_t ps)
Definition: TGLRnrCtx.h:180
Short_t SceneStyle() const
Definition: TGLRnrCtx.h:184
void SetHighlightOutline(Bool_t ho)
Definition: TGLRnrCtx.h:221
virtual TGLPhysicalShape * FindPhysical(UInt_t phid) const
Find and return physical shape identified by unique &#39;ID&#39;.
Definition: TGLScene.cxx:1221
TGLPhysicalShape * fFirstPhysical
physical instance ref counting
Standard selection record including information about containing scene and details ob out selected ob...
UInt_t UnrefFirstPhysical()
Unreferenced first physical in the list, returning its id and making it fit for destruction somewhere...
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual Bool_t DestroyPhysical(UInt_t phid)
Destroy physical shape defined by unique &#39;ID&#39;.
Definition: TGLScene.cxx:1159
std::vector< DrawElement_t * > DrawElementPtrVec_t
Definition: TGLScene.h:70
char * Form(const char *fmt,...)
static TClass * GetGLRenderer(TClass *isa)
Return direct-rendering GL class for class isa.
Definition: TGLObject.cxx:135
void SetObject(TObject *obj)
short Short_t
Definition: RtypesCore.h:35
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual void LodifySceneInfo(TGLRnrCtx &ctx)
Setup LOD-dependant values in scene-info.
void Warning(const char *location, const char *msgfmt,...)
void InvalidateBoundingBox()
Definition: TGLSceneBase.h:137
Double_t XMax() const
virtual void RenderHighlight(TGLRnrCtx &rnrCtx, DrawElementPtrVec_t &elVec)
Definition: TGLScene.cxx:672
Abstract logical shape - a GL &#39;drawable&#39; - base for all shapes - faceset sphere etc.
const Bool_t kFALSE
Definition: RtypesCore.h:88
void Lodify(TGLRnrCtx &ctx)
Quantize LODs for given render-context.
Definition: TGLScene.cxx:128
Char_t ClipMode() const
Definition: TGLSceneInfo.h:101
virtual void Draw(TGLRnrCtx &rnrCtx) const
Draw physical shape, using LOD flags, potential from display list cache.
friend class TSceneInfo
Definition: TGLScene.h:123
Bool_t IsStopwatchRunning() const
Definition: TGLRnrCtx.h:214
long Long_t
Definition: RtypesCore.h:50
Short_t LastStyle() const
Definition: TGLSceneInfo.h:127
void EndSmartRefresh()
Wipes logicals in refresh-cache.
Definition: TGLScene.cxx:1439
static const double x1[5]
Bool_t fBoundingBoxValid
Definition: TGLSceneBase.h:56
UInt_t ID() const
Float_t fLastPointSizeScale
Definition: TGLScene.h:141
#define ClassImp(name)
Definition: Rtypes.h:359
std::vector< TGLPlane > TGLPlaneSet_t
Definition: TGLUtil.h:570
virtual Int_t DestroyPhysicals()
Destroy physical shapes.
Definition: TGLScene.cxx:1183
double Double_t
Definition: RtypesCore.h:55
Float_t SceneOLLineW() const
Definition: TGLRnrCtx.h:193
virtual void RenderElements(TGLRnrCtx &rnrCtx, DrawElementPtrVec_t &elVec, Bool_t check_timeout, const TGLPlaneSet_t *clipPlanes=0)
Render DrawElements in elementVec with given timeout.
Definition: TGLScene.cxx:893
void Negate()
Negate the plane.
Definition: TGLUtil.cxx:509
UInt_t SizeOfScene() const
Return memory cost of scene.
Definition: TGLScene.cxx:1491
UInt_t GetItem(Int_t i) const
virtual void DestroyPhysicalInternal(PhysicalShapeMapIt_t pit)
Virtual function to destroy a physical.
Definition: TGLScene.cxx:1149
std::vector< const TGLPhysicalShape * > ShapeVec_t
Definition: TGLScene.h:74
void SetTransform(const TGLMatrix &transform)
unsigned long ULong_t
Definition: RtypesCore.h:51
Bool_t IsVisible() const
Definition: TGLSceneInfo.h:105
virtual void UpdateBoundingBox()
virtual void RenderSelOpaque(TGLRnrCtx &rnrCtx)
Render selected opaque elements.
Definition: TGLScene.cxx:633
virtual void PostDraw(TGLRnrCtx &rnrCtx)
Called after the rendering is finished.
Definition: TGLScene.cxx:707
void PreDraw()
Prepare for drawing - fill DrawElementPtrVectors from the contents of fVisibleElements if there was s...
Definition: TGLScene.cxx:138
The color creation and management class.
Definition: TColor.h:19
virtual void RenderSelTransp(TGLRnrCtx &rnrCtx)
Render selected transparent elements.
Definition: TGLScene.cxx:643
UInt_t Ref() const
void SetLogShape(TGLLogicalShape *lshp)
void SetDrawPass(Short_t dpass)
Definition: TGLRnrCtx.h:205
void UpdateTimeouted()
Definition: TGLSceneInfo.h:154
Short_t LastLOD() const
Definition: TGLSceneInfo.h:124
UInt_t GetMinorStamp() const
Definition: TGLSceneBase.h:116
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void RebuildSceneInfo(TGLRnrCtx &rnrCtx)
Major change in scene, need to rebuild all-element draw-vector and sort it.
Definition: TGLScene.cxx:382
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
void ReleaseGLCtxIdentity()
Release all GL resources for current context identity.
Definition: TGLScene.cxx:311
char Char_t
Definition: RtypesCore.h:29
static Bool_t IsOutside(const TGLBoundingBox &box, const TGLPlaneSet_t &planes)
Check if box is outside of all planes.
Definition: TGLScene.cxx:1543
static Float_t GetLineWidthScale()
Returns global line-width scale.
Definition: TGLUtil.cxx:1860
DrawElementPtrVec_t fOpaqueElements
Definition: TGLScene.h:95
TGLScene provides management and rendering of ROOT&#39;s default 3D /object representation as logical and...
Definition: TGLScene.h:30
EOverlap
Definition: TGLUtil.h:33
Bool_t fInSmartRefresh
Definition: TGLScene.h:137
virtual void RenderAllPasses(TGLRnrCtx &rnrCtx, DrawElementPtrVec_t &elVec, Bool_t check_timeout)
Do full rendering of scene.
Definition: TGLScene.cxx:725
Int_t GetN() const
Bool_t HasStopwatchTimedOut()
Check if the stopwatch went beyond the render time limit.
Definition: TGLRnrCtx.cxx:188
void ClearDrawElementPtrVec(DrawElementPtrVec_t &vec, Int_t maxSize)
Clear given vec and if it grew too large compared to the size of shape-of-interest also resize it...
Definition: TGLScene.cxx:84
DrawElementPtrVec_t fSelOpaqueElements
Definition: TGLScene.h:97
Base class for extended scene context.
Definition: TGLSceneInfo.h:26
virtual void UpdateSceneInfo(TGLRnrCtx &rnrCtx)
Fill scene-info with information needed for rendering, take into account the render-context (viewer s...
Definition: TGLScene.cxx:426
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Double_t YMin() const
virtual Bool_t BeginUpdate()
Put scene in update mode, return true if lock acquired.
Definition: TGLScene.cxx:1245
Bool_t TakeLock(ELock lock) const
Lock the object in mode &#39;lock&#39;.
Definition: TGLLockable.cxx:32
void TagViewersChanged()
Tag all viewers as changed.
Double_t Volume() const
static Float_t LineWidth()
Get the line-width, taking the global scaling into account.
Definition: TGLUtil.cxx:1904
Bool_t ShouldClip() const
Definition: TGLSceneInfo.h:104
virtual Bool_t IgnoreSizeForOfInterest() const
Return true if size of this shape should be ignored when determining if the object should be drawn...
virtual void PreDraw(TGLRnrCtx &rnrCtx)
Perform basic pre-render initialization:
unsigned char UChar_t
Definition: RtypesCore.h:34
Rgl::EOverlap Overlap(const TGLPlane &plane) const
Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
Definition: first.py:1
virtual void AdoptLogical(TGLLogicalShape &shape)
Adopt dynamically created logical &#39;shape&#39; - add to internal map and take responsibility for deleting...
Definition: TGLScene.cxx:1018
virtual void CalculateShapeLOD(TGLRnrCtx &rnrCtx, Float_t &pixSize, Short_t &shapeLOD) const
Calculate shape-lod, suitable for use under projection defined by &#39;rnrCtx&#39;, taking account of which l...
Double_t ZMin() const
std::vector< DrawElement_t >::iterator DrawElementVec_i
Definition: TGLScene.h:68
TSceneInfo(TGLViewerBase *view=0, TGLScene *scene=0)
Constructor.
Definition: TGLScene.cxx:48
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).
Definition: TGLScene.cxx:1532
DrawElementVec_t fVisibleElements
Definition: TGLScene.h:92
void SetSpecific(void *spec)
const Bool_t kTRUE
Definition: RtypesCore.h:87
std::vector< DrawElement_t * >::iterator DrawElementPtrVec_i
Definition: TGLScene.h:71
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:525
virtual Int_t DestroyLogicals()
Destroy all logical shapes in scene.
Definition: TGLScene.cxx:1073
TObject * ID() const
LogicalShapeMap_t::const_iterator LogicalShapeMapCIt_t
Definition: TGLScene.h:46
Short_t ViewerLOD() const
Definition: TGLRnrCtx.h:171
virtual void LodifySceneInfo(TGLRnrCtx &rnrCtx)
Setup LOD-dependant values in scene-info.
Definition: TGLScene.cxx:544
double log(double)
const char * cnt
Definition: TXMLSetup.cxx:74
const TGLLogicalShape * GetLogical() const
void ResetDrawStats()
Reset draw statistics.
Definition: TGLScene.cxx:176
Float_t SceneWFLineW() const
Definition: TGLRnrCtx.h:189
virtual void PreDraw(TGLRnrCtx &rnrCtx)
Initialize rendering.
Definition: TGLScene.cxx:568
void SetDiffuseColor(const Float_t rgba[4])
Set color from ROOT color index and transparency [0,100].
virtual void PostDraw(TGLRnrCtx &rnrCtx)
Finalize drawing.
ShapeVec_t fShapesOfInterest
Definition: TGLScene.h:90
virtual void DLCacheClear()
Clear all entries for all LODs for this drawable from the display list cache but keeping the reserved...
void ReleaseClient()
Definition: TGLContext.h:94
const char * Data() const
Definition: TString.h:345