Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLOrthoCamera.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 "TMath.h"
13 
14 #include "TGLOrthoCamera.h"
15 #include "TGLIncludes.h"
16 #include "TGLUtil.h"
17 
18 
19 /** \class TGLOrthoCamera
20 \ingroup opengl
21 Orthographic projection camera. Currently limited to three types
22 defined at construction time - kXOY, kXOZ, kZOY - where this refers
23 to the viewport plane axis - e.g. kXOY has X axis horizontal, Y
24 vertical - i.e. looking down Z axis with Y vertical.
25 
26 The plane types restriction could easily be removed to supported
27 arbitrary ortho projections along any axis/orientation with free
28 rotations about them.
29 */
30 
31 ClassImp(TGLOrthoCamera);
32 
33 UInt_t TGLOrthoCamera::fgZoomDeltaSens = 500;
34 
35 ////////////////////////////////////////////////////////////////////////////////
36 /// Construct kXOY orthographic camera.
37 
38 TGLOrthoCamera::TGLOrthoCamera() :
39  TGLCamera(TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)),
40  fType(kXOY),
41  fEnableRotate(kFALSE), fDollyToZoom(kTRUE),
42  fZoomMin(0.001), fZoomDefault(0.78), fZoomMax(1000.0),
43  fVolume(TGLVertex3(-100.0, -100.0, -100.0), TGLVertex3(100.0, 100.0, 100.0)),
44  fZoom(1.0)
45 {
46  Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
47 }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Construct orthographic camera.
51 
52 TGLOrthoCamera::TGLOrthoCamera(EType type, const TGLVector3 & hAxis, const TGLVector3 & vAxis) :
53  TGLCamera(hAxis, vAxis),
54  fType(type),
55  fEnableRotate(kFALSE), fDollyToZoom(kTRUE),
56  fZoomMin(0.001), fZoomDefault(0.78), fZoomMax(1000.0),
57  fVolume(TGLVertex3(-100.0, -100.0, -100.0), TGLVertex3(100.0, 100.0, 100.0)),
58  fZoom(1.0)
59 {
60  Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Destroy orthographic camera.
65 
66 TGLOrthoCamera::~TGLOrthoCamera()
67 {
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// Setup camera limits suitable to view the world volume defined by 'box'
72 /// and call Reset() to initialise camera.
73 
74 void TGLOrthoCamera::Setup(const TGLBoundingBox & box, Bool_t reset)
75 {
76  fVolume = box;
77 
78  if (fExternalCenter == kFALSE)
79  {
80  if (fFixDefCenter)
81  {
82  SetCenterVec(fFDCenter.X(), fFDCenter.Y(), fFDCenter.Z());
83  }
84  else
85  {
86  TGLVertex3 center = box.Center();
87  SetCenterVec(center.X(), center.Y(), center.Z());
88  }
89  }
90  if (reset)
91  Reset();
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Reset the camera to defaults - trucking, zooming to reframe the world volume
96 /// established in Setup(). Note: limits defined in Setup() are not adjusted.
97 
98 void TGLOrthoCamera::Reset()
99 {
100  TGLVector3 e = fVolume.Extents();
101  switch (fType) {
102  case kXOY:
103  case kXnOY:
104  {
105  // X -> X, Y -> Y, Z -> Z
106  fDefXSize = e.X(); fDefYSize = e.Y();
107  break;
108  }
109  case kXOZ:
110  case kXnOZ:
111  {
112  // X -> X, Z -> Y, Y -> Z
113  fDefXSize = e.X(); fDefYSize = e.Z();
114  break;
115  }
116 
117  case kZOY:
118  case kZnOY:
119  {
120  // Z -> X, Y -> Y, X -> Z
121  fDefXSize = e.Z(); fDefYSize = e.Y();
122  break;
123  }
124  case kZOX:
125  case kZnOX:
126  {
127  // Z -> X, X -> Y, Y -> Z
128  fDefXSize = e.Z(); fDefYSize = e.X();
129  break;
130  }
131  }
132 
133  fDollyDefault = 1.25*0.5*TMath::Sqrt(3)*fVolume.Extents().Mag();
134  fDollyDistance = 0.002 * fDollyDefault;
135  fZoom = fZoomDefault;
136  fCamTrans.SetIdentity();
137  fCamTrans.MoveLF(1, fDollyDefault);
138  IncTimeStamp();
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// Dolly the camera.
143 /// By default the dolly is reinterpreted to zoom, but it can be
144 /// changed by modifying the fDollyToZoom data-member.
145 
146 Bool_t TGLOrthoCamera::Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
147 {
148  if (fDollyToZoom) {
149  return Zoom(delta, mod1, mod2);
150  } else {
151  return TGLCamera::Dolly(delta, mod1, mod2);
152  }
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Zoom the camera - 'adjust lens focal length, retaining camera position'.
157 /// Arguments are:
158 ///
159 /// - 'delta' - mouse viewport delta (pixels) - +ive zoom in, -ive zoom out
160 /// - 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
161 ///
162 /// For an orthographic camera dollying and zooming are identical and both equate
163 /// logically to a rescaling of the viewport limits - without center shift.
164 /// There is no perspective foreshortening or lens 'focal length'.
165 ///
166 /// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
167 
168 Bool_t TGLOrthoCamera::Zoom(Int_t delta, Bool_t mod1, Bool_t mod2)
169 {
170  if (AdjustAndClampVal(fZoom, fZoomMin, fZoomMax, -delta*2, fgZoomDeltaSens, mod1, mod2))
171  {
172  IncTimeStamp();
173  return kTRUE;
174  }
175  else
176  {
177  return kFALSE;
178  }
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Set minimum zoom factor. If current zoom is less than z it is
183 /// set to z.
184 
185 void TGLOrthoCamera::SetZoomMin(Double_t z)
186 {
187  fZoomMin = z;
188  if (fZoom < fZoomMin) {
189  fZoom = fZoomMin;
190  IncTimeStamp();
191  }
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Set maximum zoom factor. If current zoom is greater than z it
196 /// is set to z.
197 
198 void TGLOrthoCamera::SetZoomMax(Double_t z)
199 {
200  fZoomMax = z;
201  if (fZoom > fZoomMax) {
202  fZoom = fZoomMax;
203  IncTimeStamp();
204  }
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// Truck the camera - 'move camera parallel to film plane'.
209 /// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
210 
211 Bool_t TGLOrthoCamera::Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
212 {
213  Double_t xstep = 2.0 * xDelta / fProjM[0] / fViewport.Width();
214  Double_t ystep = 2.0 * yDelta / fProjM[5] / fViewport.Height();
215 
216  xstep = AdjustDelta(xstep, 1.0, mod1, mod2);
217  ystep = AdjustDelta(ystep, 1.0, mod1, mod2);
218 
219  return Truck(-xstep, -ystep);
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// Rotate the camera - 'swivel round the view volume center'.
224 /// Returns kTRUE is redraw required (camera change), kFALSE otherwise.
225 
226 Bool_t TGLOrthoCamera::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
227 {
228  if (fEnableRotate)
229  return TGLCamera::Rotate(xDelta, yDelta, mod1, mod2);
230  else
231  return kFALSE;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Apply the camera to the current GL context, setting the viewport, projection
236 /// and modelview matrices. After this vertices etc can be directly entered
237 /// in the world frame. This also updates the cached frustum values, enabling
238 /// all the projection, overlap tests etc defined in TGLCamera to be used.
239 ///
240 /// Arguments are:
241 /// - 'box' - view volume box - ignored for ortho camera. Assumed to be same
242 /// as one passed to Setup().
243 /// - 'pickRect' - optional picking rect. If non-null, restrict drawing to this
244 /// viewport rect.
245 
246 void TGLOrthoCamera::Apply(const TGLBoundingBox & /*box*/,
247  const TGLRect * pickRect) const
248 {
249  glViewport(fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height());
250 
251  if(fViewport.Width() == 0 || fViewport.Height() == 0)
252  {
253  glMatrixMode(GL_PROJECTION);
254  glLoadIdentity();
255  glMatrixMode(GL_MODELVIEW);
256  glLoadIdentity();
257  return;
258  }
259 
260  glMatrixMode(GL_PROJECTION);
261  glLoadIdentity();
262 
263  // Load up any picking rect
264  if (pickRect)
265  {
266  TGLRect rect(*pickRect);
267  WindowToViewport(rect);
268  gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
269  (Int_t*) fViewport.CArr());
270  }
271 
272  Double_t halfRangeX, halfRangeY;
273  if (fDefYSize*fViewport.Width()/fDefXSize > fViewport.Height()) {
274  halfRangeY = 0.5 *fDefYSize;
275  halfRangeX = halfRangeY*fViewport.Width()/fViewport.Height();
276  } else {
277  halfRangeX = 0.5 *fDefXSize;
278  halfRangeY = halfRangeX*fViewport.Height()/fViewport.Width();
279  }
280 
281  halfRangeX /= fZoom;
282  halfRangeY /= fZoom;
283 
284  fNearClip = 0.05*fDollyDefault;
285  fFarClip = 2.0*fDollyDefault;
286  glOrtho(-halfRangeX, halfRangeX,
287  -halfRangeY, halfRangeY,
288  fNearClip, fFarClip);
289 
290  if (!pickRect) glGetDoublev(GL_PROJECTION_MATRIX, fLastNoPickProjM.Arr());
291 
292  // ii) setup modelview
293  glMatrixMode(GL_MODELVIEW);
294  glLoadIdentity();
295  TGLMatrix mx = fCamBase*fCamTrans;
296  TGLVector3 pos = mx.GetTranslation();
297  TGLVector3 fwd = mx.GetBaseVec(1);
298  TGLVector3 center = pos - fwd;
299  TGLVector3 up = mx.GetBaseVec(3);
300 
301  gluLookAt(pos[0], pos[1], pos[2],
302  center[0], center[1], center[2],
303  up[0], up[1], up[2]);
304 
305  if (fCacheDirty) UpdateCache();
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Configure the camera state.
310 /// - zoom - set directly (default = 0.78);
311 /// - dolly - additional move along the camera forward direction;
312 /// - center - new camera center (can be 0 for no change);
313 /// - hRotate - additional "up/down" rotation in radians;
314 /// - vRotate - additional "left/right" rotation in radians.
315 
316 void TGLOrthoCamera::Configure(Double_t zoom, Double_t dolly, Double_t center[3],
317  Double_t hRotate, Double_t vRotate)
318 {
319  fZoom = zoom;
320 
321  if (center)
322  SetCenterVec(center[0], center[1], center[2]);
323 
324  fCamTrans.MoveLF(1, dolly);
325  RotateRad(hRotate, vRotate);
326 
327  IncTimeStamp();
328 }