Logo ROOT   6.18/05
Reference Guide
TGLPerspectiveCamera.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
13#include "TGLUtil.h"
14#include "TGLIncludes.h"
15
16#include "TMath.h"
17#include "TError.h"
18
19/** \class TGLPerspectiveCamera
20\ingroup opengl
21Perspective projection camera - with characteristic foreshortening.
22*/
23
25
30
31////////////////////////////////////////////////////////////////////////////////
32/// Construct default XOZ perspective camera
33
35 TGLCamera(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
36 fFOV(fgFOVDefault)
37{
38 Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
40}
41
42////////////////////////////////////////////////////////////////////////////////
43/// Construct perspective camera
44
46 TGLCamera(hAxes, vAxes),
47 fFOV(fgFOVDefault)
48{
49 Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
51}
52
53////////////////////////////////////////////////////////////////////////////////
54/// Destroy perspective camera
55
57{
58}
59
60////////////////////////////////////////////////////////////////////////////////
61/// Setup camera limits suitable to view the world volume defined by 'box'
62/// and call Reset() to initialise camera.
63
65{
67 {
68 if (fFixDefCenter)
69 {
71 }
72 else
73 {
74 TGLVertex3 center = box.Center();
75 SetCenterVec(center.X(), center.Y(), center.Z());
76 }
77 }
78
79 // At default FOV, the dolly should be set so as to encapsulate the scene.
80 TGLVector3 extents = box.Extents();
81 Int_t sortInd[3];
82 TMath::Sort(3, extents.CArr(), sortInd);
83 Double_t size = TMath::Hypot(extents[sortInd[0]], extents[sortInd[1]]);
85
86 fDollyDefault = size / (2.0*TMath::Tan(fov*TMath::Pi()/360));
88
89 if (reset)
90 {
91 Reset();
92 }
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Reset the camera to defaults - reframe the world volume established in Setup()
97/// in default state. Note: limits defined in Setup() are not adjusted.
98
100{
102
105
106 IncTimeStamp();
107}
108
109////////////////////////////////////////////////////////////////////////////////
110/// Zoom the camera - 'adjust lens focal length, retaining camera position'.
111/// Arguments are:
112///
113/// - 'delta' - mouse viewport delta (pixels) - +ive zoom in, -ive zoom out
114/// - 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
115///
116/// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
117
119{
120 // TODO: Bring all mouse handling into camera classes - would simplify interface and
121 // remove these non-generic cases.
122 if (AdjustAndClampVal(fFOV, fgFOVMin, fgFOVMax, delta, fgFOVDeltaSens, mod1, mod2)) {
123 IncTimeStamp();
124 return kTRUE;
125 } else {
126 return kFALSE;
127 }
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Truck the camera - 'move camera parallel to film plane'.
132/// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
133
135{
136 Double_t lenMidClip = 0.5 * (fFarClip + fNearClip) * TMath::Tan(0.5*fFOV*TMath::DegToRad());
137
138 Double_t xstep = xDelta * lenMidClip / fViewport.Height();
139 Double_t ystep = yDelta * lenMidClip / fViewport.Height();
140
141 xstep = AdjustDelta(xstep, 1.0, mod1, mod2);
142 ystep = AdjustDelta(ystep, 1.0, mod1, mod2);
143
144 return Truck(-xstep, -ystep);
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Apply the camera to the current GL context, setting the viewport, projection
149/// and modelview matrices. After this vertices etc can be directly entered
150/// in the world frame. This also updates the cached frustum values, enabling
151/// all the projection, overlap tests etc defined in TGLCamera to be used.
152///
153/// Arguments are:
154/// - 'box' - view volume box - used to adjust near/far clipping
155/// - 'pickRect' - optional picking rect. If non-null, restrict drawing to this
156/// viewport rect.
157
159 const TGLRect * pickRect) const
160{
161 // TODO: If we retained the box from Setup first argument could be dropped?
162
163 // MT This whole thing is convoluted. We can calculate camera position
164 // and look-at direction without calling unproject and seeking clipping
165 // plane intersection.
166 // Besides, this would give as a proper control over camera transformation
167 // matrix.
168 //
169 // Much better since Oct 2007, the clipping planes stuff still
170 // needs to be cleaned.
171
172 glViewport(fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height());
173
174 if(fViewport.Width() == 0 || fViewport.Height() == 0)
175 {
176 glMatrixMode(GL_PROJECTION);
177 glLoadIdentity();
178 glMatrixMode(GL_MODELVIEW);
179 glLoadIdentity();
180 return;
181 }
182
183 glMatrixMode(GL_PROJECTION);
184 glLoadIdentity();
185
186 // To find decent near/far clip plane distances we construct the
187 // frustum thus:
188 // i) first setup perspective with arbitrary near/far planes
189 gluPerspective(fFOV, fViewport.Aspect(), 1.0, 1000.0);
190 // printf("FIRST STEP FOV %f, aspect %f, nearClip %f, farClip %f \n", fFOV, fViewport.Aspect(), 1., 1000.);
191
192 // ii) setup modelview
193 glMatrixMode(GL_MODELVIEW);
194 glLoadIdentity();
196 TGLVector3 pos = mx.GetTranslation();
197 TGLVector3 fwd = mx.GetBaseVec(1);
198 TGLVector3 center = pos - fwd;
199 TGLVector3 up = mx.GetBaseVec(3);
200
201 gluLookAt(pos[0], pos[1], pos[2],
202 center[0], center[1], center[2],
203 up[0], up[1], up[2]);
204
205 // iii) update the cached frustum planes so we can get eye point/direction
206 Bool_t modifiedCache = kFALSE;
207 if (fCacheDirty) {
208 UpdateCache();
209 modifiedCache = kTRUE;
210 }
211
212 // iv) Create a clip plane, using the eye direction as normal, passing through eye point
213 TGLPlane clipPlane(EyeDirection(), EyePoint());
214 fCacheDirty = modifiedCache;
215
216 // v) find the near/far distance which just encapsulate the passed bounding box vertexes
217 // not ideal - should really find the nearest/further points on box surface
218 // which intersect frustum - however this much more complicated
219 Double_t currentDist;
220 for (UInt_t i=0; i<8; i++) {
221 currentDist = clipPlane.DistanceTo(sceneBox[i]);
222 if (i==0)
223 {
224 fNearClip = currentDist;
226 }
227 if (currentDist < fNearClip)
228 fNearClip = currentDist;
229 if (currentDist > fFarClip)
230 fFarClip = currentDist;
231 }
232 // Add 1% each way to avoid any rounding conflicts with drawn objects
233 fNearClip *= 0.49; // 0.99; TODO Look at - avoid removing clipping + manip objs
234 fFarClip *= 2.01; // 1.01;
235 if (fFarClip < 2.0)
236 fFarClip = 2.0;
237 if (fNearClip < fFarClip/1000.0)
238 fNearClip = fFarClip/1000.0;
239
240 glMatrixMode(GL_PROJECTION);
241 glLoadIdentity();
242
243 // vi) Load up any picking rect and reset the perspective using the
244 // correct near/far clips distances
245 if (pickRect)
246 {
247 TGLRect rect(*pickRect);
248 WindowToViewport(rect);
249 gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
250 (Int_t*) fViewport.CArr());
251 gluPerspective(fFOV, fViewport.Aspect(), fNearClip, fFarClip);
252 }
253 else
254 {
255 gluPerspective(fFOV, fViewport.Aspect(), fNearClip, fFarClip);
256 glGetDoublev(GL_PROJECTION_MATRIX, fLastNoPickProjM.Arr());
257 }
258
259 glMatrixMode(GL_MODELVIEW);
260
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Configure the camera state.
266/// - fov - set directly field-of-view in degrees (default = 30);
267/// - dolly - additional move along the camera forward direction;
268/// - center - new camera center (can be 0 for no change);
269/// - hRotate - additional "up/down" rotation in radians;
270/// - vRotate - additional "left/right" rotation in radians.
271
273 Double_t hRotate, Double_t vRotate)
274{
275 fFOV = fov;
276
277 // Don't generally constrain external configuration
278 // However exceeding the vRotate limits or silly FOV values will
279 // cause very weird behaviour or projections so fix these
280
281 if (fFOV > 170.0) {
282 fFOV = 170.0;
283 } else if (fFOV < 0.1) {
284 fFOV = 0.1;
285 }
286
287 if (center)
288 SetCenterVec(center[0], center[1], center[2]);
289
290 fCamTrans.MoveLF(1, dolly);
291 RotateRad(hRotate, vRotate);
292
293 IncTimeStamp();
294}
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
Concrete class describing an orientated (free) or axis aligned box of 8 vertices.
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition: TGLCamera.h:44
TGLMatrix fLastNoPickProjM
timestamp
Definition: TGLCamera.h:97
TGLVector3 EyeDirection() const
Extract the camera eye direction (vector), running from EyePoint() Camera must have valid frustum cac...
Definition: TGLCamera.cxx:236
virtual Bool_t RotateRad(Double_t hRotate, Double_t vRotate)
Rotate camera around center.
Definition: TGLCamera.cxx:927
Bool_t fCacheDirty
Definition: TGLCamera.h:95
TGLMatrix fCamBase
Definition: TGLCamera.h:76
void IncTimeStamp()
Definition: TGLCamera.h:124
Double_t fNearClip
current camera center
Definition: TGLCamera.h:86
TGLMatrix fCamTrans
Definition: TGLCamera.h:77
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
TGLRect fViewport
frustum planes (cached)
Definition: TGLCamera.h:103
Double_t fDollyDefault
last applied far-clip
Definition: TGLCamera.h:90
void WindowToViewport(Int_t &, Int_t &y) const
Definition: TGLCamera.h:198
Double_t fDollyDistance
Definition: TGLCamera.h:91
void UpdateCache() const
largest box diagonal seen in OfInterest() - used when bootstrapping interest box
Definition: TGLCamera.cxx:108
Bool_t fExternalCenter
Definition: TGLCamera.h:78
Bool_t fFixDefCenter
Definition: TGLCamera.h:79
void SetCenterVec(Double_t x, Double_t y, Double_t z)
Set camera center vector.
Definition: TGLCamera.cxx:847
Double_t fFarClip
last applied near-clip
Definition: TGLCamera.h:87
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 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
TGLVector3 fFDCenter
Definition: TGLCamera.h:83
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition: TGLUtil.h:597
void MoveLF(Int_t ai, Double_t amount)
Translate in local frame.
Definition: TGLUtil.cxx:814
void SetIdentity()
Set matrix to identity.
Definition: TGLUtil.cxx:766
Double_t * Arr()
Definition: TGLUtil.h:664
TGLVector3 GetBaseVec(Int_t b) const
Definition: TGLUtil.h:753
TGLVector3 GetTranslation() const
Return the translation component of matrix.
Definition: TGLUtil.cxx:795
Perspective projection camera - with characteristic foreshortening.
virtual void Configure(Double_t fov, Double_t dolly, Double_t center[3], Double_t hRotate, Double_t vRotate)
Configure the camera state.
virtual void Apply(const TGLBoundingBox &box, const TGLRect *pickRect=0) const
Apply the camera to the current GL context, setting the viewport, projection and modelview matrices.
TGLPerspectiveCamera()
Construct default XOZ perspective camera.
virtual ~TGLPerspectiveCamera()
Destroy perspective camera.
virtual Bool_t Zoom(Int_t delta, Bool_t mod1, Bool_t mod2)
Zoom the camera - 'adjust lens focal length, retaining camera position'.
static Double_t fgFOVDefault
virtual void Reset()
Reset the camera to defaults - reframe the world volume established in Setup() in default state.
virtual void Setup(const TGLBoundingBox &box, Bool_t reset=kTRUE)
Setup camera limits suitable to view the world volume defined by 'box' and call Reset() to initialise...
virtual Bool_t Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
Truck the camera - 'move camera parallel to film plane'.
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:524
Double_t DistanceTo(const TGLVertex3 &vertex) const
Distance from plane to vertex.
Definition: TGLUtil.cxx:493
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:421
Int_t Y() const
Definition: TGLUtil.h:447
const Int_t * CArr() const
Definition: TGLUtil.h:442
Int_t Height() const
Definition: TGLUtil.h:451
Int_t Width() const
Definition: TGLUtil.h:449
Int_t X() const
Definition: TGLUtil.h:445
Double_t Aspect() const
Definition: TGLUtil.h:499
3 component (x/y/z) vector class.
Definition: TGLUtil.h:247
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:83
Double_t X() const
Definition: TGLUtil.h:118
Double_t Z() const
Definition: TGLUtil.h:122
Double_t Y() const
Definition: TGLUtil.h:120
const Double_t * CArr() const
Definition: TGLUtil.h:125
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
constexpr Double_t DegToRad()
Conversion from degree to radian:
Definition: TMath.h:82
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Double_t Hypot(Double_t x, Double_t y)
Definition: TMath.cxx:57
constexpr Double_t Pi()
Definition: TMath.h:38
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMathBase.h:362
Double_t Tan(Double_t)
Definition: TMath.h:633