Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLPhysicalShape.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Richard Maunder 25/05/2005
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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 "TGLPhysicalShape.h"
13#include "TGLLogicalShape.h"
14#include "TGLPShapeRef.h"
15#include "TGLCamera.h"
16#include "TGLRnrCtx.h"
17#include "TGLIncludes.h"
18
19#include "TGLScene.h"
20
21#include "TColor.h"
22#include "TROOT.h"
23
24#include <cmath>
25
26// For debug tracing
27#include "TClass.h"
28#include "TError.h"
29
30/** \class TGLPhysicalShape
31\ingroup opengl
32Concrete physical shape - a GL drawable. Physical shapes are the
33objects the user can actually see, select, move in the viewer. It is
34a placement of the associated local frame TGLLogicaShape into the
35world frame. The draw process is:
36
37Load attributes - material colors etc
38Load translation matrix - placement
39Load gl name (for selection)
40Call our associated logical shape Draw() to draw placed shape
41
42The physical shape supports translation, scaling and rotation,
43selection, color changes, and permitted modification flags etc.
44A physical shape cannot modify or be bound to another (or no)
45logical shape - hence const & handle. It can perform mutable
46reference counting on the logical to enable purging.
47
48Physical shape also maintains a list of references to it and
49provides notifications of change and destruction.
50See class TGLPShapeRef which needs to be sub-classes for real use.
51
52See base/src/TVirtualViewer3D for description of common external 3D
53viewer architecture and how external viewer clients use it.
54*/
55
56
57////////////////////////////////////////////////////////////////////////////////
58/// Construct a physical shape using arguments:
59/// - ID - unique drawable id.
60/// - logicalShape - bound logical shape
61/// - transform - transform for placement of logical drawing
62/// - invertedWind - use inverted face polygon winding?
63/// - rgba - basic four component (RGBA) diffuse color
64
67 const Float_t rgba[4]) :
68 fLogicalShape (&logicalShape),
69 fNextPhysical (nullptr),
70 fFirstPSRef (nullptr),
71 fID (id),
72 fTransform (transform),
73 fManip (kManipAll),
74 fSelected (0),
75 fInvertedWind (invertedWind),
76 fModified (kFALSE),
77 fIsScaleForRnr(kFALSE)
78{
79 fLogicalShape->AddRef(this);
81
82 // Initialise color
84}
85
86////////////////////////////////////////////////////////////////////////////////
87/// Construct a physical shape using arguments:
88/// - id - unique drawable id.
89/// - logicalShape - bound logical shape
90/// - transform - 16 Double_t component transform for placement of logical drawing
91/// - invertedWind - use inverted face polygon winding?
92/// - rgba - basic four component (RGBA) diffuse color
93
96 const Float_t rgba[4]) :
97 fLogicalShape (&logicalShape),
98 fNextPhysical (nullptr),
99 fFirstPSRef (nullptr),
100 fID (id),
101 fTransform (transform),
102 fManip (kManipAll),
103 fSelected (0),
104 fInvertedWind (invertedWind),
105 fModified (kFALSE),
106 fIsScaleForRnr(kFALSE)
107{
108 fLogicalShape->AddRef(this);
109
110 // Temporary hack - invert the 3x3 part of matrix as TGeo sends this
111 // in opp layout to shear/translation parts. Speak to Andrei about best place
112 // to fix - probably when filling TBuffer3D - should always be OGL convention?
115
116 // Initialise color
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Destroy the physical shape.
122
124{
125 // If destroyed from the logical shape itself the pointer has already
126 // been cleared.
127 if (fLogicalShape) fLogicalShape->SubRef(this);
128
129 // Remove all references.
130 while (fFirstPSRef) {
131 fFirstPSRef->SetPShape(nullptr);
132 }
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Add reference ref.
137
139{
140 assert(ref != nullptr);
141
142 ref->fNextPSRef = fFirstPSRef;
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// Remove reference ref.
148
150{
151 assert(ref != nullptr);
152
153 Bool_t found = kFALSE;
154 if (fFirstPSRef == ref) {
155 fFirstPSRef = ref->fNextPSRef;
156 found = kTRUE;
157 } else {
159 while ((shp2 = shp1->fNextPSRef) != nullptr) {
160 if (shp2 == ref) {
161 shp1->fNextPSRef = shp2->fNextPSRef;
162 found = kTRUE;
163 break;
164 }
165 shp1 = shp2;
166 }
167 }
168 if (found) {
169 ref->fNextPSRef = nullptr;
170 } else {
171 Error("TGLPhysicalShape::RemoveReference", "Attempt to un-ref an unregistered shape-ref.");
172 }
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Call this after modifying the physical so that the information
177/// can be propagated to the object referencing it.
178
180{
183 while (ref) {
184 ref->PShapeModified();
185 ref = ref->fNextPSRef;
186 }
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Update our internal bounding box (in global frame).
191
193{
194 fBoundingBox.Set(fLogicalShape->BoundingBox());
196
198
199 if (fLogicalShape->GetScene())
200 fLogicalShape->GetScene()->InvalidateBoundingBox();
201}
202
203////////////////////////////////////////////////////////////////////////////////
204/// Initialise the colors, using basic RGBA diffuse material color supplied
205
207{
208 // TODO: Make a color class
209 fColor[0] = rgba[0];
210 fColor[1] = rgba[1];
211 fColor[2] = rgba[2];
212 fColor[3] = rgba[3];
213
214 fColor[4] = fColor[5] = fColor[6] = 0.0f; //ambient
215 fColor[8] = fColor[9] = fColor[10] = 0.7f; //specular
216 fColor[12] = fColor[13] = fColor[14] = 0.0f; //emission
217 fColor[7] = fColor[11] = fColor[15] = 1.0f; //alpha
218 fColor[16] = 60.0f; //shininess
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// Set full color attributes - see OpenGL material documentation
223/// for full description.
224/// 0->3 diffuse, 4->7 ambient, 8->11 specular, 12->15 emission, 16 shininess
225
227{
228 // TODO: Make a color class
229 for (UInt_t i = 0; i < 17; i++) {
230 fColor[i] = color[i];
231 }
232
233 Modified();
234}
235
236////////////////////////////////////////////////////////////////////////////////
237/// Set full color attributes to all physicals sharing the same
238/// logical with this object.
239
241{
242 TGLPhysicalShape* pshp = const_cast<TGLPhysicalShape*>(fLogicalShape->GetFirstPhysical());
243 while (pshp)
244 {
245 pshp->SetColor(color);
246 pshp = pshp->fNextPhysical;
247 }
248}
249
250////////////////////////////////////////////////////////////////////////////////
251/// Set color from ROOT color index and transparency [0,100].
252
254{
255 for (Int_t i=0; i<4; ++i)
256 fColor[i] = rgba[i];
257 Modified();
258}
259
260////////////////////////////////////////////////////////////////////////////////
261/// Set color from RGBA quadruplet.
262
264{
265 for (Int_t i=0; i<4; ++i)
266 fColor[i] = rgba[i]/255.0f;
267 Modified();
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Set color from standard ROOT representation, that is color index
272/// + transparency in range [0, 100].
273
275{
276 if (ci < 0) ci = 1;
277 TColor* c = gROOT->GetColor(ci);
278 if (c) {
279 fColor[0] = c->GetRed();
280 fColor[1] = c->GetGreen();
281 fColor[2] = c->GetBlue();
282 fColor[3] = 1.0f - 0.01*transparency;
283 }
284 Modified();
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// Setup colors - avoid setting things not required
289/// for current draw flags.
290
292{
293 if (color == nullptr) color = fColor;
294
295 switch (rnrCtx.DrawPass()) {
297 {
298 // Wireframe needs basic color only
299 glColor4fv(color);
300 break;
301 }
304 {
305 // Both need material colors
306
307 // Set back diffuse only for clipping where inner (back) faces
308 // are shown. Don't set shininess or specular as we want
309 // back face to appear as 'flat' as possible as crude visual
310 // approximation to proper capped clipped solid
312 glMaterialfv(GL_FRONT, GL_AMBIENT, color + 4);
313 glMaterialfv(GL_FRONT, GL_SPECULAR, color + 8);
314 glMaterialfv(GL_FRONT, GL_EMISSION, color + 12);
315 glMaterialf(GL_FRONT, GL_SHININESS, color[16]);
316 // Some objects use point/line graphics. Material mode disabled.
317 glColor4fv(color);
318 break;
319 }
321 {
322 // Outline also needs grey wireframe but respecting
323 // transparency of main diffuse color.
324 TGLUtil::ColorAlpha(rnrCtx.ColorSet().Outline(), 0.5f*color[3]);
325 break;
326 }
327 default:
328 {
329 assert(kFALSE);
330 }
331 }
332}
333
334////////////////////////////////////////////////////////////////////////////////
335/// Draw physical shape, using LOD flags, potential from display list cache
336
338{
339 // Debug tracing
340 if (gDebug > 4) {
341 Info("TGLPhysicalShape::Draw", "this %zd (class %s) LOD %d",
342 (size_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
343 }
344
345 // If LOD is pixel or less can draw pixel(point) directly, skipping
346 // any logical call, caching etc.
347 if (rnrCtx.ShapeLOD() == TGLRnrCtx::kLODPixel)
348 {
349 if (!rnrCtx.IsDrawPassOutlineLine())
350 {
352 glBegin(GL_POINTS);
354 glEnd();
355 }
356 return;
357 }
358
359 if (gDebug > 4) {
360 Info("TGLPhysicalShape::Draw", "this %zd (class %s) LOD %d",
361 (size_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
362 }
363
364 glPushMatrix();
368 if (rnrCtx.Highlight())
369 {
371
374
375 if (rnrCtx.HighlightOutline())
376 {
377 static const Int_t offsets[20][2] =
378 { {-1,-1}, { 1,-1}, { 1, 1}, {-1, 1},
379 { 1, 0}, { 0, 1}, {-1, 0}, { 0,-1},
380 { 0,-2}, { 2, 0}, { 0, 2}, {-2, 0},
381 {-2,-2}, { 2,-2}, { 2, 2}, {-2, 2},
382 { 0,-3}, { 3, 0}, { 0, 3}, {-3, 0} };
383 static const Int_t max_off =
384 TGLUtil::GetScreenScalingFactor() > 1.5 ? 20 : 12;
385
386 const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
387
388 for (int i = 0; i < max_off; ++i)
389 {
390 glViewport(vp.X() + offsets[i][0], vp.Y() + offsets[i][1], vp.Width(), vp.Height());
391 fLogicalShape->DrawHighlight(rnrCtx, this);
392 }
393
394 glViewport(vp.X(), vp.Y(), vp.Width(), vp.Height());
395 }
396 else
397 {
398 fLogicalShape->DrawHighlight(rnrCtx, this);
399 }
400
401 glPopAttrib();
402 }
403 else
404 {
406 if (rnrCtx.IsDrawPassOutlineLine())
408 fLogicalShape->Draw(rnrCtx);
409 if (rnrCtx.IsDrawPassOutlineLine())
411 }
414 glPopMatrix();
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// Calculate shape-lod, suitable for use under
419/// projection defined by 'rnrCtx', taking account of which local
420/// axes of the shape support LOD adjustment, and the global
421/// 'sceneFlags' passed.
422///
423/// Returned shapeLOD component is from 0 (kLODPixel - lowest
424/// quality) to 100 (kLODHigh - highest quality).
425///
426/// Scene flags are not used. LOD quantization is not done. RnrCtx
427/// is not modified as this is called via lodification stage of
428/// rendering.
429
431{
432 TGLLogicalShape::ELODAxes lodAxes = fLogicalShape->SupportedLODAxes();
433
435 { // Shape doesn't support LOD along any axes return special
436 // unsupported LOD draw/cache flag.
437 // TODO: Still ... could check for kLODPixel when very small,
438 // by using diagonal from bounding-box and some special camera foo.
439 pixSize = 100; // Make up something / irrelevant.
441 return;
442 }
443
444 std::vector <Double_t> boxViewportDiags;
445 const TGLBoundingBox & box = BoundingBox();
446 const TGLCamera & camera = rnrCtx.RefCamera();
447
449 // Shape supports LOD along all axes - basis LOD hint on diagonal of viewport
450 // projection rect round whole bounding box
451 boxViewportDiags.push_back(camera.ViewportRect(box).Diagonal());
453 // Shape supports LOD along Y/Z axes (not X). LOD hint based on longest
454 // diagonal (largest rect) of either of the X axis end faces
455 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceLowX).Diagonal());
456 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceHighX).Diagonal());
458 // Shape supports LOD along X/Z axes (not Y). See above for Y/Z
459 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceLowY).Diagonal());
460 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceHighY).Diagonal());
462 // Shape supports LOD along X/Y axes (not Z). See above for Y/Z
463 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceLowZ).Diagonal());
464 boxViewportDiags.push_back(camera.ViewportRect(box, TGLBoundingBox::kFaceHighZ).Diagonal());
465 } else {
466 // Don't bother to implement LOD calc for shapes supporting LOD along single
467 // axis only. Not needed at present + unlikely case - but could be done based
468 // on longest of projection of 4 edges of BBox along LOD axis. However this would
469 // probably be more costly than just using whole BB projection (as for all axes)
470 Error("TGLPhysicalShape::CalcPhysicalLOD", "LOD calculation for single axis not implemented presently");
472 return;
473 }
474
475 // Find largest of the projected diagonals
477 for (UInt_t i = 0; i < boxViewportDiags.size(); i++) {
480 }
481 }
483
484 if (largestDiagonal <= 1.0) {
486 } else {
487 // TODO: Get real screen size - assuming 2000 pixel screen at present
488 // Calculate a non-linear sizing hint for this shape based on diagonal.
489 // Needs more experimenting with...
490 UInt_t lodApp = static_cast<UInt_t>(std::pow(largestDiagonal,0.4) * 100.0 / std::pow(2000.0,0.4));
491 if (lodApp > 1000) lodApp = 1000;
493 }
494}
495
496////////////////////////////////////////////////////////////////////////////////
497/// Factor in scene/vierer LOD and Quantize ... forward to
498/// logical shape.
499
504
505////////////////////////////////////////////////////////////////////////////////
506/// Request creation of context menu on shape, attached to 'menu' at screen position
507/// 'x' 'y'
508
510{
511 // Just defer to our logical at present
512 fLogicalShape->InvokeContextMenu(menu, x, y);
513}
#define c(i)
Definition RSha256.hxx:101
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char)
Definition RtypesCore.h:52
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
#define gROOT
Definition TROOT.h:411
The color creation and management class.
Definition TColor.h:22
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
This class provides an interface to context sensitive popup menus.
Concrete class describing an orientated (free) or axis aligned box of 8 vertices.
void Set(const TGLVertex3 vertex[8])
Set a bounding box from provided 8 vertices.
void Transform(const TGLMatrix &matrix)
Transform all vertices with matrix.
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition TGLCamera.h:44
Abstract logical shape - a GL 'drawable' - base for all shapes - faceset sphere etc.
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition TGLUtil.h:598
void Transpose3x3()
Transpose the top left 3x3 matrix component along major diagonal Supported as currently incompatibili...
Definition TGLUtil.cxx:941
const Double_t * CArr() const
Definition TGLUtil.h:664
Bool_t IsScalingForRender() const
Return true if matrix is to be considered a scaling matrix for rendering.
Definition TGLUtil.cxx:1105
Base class for references to TGLPysicalShape that need to be notified when the shape is destroyed.
virtual void SetPShape(TGLPhysicalShape *shape)
Set the shape.
Concrete physical shape - a GL drawable.
void Modified()
Call this after modifying the physical so that the information can be propagated to the object refere...
void InvokeContextMenu(TContextMenu &menu, UInt_t x, UInt_t y) const
Request creation of context menu on shape, attached to 'menu' at screen position 'x' 'y'.
virtual ~TGLPhysicalShape()
Destroy the physical shape.
void SetupGLColors(TGLRnrCtx &rnrCtx, const Float_t *color=nullptr) const
Setup colors - avoid setting things not required for current draw flags.
const TGLLogicalShape * fLogicalShape
Bool_t fModified
face winding TODO: can get directly from fTransform?
const TGLBoundingBox & BoundingBox() const
virtual void QuantizeShapeLOD(Short_t shapeLOD, Short_t combiLOD, Short_t &quantLOD) const
Factor in scene/vierer LOD and Quantize ... forward to logical shape.
void RemoveReference(TGLPShapeRef *ref)
Remove reference ref.
void InitColor(const Float_t rgba[4])
Initialise the colors, using basic RGBA diffuse material color supplied.
void SetColor(const Float_t rgba[17])
Set full color attributes - see OpenGL material documentation for full description.
Bool_t fIsScaleForRnr
has been modified - retain across scene rebuilds
virtual TClass * IsA() const
void SetColorOnFamily(const Float_t rgba[17])
Set full color attributes to all physicals sharing the same logical with this object.
virtual void CalculateShapeLOD(TGLRnrCtx &rnrCtx, Float_t &pixSize, Short_t &shapeLOD) const
Calculate shape-lod, suitable for use under projection defined by 'rnrCtx', taking account of which l...
void AddReference(TGLPShapeRef *ref)
Add reference ref.
Bool_t fInvertedWind
selected state
void SetDiffuseColor(const Float_t rgba[4])
Set color from ROOT color index and transparency [0,100].
TGLPhysicalShape(const TGLPhysicalShape &)=delete
TGLBoundingBox fBoundingBox
transform (placement) of physical instance
TGLMatrix fTransform
unique physical ID within containing scene
TGLPShapeRef * fFirstPSRef
pointer to next replica
Float_t fColor[17]
bounding box of the physical (transformed)
void UpdateBoundingBox()
cache
virtual void Draw(TGLRnrCtx &rnrCtx) const
Draw physical shape, using LOD flags, potential from display list cache.
Viewport (pixel base) 2D rectangle class.
Definition TGLUtil.h:422
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition TGLRnrCtx.h:41
@ kPassOutlineFill
Definition TGLRnrCtx.h:56
@ kPassWireFrame
Definition TGLRnrCtx.h:58
@ kPassOutlineLine
Definition TGLRnrCtx.h:57
static UInt_t LockColor()
Prevent further color changes.
Definition TGLUtil.cxx:1660
static UInt_t UnlockColor()
Allow color changes.
Definition TGLUtil.cxx:1668
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1843
static void ColorAlpha(const TGLColor &color, UChar_t alpha)
Set color from TGLColor and alpha value.
Definition TGLUtil.cxx:1696
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17