ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TGLCamera.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 "TGLCamera.h"
13 #include "TGLIncludes.h"
14 #include "TGLBoundingBox.h"
15 #include "TError.h"
16 #include "TMath.h"
17 
18 /** \class TGLCamera
19 \ingroup opengl
20 Abstract base camera class - concrete classes for orthographic and
21 perspective cameras derive from it. This class maintains values for
22 the current:
23  1. Viewport
24  2. Projection, modelview and clip matrices - extracted from GL
25  3. The 6 frustum planes
26  4. Expanded frustum interest box
27 
28 It provides methods for various projection, overlap and intersection
29 tests for viewport and world locations, against the true frustum and
30 expanded interest box, and for extracting eye position and direction.
31 
32 It also defines the pure virtual manipulation interface methods the
33 concrete ortho and perspective classes must implement.
34 */
35 
37 
38 const Double_t TGLCamera::fgInterestBoxExpansion = 1.3;
39 UInt_t TGLCamera::fgDollyDeltaSens = 500;
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 /// Default base camera constructor
43 
45  fExternalCenter(kFALSE),
46  fFixDefCenter(kFALSE),
47  fWasArcBalled(kFALSE),
48  fCenter(&fDefCenter),
49  fNearClip(0), fFarClip(0),
50  fDollyDefault(1.0), fDollyDistance(1.0),
51  fVAxisMinAngle(0.01f),
52  fCacheDirty(kTRUE),
53  fTimeStamp (1),
54  fProjM(), fModVM(), fClipM(),
55  fViewport(0,0,100,100),
56  fLargestSeen(0.0)
57 {
58  for (UInt_t i = 0; i < kPlanesPerFrustum; i++ ) {
59  fFrustumPlanes[i].Set(1.0, 0.0, 0.0, 0.0);
60  }
61  TGLVertex3 origin;
62  fCamBase.Set(origin, TGLVector3(1, 0, 0), TGLVector3(0, 0, 1));
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Default base camera constructor
67 
68 TGLCamera::TGLCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis) :
69  fExternalCenter(kFALSE),
70  fFixDefCenter(kFALSE),
71  fWasArcBalled(kFALSE),
72  fCenter(&fDefCenter),
73  fNearClip(0), fFarClip(0),
74  fDollyDefault(1.0), fDollyDistance(1.0),
75  fVAxisMinAngle(0.01f),
76  fCacheDirty(kTRUE),
77  fTimeStamp (1),
78  fProjM(), fModVM(), fClipM(),
79  fViewport(0,0,100,100),
80  fLargestSeen(0.0)
81 {
82  for (UInt_t i = 0; i < kPlanesPerFrustum; i++ ) {
83  fFrustumPlanes[i].Set(1.0, 0.0, 0.0, 0.0);
84  }
85  TGLVertex3 origin;
86  fCamBase.Set(origin, vAxis, hAxis);
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Base camera destructor.
91 
93 {
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// Set viewport extents from passed 'viewport' rect.
98 
99 void TGLCamera::SetViewport(const TGLRect & viewport)
100 {
101  fViewport = viewport;
102  IncTimeStamp();
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Update internally cached frustum values
107 
109 {
111 
112  glGetDoublev(GL_PROJECTION_MATRIX, fProjM.Arr());
113  glGetDoublev(GL_MODELVIEW_MATRIX, fModVM.Arr());
114 
115  // Multiply projection by modelview to get the clip matrix
116  // TODO: Move this into TGLMatrix or shift all over to ROOT ones
117  fClipM = fProjM;
118  fClipM *= fModVM;
119 
120  // RIGHT clipping plane
121  fFrustumPlanes[kRight].Set(fClipM[ 3] - fClipM[ 0],
122  fClipM[ 7] - fClipM[ 4],
123  fClipM[11] - fClipM[ 8],
124  fClipM[15] - fClipM[12]);
125 
126  // LEFT clipping plane
127  fFrustumPlanes[kLeft].Set(fClipM[ 3] + fClipM[ 0],
128  fClipM[ 7] + fClipM[ 4],
129  fClipM[11] + fClipM[ 8],
130  fClipM[15] + fClipM[12]);
131 
132  // BOTTOM clipping plane
133  fFrustumPlanes[kBottom].Set(fClipM[ 3] + fClipM[ 1],
134  fClipM[ 7] + fClipM[ 5],
135  fClipM[11] + fClipM[ 9],
136  fClipM[15] + fClipM[13]);
137 
138 
139  // TOP clipping plane
140  fFrustumPlanes[kTop].Set(fClipM[ 3] - fClipM[ 1],
141  fClipM[ 7] - fClipM[ 5],
142  fClipM[11] - fClipM[ 9],
143  fClipM[15] - fClipM[13]);
144 
145  // FAR clipping plane
146  fFrustumPlanes[kFar].Set(fClipM[ 3] - fClipM[ 2],
147  fClipM[ 7] - fClipM[ 6],
148  fClipM[11] - fClipM[10],
149  fClipM[15] - fClipM[14]);
150 
151  // NEAR clipping plane
152  fFrustumPlanes[kNear].Set(fClipM[ 3] + fClipM[ 2],
153  fClipM[ 7] + fClipM[ 6],
154  fClipM[11] + fClipM[10],
155  fClipM[15] + fClipM[14]);
156 
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// Return the the current camera frustum. If asBox == kFALSE return
162 /// a true frustum (truncated square based pyramid). If asBox == kTRUE
163 /// return a true box, using the far clipping plane intersection projected
164 /// back to the near plane.
165 ///
166 /// Camera must have valid frustum cache - call Apply() after last modification, before using
167 ///
168 /// Note: TGLBoundingBox is not really valid when filled with truncated pyramid
169 /// - this is used as a visual debug aid only so ok.
170 
172 {
173  // TODO: BoundingBox object is not always valid
174  // Need a generic bounding volume object
175  if (fCacheDirty) {
176  Error("TGLCamera::FrustumBox()", "cache dirty - must call Apply()");
177  }
178 
179 
180  TGLVertex3 vertex[8];
181 
182  // 7-------6
183  // /| /|
184  // 3-------2 |
185  // | 4-----|-5
186  // |/ |/
187  // 0-------1
188 
189  // Get four vertices of frustum on the far clipping plane
190  // We assume they always intersect
192  vertex[5] = Intersection(fFrustumPlanes[kFar], fFrustumPlanes[kBottom], fFrustumPlanes[kRight]).second;
193  vertex[6] = Intersection(fFrustumPlanes[kFar], fFrustumPlanes[kTop], fFrustumPlanes[kRight]).second;
194  vertex[7] = Intersection(fFrustumPlanes[kFar], fFrustumPlanes[kTop], fFrustumPlanes[kLeft]).second;
195 
196  if (asBox) {
197  // Now find the matching four vertices for above, projected onto near clip plane
198  // As near and far clip planes are parallel this forms a orientated box encompassing the frustum
199  vertex[0] = fFrustumPlanes[kNear].NearestOn(vertex[4]);
200  vertex[1] = fFrustumPlanes[kNear].NearestOn(vertex[5]);
201  vertex[2] = fFrustumPlanes[kNear].NearestOn(vertex[6]);
202  vertex[3] = fFrustumPlanes[kNear].NearestOn(vertex[7]);
203  } else {
204  // Returning true frustum - find vertices at near clipping plane
205  // We assume they always intersect
206  vertex[0] = Intersection(fFrustumPlanes[kNear], fFrustumPlanes[kBottom], fFrustumPlanes[kLeft]).second;
207  vertex[1] = Intersection(fFrustumPlanes[kNear], fFrustumPlanes[kBottom], fFrustumPlanes[kRight]).second;
208  vertex[2] = Intersection(fFrustumPlanes[kNear], fFrustumPlanes[kTop], fFrustumPlanes[kRight]).second;
209  vertex[3] = Intersection(fFrustumPlanes[kNear], fFrustumPlanes[kTop], fFrustumPlanes[kLeft]).second;
210  }
211 
212  return TGLBoundingBox(vertex);
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Return the camera eye point (vertex) in world space
217 /// Camera must have valid frustum cache - call Apply() after last modification, before using
218 
220 {
221  if (fCacheDirty) {
222  Error("TGLPerspectiveCamera::FrustumBox()", "cache dirty - must call Apply()");
223  }
224 
225  // Use intersection of right/left/top frustum planes - can be done in
226  // other ways from camera values but this is easiest.
227  // Note for an ortho camera this will result in an infinite z distance
228  // which is theoretically correct although of limited use
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Extract the camera eye direction (vector), running from EyePoint()
234 /// Camera must have valid frustum cache - call Apply() after last modification, before using
235 
237 {
238  if (fCacheDirty) {
239  Error("TGLCamera::FrustumBox()", "cache dirty - must call Apply()");
240  }
241  // Direction is just normal of near clipping plane
242  return fFrustumPlanes[kNear].Norm();
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Find the center of the camera frustum from intersection of planes
247 /// This method will work even with parallel left/right & top/bottom and
248 /// infinite eye point of ortho cameras
249 /// Camera must have valid frustum cache - call Apply() after last modification, before using
250 
252 {
253  if (fCacheDirty) {
254  Error("TGLCamera::FrustumCenter()", "cache dirty - must call Apply()");
255  }
256  std::pair<Bool_t, TGLVertex3> nearBottomLeft = Intersection(fFrustumPlanes[kNear],
259  std::pair<Bool_t, TGLVertex3> farTopRight = Intersection(fFrustumPlanes[kFar],
262  // Planes should intersect
263  if (!nearBottomLeft.first || !farTopRight.first) {
264  Error("TGLCamera::FrustumCenter()", "frustum planes invalid");
265  return TGLVertex3(0.0, 0.0, 0.0);
266  }
267  return nearBottomLeft.second + (farTopRight.second - nearBottomLeft.second)/2.0;
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Calculate overlap (kInside, kOutside, kPartial) of box with camera
272 /// frustum
273 /// Camera must have valid frustum cache - call Apply() after last modification, before using
274 
276 {
277  if (fCacheDirty) {
278  Error("TGLCamera::FrustumOverlap()", "cache dirty - must call Apply()");
279  }
280 
281  // Test shape against each plane in frustum - returning overlap result
282  // This method can result in kFALSE positives, where shape lies outside
283  // frustum, but not outside a single plane of it. In this case the shape
284  // will be regarded incorrectly as intersecting (kPartial)
285  // TODO: Improve this - have a reliable test (separating axes).
286 
287  Int_t planesInside = 0; // Assume outside to start
288  for (Int_t planeIndex = 0; planeIndex < kPlanesPerFrustum; ++planeIndex)
289  {
290  Rgl::EOverlap planeOverlap = box.Overlap(fFrustumPlanes[planeIndex]);
291 
292  // Special case - any object which comes through the near clipping
293  // plane is completely removed - disabled at present
294  // TODO: In future may want to fade object (opacity) as they approach
295  // near clip - how will this be returned? template pair?
296  /*if (planeIndex == kNear && planeOverlap == kPartial) {
297  return kOutside;
298  }*/
299  // Once we find a single plane which shape is outside, we are outside the frustum
300  if (planeOverlap == Rgl::kOutside) {
301  return Rgl::kOutside;
302  } else if (planeOverlap == Rgl::kInside) {
303  planesInside++;
304  }
305  }
306  // Completely inside frustum
307  if (planesInside == kPlanesPerFrustum) {
308  return Rgl::kInside;
309  } else {
310  return Rgl::kPartial;
311  }
312 }
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 /// Calculate overlap (kInside, kOutside, kPartial) of box projection onto viewport
316 /// (as rect) against the viewport rect.
317 /// Camera must have valid frustum cache - call Apply() after last modification, before using.
318 
320 {
321  return ViewportRect(box).Overlap(fViewport);
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Calculate viewport rectangle which just contains projection of single 'face'
326 /// of world frame bounding box 'box' onto the viewport. Note use other version
327 /// of ViewportRect() if you want whole 'box' contained
328 
330  const TGLBoundingBox::EFace face) const
331 {
332  return ViewportRect(box, &face);
333 }
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// Calculate viewport rectangle which just contains projection of
337 /// world frame bounding box 'box' onto the viewport. If face is
338 /// null the rect contains the whole bounding box (8 vertices/6
339 /// faces). If face is non-null it indicates a box face, and the
340 /// rect contains the single face (4 vertices). Note use other
341 /// version of ViewportRect() if you wish to just pass a static
342 /// EFace enum member (e.g. kFaceLowX)
343 ///
344 /// Note:
345 /// 1. Rectangle is NOT clipped by viewport limits - so can result
346 /// in rect with corners outside viewport - negative etc
347 /// 2. TGLRect provides int (pixel based) values - not subpixel accurate
348 /// 3. Camera must have valid frustum cache - call Apply() after last
349 /// modification, before calling
350 
352  const TGLBoundingBox::EFace * face) const
353 {
354  if (fCacheDirty) {
355  Error("TGLCamera::ViewportSize()", "cache dirty - must call Apply()");
356  }
357 
358  // TODO: Maybe TGLRect should be converted to Double_t so subpixel accurate
359  // Would give better LOD calculations at small sizes
360 
361  // May often result in a rect bigger then the viewport
362  // as gluProject does not clip.
363  Double_t winX, winY, winZ;
364  TGLRect screenRect;
365 
366  // TGLBoundingBox::Vertices() & TGLBoundingBox::FaceVertices() return
367  // const & vectors so this *should* all be efficient...
368  UInt_t vertexCount;
369  if (face) {
370  vertexCount = box.FaceVertices(*face).size();
371  } else {
372  vertexCount = box.NumVertices();
373  }
374 
375  for (UInt_t i = 0; i < vertexCount; i++)
376  {
377  const TGLVertex3 & vertex = face ? box.Vertex(box.FaceVertices(*face).at(i)) :
378  box.Vertex(i);
379 
380  gluProject(vertex.X(), vertex.Y(), vertex.Z(),
382  &winX, &winY, &winZ);
383 
384  if (i == 0) {
385  screenRect.SetCorner(static_cast<Int_t>(winX),static_cast<Int_t>(winY));
386  } else {
387  screenRect.Expand(static_cast<Int_t>(winX), static_cast<Int_t>(winY));
388  }
389  }
390 
391  return screenRect;
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Convert a 3D world vertex to '3D' viewport (screen) one. The X()/Y()
396 /// components of the viewport vertex are the horizontal/vertical pixel
397 /// positions. The Z() component is the viewport depth value - for a
398 /// default depth range this is 0.0 (at near clip plane) to 1.0 (at far
399 /// clip plane). See OpenGL gluProject & glDepth documentation
400 ///
401 /// Camera must have valid frustum cache - call Apply() after last modification, before using
402 
404  TGLMatrix* modviewMat) const
405 {
406  if (fCacheDirty) {
407  Error("TGLCamera::WorldToViewport()", "cache dirty - must call Apply()");
408  }
409  TGLVertex3 viewportVertex;
410  gluProject(worldVertex[0], worldVertex[1], worldVertex[2],
411  modviewMat ? modviewMat->CArr() : fModVM.CArr(),
412  fProjM.CArr(), fViewport.CArr(),
413  &viewportVertex[0], &viewportVertex[1], &viewportVertex[2]);
414  return viewportVertex;
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Convert a 3D vector worldDelta (shift) about vertex worldRef to a viewport
419 /// (screen) '3D' vector. The X()/Y() components of the vector are the horizontal /
420 /// vertical pixel deltas. The Z() component is the viewport depth delta - for a
421 /// default depth range between 0.0 (at near clip plane) to 1.0 (at far clip plane)
422 /// See OpenGL gluProject & glDepth documentation
423 ///
424 /// Camera must have valid frustum cache - call Apply()
425 
427  const TGLVector3 & worldDelta) const
428 {
429  if (fCacheDirty) {
430  Error("TGLCamera::WorldToViewport()", "cache dirty - must call Apply()");
431  }
432  TGLVertex3 other = worldRef + worldDelta;
433  TGLVertex3 v1 = WorldToViewport(worldRef);
434  TGLVertex3 v2 = WorldToViewport(other);
435  return v2 - v1;
436 }
437 
438 ////////////////////////////////////////////////////////////////////////////////
439 /// Convert a '3D' viewport vertex to 3D world one. The X()/Y() components
440 /// of viewportVertex are the horizontal/vertical pixel position.
441 
443  TGLMatrix* modviewMat) const
444 {
445  // The Z() component is the viewport depth value - for a default
446  // depth range this is 0.0 (at near clip plane) to 1.0 (at far clip
447  // plane). Without Z() the viewport position corresponds to a line
448  // in 3D world space - see:
449  // TGLLine3 TGLCamera::ViewportToWorld(Double_t viewportX, Double_t viewportY) const
450  //
451  // See also OpenGL gluUnProject & glDepth documentation.
452  //
453  // Camera must have valid frustum cache - call Apply() after last
454  // modification, before using.
455 
456  if (fCacheDirty) {
457  Error("TGLCamera::ViewportToWorld()", "cache dirty - must call Apply()");
458  }
459  TGLVertex3 worldVertex;
460  gluUnProject(viewportVertex[0], viewportVertex[1], viewportVertex[2],
461  modviewMat ? modviewMat->CArr() : fModVM.CArr(),
462  fProjM.CArr(), fViewport.CArr(),
463  &worldVertex[0], &worldVertex[1], &worldVertex[2]);
464  return worldVertex;
465 }
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Convert a 2D viewport position to 3D world line - the projection of the
469 /// viewport point into 3D space. Line runs from near to far camera clip planes
470 /// (the minimum and maximum visible depth). See also
471 /// TGLVertex3 TGLCamera::ViewportToWorld(const TGLVertex3 & viewportVertex) const
472 /// for 3D viewport -> 3D world vertex conversions.
473 /// See also OpenGL gluUnProject & glDepth documentation
474 ///
475 /// Camera must have valid frustum cache - call Apply() after last modification, before using
476 
478 {
479  if (fCacheDirty) {
480  Error("TGLCamera::Viewport2DToWorldLine()", "cache dirty - must call Apply()");
481  }
482  // Find world vertices at near and far clip planes, and return line through them
483  TGLVertex3 nearClipWorld = ViewportToWorld(TGLVertex3(viewportX, viewportY, 0.0));
484  TGLVertex3 farClipWorld = ViewportToWorld(TGLVertex3(viewportX, viewportY, 1.0));
485  return TGLLine3(nearClipWorld, farClipWorld - nearClipWorld);
486 }
487 
488 ////////////////////////////////////////////////////////////////////////////////
489 /// Convert a 2D viewport position to 3D world line - the projection of the
490 /// viewport point into 3D space. Line runs from near to far camera clip planes
491 /// (the minimum and maximum visible depth). See also
492 /// TGLVertex3 TGLCamera::ViewportToWorld(const TGLVertex3 & viewportVertex) const
493 /// for 3D viewport -> 3D world vertex conversions.
494 /// See also OpenGL gluUnProject & glDepth documentation
495 ///
496 /// Camera must have valid frustum cache - call Apply() after last modification, before using
497 
499 {
500  return ViewportToWorld(viewport.GetX(), viewport.GetY());
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Find the intersection of projection of supplied viewport point (a 3D world
505 /// line - see ViewportToWorld) with supplied world plane. Returns std::pair
506 /// of Bool_t and TGLVertex3. If line intersects std::pair.first (Bool_t) is
507 /// kTRUE, and std::pair.second (TGLVertex) contains the intersection vertex.
508 /// If line does not intersect (line and plane parallel) std::pair.first
509 /// (Bool_t) if kFALSE, and std::pair.second (TGLVertex) is invalid.
510 ///
511 /// NOTE: The projection lines is extended for the plane intersection test
512 /// hence the intersection vertex can lie outside the near/far clip regions
513 /// (not visible)
514 ///
515 /// Camera must have valid frustum cache - call Apply() after last modification, before using
516 
517 std::pair<Bool_t, TGLVertex3> TGLCamera::ViewportPlaneIntersection(Double_t viewportX, Double_t viewportY,
518  const TGLPlane & worldPlane) const
519 {
520  TGLLine3 worldLine = ViewportToWorld(viewportX, viewportY);
521 
522  // Find intersection of line with plane
523  return Intersection(worldPlane, worldLine, kTRUE /* extended */ );
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Find the intersection of projection of supplied viewport TPoint (a 3D world
528 /// line - see ViewportToWorld) with supplied world plane. Returns std::pair
529 /// of bool and vertex. If line intersects
530 ///
531 /// Camera must have valid frustum cache - call Apply() after last modification, before using
532 
533 std::pair<Bool_t, TGLVertex3> TGLCamera::ViewportPlaneIntersection(const TPoint & viewport,
534  const TGLPlane & worldPlane) const
535 {
536  return ViewportPlaneIntersection(viewport.GetX(), viewport.GetY(), worldPlane);
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 /// Apply a 2D viewport delta (shift) to the projection of worldRef onto viewport,
541 /// returning the resultant world vector which equates to it. Useful for making
542 /// 3D world objects track mouse moves.
543 ///
544 /// Camera must have valid frustum cache - call Apply()
545 
547  Double_t viewportYDelta, TGLMatrix* modviewMat) const
548 {
549  if (fCacheDirty) {
550  Error("TGLCamera::ViewportDeltaToWorld()", "cache dirty - must call Apply()");
551  }
552  TGLVertex3 winVertex = WorldToViewport(worldRef, modviewMat);
553  winVertex.Shift(viewportXDelta, viewportYDelta, 0.0);
554  return (ViewportToWorld(winVertex, modviewMat) - worldRef);
555 }
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Calculate if the an object defined by world frame bounding box
559 /// is 'of interest' to the camera. This is defined as box:
560 ///
561 /// 1. intersecting completely or partially (kInside/kPartial) with
562 /// cameras interest box (fInterestBox)
563 /// 2. having significant length OR volume ratio compared to this
564 /// interest box
565 ///
566 /// If a box is 'of interest' returns kTRUE, kFALSE otherwise. See
567 /// TGLCamera::UpdateInterest() for more details of camera interest
568 /// box.
569 ///
570 /// Note: Length/volume ratios NOT dependent on the projected size
571 /// of box at current camera configuration as we do not want
572 /// continual changes. This is used when (re) populating the scene
573 /// with objects from external client.
574 ///
575 /// TODO: Might be more logical to move this test out to client -
576 /// and have accessor for fInterestBox instead?
577 
579 {
580  Bool_t interest = kFALSE;
581 
582  // *********** IMPORTANT - Bootstrapping the camera with empty scene
583  //
584  // Initially the camera can't be Setup() (limits etc) until the
585  // scene is populated and it has a valid bounding box to pass to
586  // the camera. However the scene can't be populated without
587  // knowing if objects sent are 'of interest' - which needs a camera
588  // interest box, made from a properly setup camera frustum - catch
589  // 22.
590  //
591  // To overcome this we track the largest box diagonal seen so far and
592  // regard anything over 0.001 of this as 'of interest'. This enables
593  // us to get a roughly populated scene with largest objects, setup
594  // the camera, and do first draw. We then do a
595  // TGLCamera::UpdateInterest() - which always return kTRUE, and
596  // thus fires an internal rebuild to fill scene properly and
597  // finally setup camera properly.
598 
599  if (fInterestBox.IsEmpty())
600  {
601  if (box.Diagonal() >= fLargestSeen * 0.001)
602  {
603  if (box.Diagonal() > fLargestSeen) {
604  fLargestSeen = box.Diagonal();
605  }
606  interest = kTRUE;
607  }
608  }
609  else
610  {
611  // Objects are of interest if the have length ratio c.f. the
612  // current interest box, and they at least partially overlap it.
613  // Some objects have zero volume BBs - e.g. single points - skip
614  // the test for these as there is no way to threshold on 0.
615  if (box.IsEmpty())
616  {
617  interest = kTRUE;
618  }
619  else
620  {
621  if (ignoreSize || box.Diagonal() / fInterestBox.Diagonal() > 0.0001)
622  interest = fInterestBox.Overlap(box) != Rgl::kOutside;
623  }
624  }
625 
626  return interest;
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 /// Update the internal interest box (fInterestBox) of the camera.
631 /// The interest box is an orientated bounding box, calculated as
632 /// an expanded container round the frustum. It is used to test if
633 /// if object bounding boxes are of interest (should be accepted
634 /// into viewer scene) for a camera - see TGLCamera::OfInterest()
635 ///
636 /// The interest box is updated if the frustum is no longer contained
637 /// in the existing one, or a new one calculated on the current frustum
638 /// differs significantly in volume (camera has been zoomed/dollyed
639 /// sizable amount).
640 ///
641 /// If the interest box is updated we return kTRUE - kFALSE otherwise.
642 
644 {
645  Bool_t exposedUpdate = kFALSE;
646 
647  // Construct a new interest box using the current frustum box as a basis
648  TGLBoundingBox frustumBox = Frustum(kTRUE);
649  TGLBoundingBox newInterestBox(frustumBox);
650 
651  // The Z(2) axis of frustum (near->far plane) can be quite shallow c.f. X(0)/Y(1)
652  // For interest box we want to expand to ensure it is at least size
653  // of smaller X/Y to avoid excessive interest box recalculations
654  TGLVector3 frustumExtents = frustumBox.Extents();
655  Double_t minBoxLength = frustumExtents.Mag() * fgInterestBoxExpansion;
656  newInterestBox.Scale(minBoxLength/frustumExtents[0], minBoxLength/frustumExtents[1], minBoxLength/frustumExtents[2]);
657 
658  // Calculate volume ratio of new to old
659  Double_t volRatio = 0.0;
660 
661  // If the interest box is empty the interest is ALWAYS updated
662  // See TGLCamera::OfInterest() comment on bootstrapping
663  if (!fInterestBox.IsEmpty()) {
664  volRatio = newInterestBox.Volume() / fInterestBox.Volume();
665  }
666 
667  // Update the existing interest box with new one if:
668  // 1. Volume ratio old/new interest has changed significantly
669  // 2. The current frustum is not inside existing interest
670  // 3. Force case (debugging)
671  if (volRatio > 8.0 || volRatio < 0.125 || fInterestBox.IsEmpty() ||
672  fInterestBox.Overlap(frustumBox) != Rgl::kInside || force)
673  {
675  fInterestBox = newInterestBox;
676 
677  // Frustum should be fully contained now
678  if (fInterestBox.Overlap(frustumBox) != Rgl::kInside) {
679  Error("TGLCamera::UpdateInterest", "update interest box does not contain frustum");
680  }
681 
682  exposedUpdate = kTRUE;
683 
684  // Keep the real frustum (true and box versions) as debugging aid
686  fInterestFrustumAsBox = frustumBox;
687 
688  if (gDebug>2 || force) {
689  Info("TGLCamera::UpdateInterest", "changed - volume ratio %f", volRatio );
690  }
691  }
692 
693  return exposedUpdate;
694 }
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// Clear out the existing interest box
698 
700 {
702 
703  // We also reset the bootstrapping variable - see
704  // TGLCamera::OfInterest comments.
705  fLargestSeen = 0.0;
706 }
707 
708 ////////////////////////////////////////////////////////////////////////////////
709 /// Adjust a passed REFERENCE value 'val', based on screenShift delta.
710 /// Two modifier flags ('mod1' / 'mod2' ) for sensitivity:
711 ///
712 /// - mod1 = kFALSE, mod2 = kFALSE : normal sensitivity (screenShift/screenShiftRange)
713 /// - mod1 = kTRUE, mod2 = kFALSE : 0.1x sensitivity
714 /// - mod1 = kTRUE, mod2 = kTRUE : 0.01x sensitivity
715 /// - mod1 = kFALSE, mod2 = kTRUE : 10.0x sensitivity
716 ///
717 /// 'val' is modified and clamped to 'min' / 'max' range.
718 /// Return bool kTRUE if val actually changed.
719 ///
720 /// Used as common interaction function for adjusting zoom/dolly etc
721 
723  Int_t screenShift, Int_t screenShiftRange,
724  Bool_t mod1, Bool_t mod2) const
725 {
726  if (screenShift == 0) {
727  return kFALSE;
728  }
729 
730  // Calculate a sensitivity based on passed modifiers
731  Double_t sens = val * static_cast<Double_t>(screenShift);
732 
733  if (mod1) {
734  sens *= 0.1;
735  if (mod2) {
736  sens *= 0.1;
737  }
738  } else {
739  if (mod2) {
740  sens *= 10.0;
741  }
742  }
743 
744  Double_t oldVal = val;
745  Double_t shift = sens / static_cast<Double_t>(screenShiftRange);
746  val -= shift;
747 
748  if (val < min) {
749  val = min;
750  }
751  else if (val > max) {
752  val = max;
753  }
754 
755  return val != oldVal;
756 }
757 
758 ////////////////////////////////////////////////////////////////////////////////
759 /// Adjust a passed screen value and apply modifiers.
760 /// See AdjustAndClampVal() for details.
761 
763  Bool_t mod1, Bool_t mod2) const
764 {
765  if (screenShift == 0)
766  return 0;
767 
768  // Calculate a sensitivity based on passed modifiers
769  Double_t sens = 1.0;
770 
771  if (mod1) {
772  sens *= 0.1;
773  if (mod2) {
774  sens *= 0.1;
775  }
776  } else {
777  if (mod2) {
778  sens *= 10.0;
779  }
780  }
781 
782  return sens * deltaFactor * screenShift;
783 }
784 
785 ////////////////////////////////////////////////////////////////////////////////
786 /// Draw out some debugging aids for the camera:
787 ///
788 /// 1. The frustum used to create the current interest box (RED)
789 /// 2. The same frustum as a squared off box (ORANGE)
790 /// 3. The axis aligned version of the frustum used as interest box basis (YELLOW)
791 /// 4. The current interest box (BLUE)
792 
794 {
795  // Interest box frustum base (RED)
796  glColor3d(1.0,0.0,0.0);
798 
799  // Interest box frustum as box (ORANGE)
800  glColor3d(1.0,0.65,0.15);
802 
803  // Current Interest box (BLUE)
804  glColor3d(0.0,0.0,1.0);
805  fInterestBox.Draw();
806 
807  // Previous interest (GREY)
808  glColor3d(.8,.7,.6);
810 
811  // Also draw line from current eye point out in eye direction - should not
812  // appear if calculated correctly
814  TGLVertex3 end = start + EyeDirection();
815  glColor3d(1.0,1.0,1.0);
816  glBegin(GL_LINES);
817  glVertex3dv(start.CArr());
818  glVertex3dv(end.CArr());
819  glEnd();
820 }
821 
822 ////////////////////////////////////////////////////////////////////////////////
823 /// Set camera center diffrent than scene center, if enable is kTRUE.
824 
826 {
827  if (fExternalCenter == enable)
828  return;
829 
830  fExternalCenter = enable;
831  if (fExternalCenter)
832  fCenter = &fExtCenter;
833  else
834  fCenter = &fDefCenter;
835 
838  TGLMatrix binv = fCamBase; binv.Invert();
839  fCamTrans = binv * bt;
840 
841  IncTimeStamp();
842 }
843 
844 ////////////////////////////////////////////////////////////////////////////////
845 /// Set camera center vector.
846 
848 {
849  if (fExternalCenter)
850  fExtCenter.Set(x, y, z);
851  else
852  fDefCenter.Set(x, y, z);
853 
856  TGLMatrix binv = fCamBase; binv.Invert();
857  fCamTrans = binv * bt;
858 
859  IncTimeStamp();
860 }
861 
862 ////////////////////////////////////////////////////////////////////////////////
863 /// Set camera center vector and do not keep the same combined
864 /// camera transformation matrix.
865 /// It appears as if the camera warped to the new center.
866 
868 {
869  if (fExternalCenter)
870  fExtCenter.Set(x, y, z);
871  else
872  fDefCenter.Set(x, y, z);
873 
875 
876  IncTimeStamp();
877 }
878 
879 ////////////////////////////////////////////////////////////////////////////////
880 /// Get angle between camera up axis.
881 
883 {
885  TGLVector3 zdir = fCamBase.GetBaseVec(3);
886  fCamBase.RotateIP(fwd);
887  return TMath::ACos(fwd*zdir);
888 }
889 
890 ////////////////////////////////////////////////////////////////////////////////
891 /// Truck the camera - 'move camera parallel to film plane'.
892 /// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
893 
895 {
896  if (xDelta != 0 || yDelta != 0)
897  {
898  fCamTrans.MoveLF(2, xDelta);
899  fCamTrans.MoveLF(3, yDelta);
900 
901  IncTimeStamp();
902  return kTRUE;
903  }
904  else
905  {
906  return kFALSE;
907  }
908 }
909 
910 ////////////////////////////////////////////////////////////////////////////////
911 /// Rotate the camera round view volume center established in Setup().
912 /// Arguments are:
913 /// - xDelta - horizontal delta (pixels)
914 /// - YDelta - vertical delta (pixels)
915 
916 Bool_t TGLCamera::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
917 {
918  Double_t vRotate = AdjustDelta(xDelta, TMath::TwoPi() / fViewport.Width(), mod1, mod2);
919  Double_t hRotate = AdjustDelta(yDelta, TMath::Pi() / fViewport.Height(), mod1, mod2);
920 
921  return RotateRad(hRotate, vRotate);
922 }
923 
924 ////////////////////////////////////////////////////////////////////////////////
925 /// Rotate camera around center.
926 
928 {
929  using namespace TMath;
930 
931  if (fWasArcBalled)
932  {
933  Double_t *M = fCamTrans.Arr();
934  Double_t d = M[2];
935  if (d > 1) d = 1;
936  else if (d < -1) d = -1; // Fix numerical errors
937 
938  Double_t theta = ASin(d);
939  Double_t phi = Abs(Cos(theta)) > 8.7e-6 ? ATan2(M[1], M[0]) : ATan2(-M[4], M[5]);
940 
941  M[0] = M[5] = M[10] = 1;
942  M[1] = M[2] = M[4] = M[6] = M[8] = M[9] = 0;
943  fCamTrans.RotateLF(1, 2, phi);
944  fCamTrans.RotateLF(1, 3, theta);
945  }
946 
947  if (hRotate != 0.0 || fWasArcBalled)
948  {
953 
954  Double_t deltaF = pos * fwd;
955  Double_t deltaU = pos * up;
956 
957  // up vector lock
958  TGLVector3 zdir = fCamBase.GetBaseVec(3);
959 
960  fCamBase.RotateIP(fwd);
961  Double_t theta = ACos(fwd*zdir);
962  if (theta + hRotate < fVAxisMinAngle)
963  hRotate = fVAxisMinAngle - theta;
964  else if (theta + hRotate > Pi() - fVAxisMinAngle)
965  hRotate = Pi() - fVAxisMinAngle - theta;
966 
967  fCamTrans.MoveLF(1, -deltaF);
968  fCamTrans.MoveLF(3, -deltaU);
969  fCamTrans.RotateLF(3, 1, hRotate);
970  fCamTrans.MoveLF(3, deltaU);
971  fCamTrans.MoveLF(1, deltaF);
972 
974  }
975  if (vRotate != 0.0)
976  {
977  fCamTrans.RotatePF(1, 2, -vRotate);
978  }
979 
980  IncTimeStamp();
981  return kTRUE;
982 }
983 
984 ////////////////////////////////////////////////////////////////////////////////
985 /// Rotate the camera round view volume center established in Setup().
986 /// Arguments are:
987 /// - xDelta - horizontal delta (pixels)
988 /// - YDelta - vertical delta (pixels)
989 
991 {
992  Double_t vRotate = AdjustDelta(xDelta, TMath::TwoPi() / fViewport.Width(), mod1, mod2);
993  Double_t hRotate = AdjustDelta(yDelta, TMath::Pi() / fViewport.Height(), mod1, mod2);
994 
995  return RotateArcBallRad(hRotate, vRotate);
996 }
997 
998 ////////////////////////////////////////////////////////////////////////////////
999 /// Rotate camera around center.
1000 
1002 {
1003  using namespace TMath;
1004 
1005  TGLVector3 fwd = fCamTrans.GetBaseVec(1);
1006  TGLVector3 lft = fCamTrans.GetBaseVec(2);
1009 
1010  Double_t deltaF = pos * fwd;
1011  Double_t deltaL = pos * lft;
1012  Double_t deltaU = pos * up;
1013 
1014  fCamTrans.MoveLF(1, -deltaF);
1015  fCamTrans.MoveLF(2, -deltaL);
1016  fCamTrans.MoveLF(3, -deltaU);
1017 
1018  if (hRotate != 0.0)
1019  {
1020  fCamTrans.RotateLF(3, 1, hRotate);
1021  }
1022  if (vRotate != 0.0)
1023  {
1024  fCamTrans.RotateLF(1, 2, -vRotate);
1025  }
1026 
1027  fCamTrans.MoveLF(3, deltaU);
1028  fCamTrans.MoveLF(2, deltaL);
1029  fCamTrans.MoveLF(1, deltaF);
1030 
1031  fWasArcBalled = kTRUE;
1032 
1033  IncTimeStamp();
1034  return kTRUE;
1035 }
1036 
1037 ////////////////////////////////////////////////////////////////////////////////
1038 /// Dolly the camera - 'move camera along eye line, retaining lens focal length'.
1039 /// Arguments are:
1040 ///
1041 /// - 'delta' - mouse viewport delta (pixels) - +ive dolly in, -ive dolly out
1042 /// - 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
1043 ///
1044 /// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
1045 
1047 {
1048  Double_t step = AdjustDelta(delta, fDollyDistance, mod1, mod2);
1049  if (step == 0)
1050  return kFALSE;
1051 
1052  fCamTrans.MoveLF(1, -step);
1053 
1054  IncTimeStamp();
1055  return kTRUE;
1056 }
const std::vector< UInt_t > & FaceVertices(EFace face) const
return a vector of face vertices y | | |________x / 3----—2 / /| /| z 7----—6 | | 0--—|-1 |/ |/ 4----...
TGLBoundingBox fInterestFrustum
previous interest box (DEBUG)
Definition: TGLCamera.h:62
void DrawDebugAids() const
Draw out some debugging aids for the camera:
Definition: TGLCamera.cxx:793
TGLMatrix fModVM
projection matrix (cached)
Definition: TGLCamera.h:99
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
TGLRect ViewportRect(const TGLBoundingBox &box, TGLBoundingBox::EFace face) const
Calculate viewport rectangle which just contains projection of single 'face' of world frame bounding ...
Definition: TGLCamera.cxx:329
Bool_t fExternalCenter
Definition: TGLCamera.h:78
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition: TGLCamera.h:43
TGLBoundingBox fInterestFrustumAsBox
frustum basis of current interest box - NOT a true BB! (DEBUG)
Definition: TGLCamera.h:63
Int_t Width() const
Definition: TGLUtil.h:455
const Double_t * v1
Definition: TArcBall.cxx:33
TGLVertex3 EyePoint() const
Return the camera eye point (vertex) in world space Camera must have valid frustum cache - call Apply...
Definition: TGLCamera.cxx:219
Double_t Invert()
Invert the matrix, returns determinant.
Definition: TGLUtil.cxx:999
Float_t theta
Definition: shapesAnim.C:5
void SetBaseVec(Int_t b, Double_t x, Double_t y, Double_t z)
Definition: TGLUtil.h:736
TGLVector3 GetTranslation() const
Return the translation component of matrix.
Definition: TGLUtil.cxx:822
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition: TGLUtil.h:600
#define assert(cond)
Definition: unittest.h:542
void RotateIP(TGLVector3 &v) const
Rotate vector in-place. Translation is not applied.
Definition: TGLUtil.cxx:1115
const Double_t * CArr() const
Definition: TGLUtil.h:129
TGLMatrix fCamTrans
Definition: TGLCamera.h:77
void Expand(Int_t x, Int_t y)
Expand the rect to encompass point (x,y)
Definition: TGLUtil.cxx:291
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
Double_t AdjustDelta(Double_t screenShift, Double_t deltaFactor, Bool_t mod1, Bool_t mod2) const
Adjust a passed screen value and apply modifiers.
Definition: TGLCamera.cxx:762
Double_t GetTheta() const
Get angle between camera up axis.
Definition: TGLCamera.cxx:882
TGLVector3 ViewportDeltaToWorld(const TGLVertex3 &worldRef, Double_t viewportXDelta, Double_t viewportYDelta, TGLMatrix *modviewMat=0) const
Apply a 2D viewport delta (shift) to the projection of worldRef onto viewport, returning the resultan...
Definition: TGLCamera.cxx:546
Double_t Mag() const
Definition: TGLUtil.h:303
Int_t NumVertices() const
int Int_t
Definition: RtypesCore.h:41
virtual Bool_t RotateRad(Double_t hRotate, Double_t vRotate)
Rotate camera around center.
Definition: TGLCamera.cxx:927
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Bool_t RotateArcBall(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Rotate the camera round view volume center established in Setup().
Definition: TGLCamera.cxx:990
TGLVector3 EyeDirection() const
Extract the camera eye direction (vector), running from EyePoint() Camera must have valid frustum cac...
Definition: TGLCamera.cxx:236
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
Double_t fLargestSeen
the interest box - created in UpdateInterest()
Definition: TGLCamera.h:106
void Set(Double_t x, Double_t y, Double_t z)
Definition: TGLUtil.h:213
TGLCamera()
Default base camera constructor.
Definition: TGLCamera.cxx:44
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
TFile * f
TGLVector3 fExtCenter
Definition: TGLCamera.h:81
Rgl::EOverlap Overlap(const TGLRect &other) const
Return overlap result (kInside, kOutside, kPartial) of this rect with 'other'.
Definition: TGLUtil.cxx:327
Double_t Volume() const
Double_t x[n]
Definition: legend1.C:17
Double_t Diagonal() const
void Set(const TGLVertex3 &origin, const TGLVector3 &zAxis, const TGLVector3 &xAxis=0)
Set matrix which when applied puts local origin at 'origin' and the local Z axis in direction 'z'...
Definition: TGLUtil.cxx:764
TGLBoundingBox fInterestBox
viewport (GL coords - origin bottom left)
Definition: TGLCamera.h:105
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:86
TGLVertex3 WorldToViewport(const TGLVertex3 &worldVertex, TGLMatrix *modviewMat=0) const
Convert a 3D world vertex to '3D' viewport (screen) one.
Definition: TGLCamera.cxx:403
void RotateLF(Int_t i1, Int_t i2, Double_t amount)
Rotate in local frame.
Definition: TGLUtil.cxx:925
int d
Definition: tornado.py:11
TGLRect fViewport
frustum planes (cached)
Definition: TGLCamera.h:103
void RotatePF(Int_t i1, Int_t i2, Double_t amount)
Rotate in parent frame. Does optimised version of MultLeft.
Definition: TGLUtil.cxx:942
void UpdateCache() const
largest box diagonal seen in OfInterest() - used when bootstrapping interest box
Definition: TGLCamera.cxx:108
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:426
TGLVertex3 ViewportToWorld(const TGLVertex3 &viewportVertex, TGLMatrix *modviewMat=0) const
Convert a '3D' viewport vertex to 3D world one.
Definition: TGLCamera.cxx:442
virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Rotate the camera round view volume center established in Setup().
Definition: TGLCamera.cxx:916
Double_t * Arr()
Definition: TGLUtil.h:668
3 component (x/y/z) vector class.
Definition: TGLUtil.h:250
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:454
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Double_t TwoPi()
Definition: TMath.h:45
void Draw(Bool_t solid=kFALSE) const
Draw the bounding box as either wireframe (default) of solid using current GL color.
Float_t z[5]
Definition: Ifit.C:16
void SetCenterVecWarp(Double_t x, Double_t y, Double_t z)
Set camera center vector and do not keep the same combined camera transformation matrix.
Definition: TGLCamera.cxx:867
Bool_t fWasArcBalled
Definition: TGLCamera.h:80
SCoord_t GetY() const
Definition: TPoint.h:50
REAL * vertex
Definition: triangle.c:512
TGLBoundingBox Frustum(Bool_t asBox=kTRUE) const
expansion c.f. aligned current frustum box
Definition: TGLCamera.cxx:171
TGLVector3 Extents() const
Definition: TPoint.h:33
Bool_t AdjustAndClampVal(Double_t &val, Double_t min, Double_t max, Int_t screenShift, Int_t screenShiftRange, Bool_t mod1, Bool_t mod2) const
Adjust a passed REFERENCE value 'val', based on screenShift delta.
Definition: TGLCamera.cxx:722
TGLPlane fFrustumPlanes[kPlanesPerFrustum]
object space clip matrix (cached)
Definition: TGLCamera.h:101
TGLMatrix fClipM
modelView matrix (cached)
Definition: TGLCamera.h:100
TGLVector3 GetBaseVec(Int_t b) const
Definition: TGLUtil.h:757
const TGLVertex3 & Vertex(UInt_t index) const
Double_t fDollyDistance
Definition: TGLCamera.h:91
double Pi()
Mathematical constants.
Definition: Math.h:68
TGLVector3 * fCenter
Definition: TGLCamera.h:84
Rgl::EOverlap ViewportOverlap(const TGLBoundingBox &box) const
Calculate overlap (kInside, kOutside, kPartial) of box projection onto viewport (as rect) against the...
Definition: TGLCamera.cxx:319
unsigned int UInt_t
Definition: RtypesCore.h:42
void SetExternalCenter(Bool_t x)
Set camera center diffrent than scene center, if enable is kTRUE.
Definition: TGLCamera.cxx:825
virtual Bool_t Truck(Double_t xDelta, Double_t yDelta)
Truck the camera - 'move camera parallel to film plane'.
Definition: TGLCamera.cxx:894
3D space, fixed length, line class, with direction / length 'vector', passing through point 'vertex'...
Definition: TGLUtil.h:391
Double_t ACos(Double_t)
Definition: TMath.h:445
virtual ~TGLCamera()
Base camera destructor.
Definition: TGLCamera.cxx:92
std::pair< Bool_t, TGLVertex3 > ViewportPlaneIntersection(Double_t viewportX, Double_t viewportY, const TGLPlane &worldPlane) const
Find the intersection of projection of supplied viewport point (a 3D world line - see ViewportToWorld...
Definition: TGLCamera.cxx:517
Double_t Cos(Double_t)
Definition: TMath.h:424
TGLVertex3 NearestOn(const TGLVertex3 &point) const
Return nearest point on plane.
Definition: TGLUtil.cxx:528
Double_t Pi()
Definition: TMath.h:44
TGLVector3 Norm() const
Definition: TGLUtil.h:561
void Scale(Double_t factor)
Isotropically scale bounding box along it's LOCAL axes, preserving center.
Float_t phi
Definition: shapesAnim.C:6
void SetCenterVec(Double_t x, Double_t y, Double_t z)
Set camera center vector.
Definition: TGLCamera.cxx:847
TGLMatrix fCamBase
Definition: TGLCamera.h:76
const Int_t * CArr() const
Definition: TGLUtil.h:448
TGLBoundingBox fPreviousInterestBox
Definition: TGLCamera.h:61
#define ClassImp(name)
Definition: Rtypes.h:279
double Double_t
Definition: RtypesCore.h:55
void SetCorner(Int_t x, Int_t y)
Definition: TGLUtil.h:485
Bool_t fCacheDirty
Definition: TGLCamera.h:95
void ResetInterest()
Clear out the existing interest box.
Definition: TGLCamera.cxx:699
void SetEmpty()
Set bounding box empty - all vertices at (0,0,0)
Double_t y[n]
Definition: legend1.C:17
Float_t fVAxisMinAngle
Definition: TGLCamera.h:92
Bool_t UpdateInterest(Bool_t force)
Update the internal interest box (fInterestBox) of the camera.
Definition: TGLCamera.cxx:643
virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
Dolly the camera - 'move camera along eye line, retaining lens focal length'.
Definition: TGLCamera.cxx:1046
Rgl::EOverlap FrustumOverlap(const TGLBoundingBox &box) const
Calculate overlap (kInside, kOutside, kPartial) of box with camera frustum Camera must have valid fru...
Definition: TGLCamera.cxx:275
Double_t X() const
Definition: TGLUtil.h:122
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
Rgl::EOverlap Overlap(const TGLPlane &plane) const
Find overlap (Inside, Outside, Partial) of plane c.f. bounding box.
SCoord_t GetX() const
Definition: TPoint.h:49
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
TGLVertex3 FrustumCenter() const
Find the center of the camera frustum from intersection of planes This method will work even with par...
Definition: TGLCamera.cxx:251
Double_t Y() const
Definition: TGLUtil.h:124
EOverlap
Definition: TGLUtil.h:37
TGLMatrix fProjM
no-pick projection matrix (cached)
Definition: TGLCamera.h:98
Double_t ASin(Double_t)
Definition: TMath.h:439
Int_t Height() const
Definition: TGLUtil.h:457
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
TGLVector3 fDefCenter
Definition: TGLCamera.h:82
Double_t Z() const
Definition: TGLUtil.h:126
Bool_t IsEmpty() const
void Shift(TGLVector3 &shift)
Offset a vertex by vector 'shift'.
Definition: TGLUtil.cxx:93
void SetViewport(const TGLRect &viewport)
Set viewport extents from passed 'viewport' rect.
Definition: TGLCamera.cxx:99
TGLVector3 WorldDeltaToViewport(const TGLVertex3 &worldRef, const TGLVector3 &worldDelta) const
Convert a 3D vector worldDelta (shift) about vertex worldRef to a viewport (screen) '3D' vector...
Definition: TGLCamera.cxx:426
const Bool_t kTRUE
Definition: Rtypes.h:91
Bool_t OfInterest(const TGLBoundingBox &box, Bool_t ignoreSize) const
Calculate if the an object defined by world frame bounding box is 'of interest' to the camera...
Definition: TGLCamera.cxx:578
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:529
void IncTimeStamp()
Definition: TGLCamera.h:124
const Double_t * CArr() const
Definition: TGLUtil.h:667
static const Double_t fgInterestBoxExpansion
frustum basis (as box) of current interest box (DEBUG)
Definition: TGLCamera.h:65
void MoveLF(Int_t ai, Double_t amount)
Translate in local frame.
Definition: TGLUtil.cxx:841
void Set(const TGLPlane &other)
Assign from other.
Definition: TGLUtil.cxx:453
virtual Bool_t RotateArcBallRad(Double_t hRotate, Double_t vRotate)
Rotate camera around center.
Definition: TGLCamera.cxx:1001
std::pair< Bool_t, TGLLine3 > Intersection(const TGLPlane &p1, const TGLPlane &p2)
Find 3D line interestion of this plane with 'other'.
Definition: TGLUtil.cxx:544