qtopengl_camera.cpp
Go to the documentation of this file.
1 
7 #include "qtopengl_camera.h"
8 #include <QPoint>
9 #include <argos3/core/utility/math/quaternion.h>
10 #include <argos3/core/utility/logging/argos_log.h>
11 #include <argos3/core/simulator/simulator.h>
12 #include <argos3/core/simulator/space/space.h>
13 
14 namespace argos {
15 
16  static const Real MOVE_GAIN = 0.005 / Exp(0.02);
17  static const Real ROTATE_GAIN = 0.01 / Exp(-0.02);
18  static const Real FOCAL_LENGTH_GAIN = 0.0075;
19  static const Real FOCAL_LENGTH_OFFSET = 0.0575;
20 
21  /****************************************/
22  /****************************************/
23 
25  /* Get positional attributes */
26  GetNodeAttribute(t_tree, "position", Position);
27  GetNodeAttribute(t_tree, "look_at", Target);
28  /* Was the up vector specified? */
29  if(!NodeAttributeExists(t_tree, "up")) {
30  /* Calculate the Left vector
31  It is located on a plane parallel to XY
32  It is perpendicular to the projection of Forward on that plane
33  */
34  CVector3 cForward((Target - Position).Normalize());
35  CVector3 cLeft;
36  if(cForward.GetX() != 0 || cForward.GetY() != 0) {
37  CVector2 cLeftXY(cForward.GetX(), cForward.GetY());
38  cLeftXY.Perpendicularize();
39  cLeft.Set(cLeftXY.GetX(), cLeftXY.GetY(), 0.0f);
40  cLeft.Normalize();
41  }
42  else {
43  LOGERR << "[WARNING] The given camera position is ambiguous, "
44  << "and a standard attitude has been used to calculate it. "
45  << "Consider specifying the \"up\" vector in the .argos file "
46  << "for more precise placement."
47  << std::endl;
48  cLeft = CVector3::Y;
49  }
50  /* Calculate the Up vector with a cross product */
51  Up = cForward;
52  Up.CrossProduct(cLeft).Normalize();
53  }
54  else {
55  /* Get Up vector */
56  GetNodeAttribute(t_tree, "up", Up);
57  Up.Normalize();
58  }
59  /* Get focal length */
60  Real fValue;
61  GetNodeAttributeOrDefault<Real>(t_tree, "lens_focal_length", fValue, 20.0f);
62  LensFocalLength = fValue * 0.001f;
64  }
65 
66  /****************************************/
67  /****************************************/
68 
70  YFieldOfView = ToDegrees(2.0f * ATan2(0.027f * 0.5f, LensFocalLength));
71  }
72 
73  /****************************************/
74  /****************************************/
75 
77  m_bEnableTimeline(false),
78  m_bHasTimeline(false),
79  m_unLoop(0) {
80  /* automatically place the cameras at 30 degree increments
81  around the arena */
82  const CVector3& cArenaSize =
84  const CVector3& cArenaCenter =
86  for(UInt32 un_index = 0;
87  un_index < m_arrPlacements.size();
88  ++un_index) {
90  cAngle *= static_cast<Real>(un_index);
91  m_arrPlacements[un_index].Position =
92  CVector3::X * cArenaSize.Length();
93  m_arrPlacements[un_index].Position.RotateZ(cAngle);
94  m_arrPlacements[un_index].Position +=
95  (cArenaCenter + CVector3::Z * cArenaSize.GetZ());
96  m_arrPlacements[un_index].Target = cArenaCenter;
97  m_arrPlacements[un_index].Target.SetZ(0);
98  /* (position - target).Normalize() ? */
99  m_arrPlacements[un_index].Up = CVector3::Z;
100  m_arrPlacements[un_index].LensFocalLength =
101  (FOCAL_LENGTH_GAIN * Cos(4.0 * cAngle) + FOCAL_LENGTH_OFFSET);
102  m_arrPlacements[un_index].CalculateYFieldOfView();
103  }
105  }
106 
107  /****************************************/
108  /****************************************/
109 
111 
112  /****************************************/
113  /****************************************/
114 
116  try {
117  if(NodeExists(t_tree, "placements")) {
118  TConfigurationNode& tPlacementsNode = GetNode(t_tree, "placements");
119  /* Parse the placement nodes */
120  TConfigurationNodeIterator itPlacement("placement");
121  for(itPlacement = itPlacement.begin(&tPlacementsNode);
122  itPlacement != itPlacement.end();
123  ++itPlacement) {
124  UInt32 unIndex = 0;
125  GetNodeAttribute(*itPlacement, "index", unIndex);
126  if(unIndex < m_arrPlacements.size()) {
127  m_arrPlacements[unIndex].Init(*itPlacement);
128  }
129  else {
130  THROW_ARGOSEXCEPTION("Placement index is out of bounds");
131  }
132  }
133  }
134  /* Parse the timeline nodes */
135  if(NodeExists(t_tree, "timeline")) {
136  m_bHasTimeline = true;
137  TConfigurationNode& tTimelineNode = GetNode(t_tree, "timeline");
138  /* When does the timeline loop */
139  GetNodeAttributeOrDefault(tTimelineNode, "loop", m_unLoop, m_unLoop);
140  /* Parse the placement nodes */
141  TConfigurationNodeIterator itTimelineElement;
142  UInt32 unLastStep = 0;
143  UInt32 unKeyframeStep = 0;
144  UInt32 unKeyframePlacement = 0;
145  for(itTimelineElement = itTimelineElement.begin(&tTimelineNode);
146  itTimelineElement != itTimelineElement.end();
147  ++itTimelineElement) {
148  /* Create timeline item */
149  if(itTimelineElement->Value() == "keyframe") {
150  GetNodeAttribute(*itTimelineElement, "placement", unKeyframePlacement);
151  GetNodeAttribute(*itTimelineElement, "step", unKeyframeStep);
152  if(unKeyframeStep < unLastStep) {
153  THROW_ARGOSEXCEPTION("Keyframes must be in increasing order");
154  }
155  if(m_unLoop && unKeyframeStep > m_unLoop) {
156  THROW_ARGOSEXCEPTION("Keyframe step must be less than the loop period");
157  }
158  else {
159  unLastStep = unKeyframeStep;
160  m_vecKeyframes.emplace_back(unKeyframeStep,
161  unKeyframePlacement,
162  false);
163  }
164  }
165  else if(itTimelineElement->Value() == "interpolate") {
166  if(!m_vecKeyframes.empty()) {
167  m_vecKeyframes.back().InterpolateToNext = true;
168  }
169  }
170  }
171  }
172  /* Reset the camera */
173  Reset();
174  }
175  catch(CARGoSException& ex) {
176  THROW_ARGOSEXCEPTION_NESTED("Error initializing QTOpenGL camera", ex);
177  }
178  }
179 
180  /****************************************/
181  /****************************************/
182 
184  if(m_bHasTimeline) {
185  m_bEnableTimeline = true;
186  UpdateTimeline();
187  }
188  else {
190  }
191  }
192 
193  /****************************************/
194  /****************************************/
195 
197  const CVector3& cPosition = m_sActivePlacement.Position;
198  const CVector3& cTarget = m_sActivePlacement.Target;
199  const CVector3& cUp = m_sActivePlacement.Up;
200  gluLookAt(cPosition.GetX(),
201  cPosition.GetY(),
202  cPosition.GetZ(),
203  cTarget.GetX(),
204  cTarget.GetY(),
205  cTarget.GetZ(),
206  cUp.GetX(),
207  cUp.GetY(),
208  cUp.GetZ());
209  }
210 
211  /****************************************/
212  /****************************************/
213 
214  void CQTOpenGLCamera::Rotate(const QPoint& c_delta) {
215  /* Disable timeline on rotate */
216  m_bEnableTimeline = false;
217  /* Calculate fRotationSensitivity */
218  Real fRotationSensitivity =
219  ROTATE_GAIN * Exp(-m_sActivePlacement.LensFocalLength);
220  /* Rotate the camera */
221  Rotate(CRadians(fRotationSensitivity * c_delta.y()),
222  CRadians(-fRotationSensitivity * c_delta.x()));
223  }
224 
225  /****************************************/
226  /****************************************/
227 
229  const CRadians& c_left_right = CRadians::ZERO) {
230  CVector3& cUp = m_sActivePlacement.Up;
231  /* Calculate the forward and left vectors */
232  CVector3 cForward((m_sActivePlacement.Target - m_sActivePlacement.Position).Normalize());
233  CVector3 cLeft(cUp);
234  cLeft.CrossProduct(cForward).Normalize();
235  /* Apply up/down rotation */
236  if(c_up_down != CRadians::ZERO) {
237  /* Rotate around the local Y axis (Left)
238  The rotation matrix corresponding to this rotation is:
239  | Fcos(a)-Usin(a) L Ucos(a)+Fsin(a) |
240  where a is c_angle
241  L is the Left vector (local Y)
242  U is the Up vector (local Z)
243  F is the Forward vector (local X)
244  */
245  /* Calculate the new Up vector, given by:
246  Ucos(a)+Fsin(a)
247  */
248  /* Same, but faster than
249  cNewUp = Up * Cos(c_angle) + Forward * Sin(c_angle);
250  */
251  CVector3 cNewUp(m_sActivePlacement.Up);
252  /* Calculate the forward and left vector */
253  cNewUp *= Cos(c_up_down);
254  cNewUp += cForward * Sin(c_up_down);
255  /* Check whether the rotation exceeds the limits */
257  /*
258  * The rotation exceeds the limits
259  * The camera Up vector would form an angle bigger than 90 degrees with
260  * the global Z axis
261  */
262  /* We force the Up vector to lie on the XY plane */
263  cUp.SetZ(0.0f);
264  cUp.Normalize();
265  if(cForward.GetZ() < 0.0f) {
266  /* Forward was looking down, set it to -Z */
267  cForward = -CVector3::Z;
268  }
269  else {
270  /* Forward was looking up, set it to Z */
271  cForward = CVector3::Z;
272  }
273  }
274  else {
275  /* The rotation is OK */
276  cUp = cNewUp;
277  cUp.Normalize();
278  /* Now calculate the new Forward vector with a cross product
279  NOTE: the Left vector, being the rotation axis, remains
280  unchanged!
281  */
282  cForward = cLeft;
283  cForward.CrossProduct(cUp).Normalize();
284  }
285  }
286  /* Apply left/right rotation */
287  if(c_left_right != CRadians::ZERO) {
288  /* This rotation is performed around the global Z axis.
289  To this aim, along with the global Z axis we project the
290  Forward and Left axes onto the XY plane and use these as
291  additional axis to build up the rotation matrix.
292  With the matrix, we rotate the projected Forward and Left vectors.
293  We then transform the projected vectors into the final ones.
294  Finally, we cross-product the two vectors to obtain the new Up vector.
295  */
296  if(cForward.GetX() != 0 || cForward.GetY() != 0) {
297  /* Project Forward onto the XY axis */
298  CVector3 cForwardXY(cForward.GetX(), cForward.GetY(), 0.0f);
299  /* Save its length: it will be used to restore the Z coordinate correctly */
300  Real cForwardXYLength = cForwardXY.Length();
301  /* Normalize the projection */
302  cForwardXY.Normalize();
303  /* Project Left onto the XY axis and normalize the result */
304  CVector3 cLeftXY = CVector3::Z;
305  cLeftXY.CrossProduct(cForwardXY).Normalize();
306  /* The rotation matrix corresponding to this rotation is:
307  | Fcos(a)+Lsin(a) -Fsin(a)+Lcos(a) Z |
308  where a is c_angle
309  L is the Left vector projected on XY
310  F is the Forward vector projected on XY
311  Z is the global Z vector
312  */
313  /* Calculate the new cForwardXY vector, given by:
314  Fcos(a)+Lsin(a)
315  We keep the unrotated cForwardXY vector, because we will
316  need it for rotating Left too.
317  */
318  /* Same, but faster than
319  CVector3 cNewForwardXY = cForwardXY * Cos(c_angle) + cLeftXY * Sin(c_angle);
320  */
321  CVector3 cNewForwardXY(cForwardXY);
322  cNewForwardXY *= Cos(c_left_right);
323  cNewForwardXY += cLeftXY * Sin(c_left_right);
324  cNewForwardXY.Normalize();
325  /* Update Forward from cNewForwardXY: we want to keep the Z coordinate
326  of Forward unchanged cause we rotated around the global Z, but we
327  need to update the X and Y coordinates. Right now, cNewForwardXY has
328  zero Z coordinate and length 1, which means that its X and Y are wrong.
329  To get the right values, we need to scale it back to the length of the
330  projection of Forward onto the XY plane. Once this is done, the X and Y
331  coordinates are right.
332  */
333  /* Scale the vector back to the right length */
334  cNewForwardXY *= cForwardXYLength;
335  /* Finally, update Forward */
336  cForward.SetX(cNewForwardXY.GetX());
337  cForward.SetY(cNewForwardXY.GetY());
338  cForward.Normalize();
339  /* Calculate the new Left vector, given by:
340  -Fsin(a)+Lcos(a)
341  */
342  /* Same, but faster than
343  Left = cLeftXY * Cos(c_angle) - cForwardXY * Sin(c_angle);
344  */
345  cLeft = cLeftXY;
346  cLeft *= Cos(c_left_right);
347  cLeft -= cForwardXY * Sin(c_left_right);
348  cLeft.Normalize();
349  /* To calculate the new Up vector, a cross-product is enough */
350  cUp = cForward;
351  cUp.CrossProduct(cLeft).Normalize();
352  }
353  }
354  m_sActivePlacement.Target = m_sActivePlacement.Position;
355  m_sActivePlacement.Target += cForward;
356  }
357 
358  /****************************************/
359  /****************************************/
360 
361  void CQTOpenGLCamera::Move(SInt32 n_forwards_backwards,
362  SInt32 n_sideways,
363  SInt32 n_up_down) {
364  /* disable timeline on move */
365  m_bEnableTimeline = false;
366  /* Get cUp and calculate cForward and cLeft */
367  const CVector3& cUp = m_sActivePlacement.Up;
368  CVector3 cForward((m_sActivePlacement.Target - m_sActivePlacement.Position).Normalize());
369  CVector3 cLeft = m_sActivePlacement.Up;
370  cLeft.CrossProduct(cForward).Normalize();
371  /* Calculate motion sensitivity */
372  Real fMotionSensitivity = MOVE_GAIN * Exp(m_sActivePlacement.LensFocalLength);
373  /* Apply translation */
374  m_sActivePlacement.Position +=
375  cForward * (fMotionSensitivity * n_forwards_backwards) +
376  cLeft * (fMotionSensitivity * n_sideways) +
377  cUp * (fMotionSensitivity * n_up_down);
378  m_sActivePlacement.Target = m_sActivePlacement.Position;
379  m_sActivePlacement.Target += cForward;
380  }
381 
382  /****************************************/
383  /****************************************/
384 
385  void CQTOpenGLCamera::Interpolate(UInt32 un_start_placement,
386  UInt32 un_end_placement,
387  Real f_time_fraction) {
388  const SPlacement& sStart = m_arrPlacements[un_start_placement];
389  const SPlacement& sEnd = m_arrPlacements[un_end_placement];
390  /* Linear interpolate position vector */
391  m_sActivePlacement.Position = (sEnd.Position - sStart.Position);
392  m_sActivePlacement.Position *= f_time_fraction;
393  m_sActivePlacement.Position += sStart.Position;
394  /* Linear interpolate look at vector */
395  m_sActivePlacement.Target = (sEnd.Target - sStart.Target);
396  m_sActivePlacement.Target *= f_time_fraction;
397  m_sActivePlacement.Target += sStart.Target;
398  /* Linear interpolate up vector */
399  m_sActivePlacement.Up = (sEnd.Up - sStart.Up);
400  m_sActivePlacement.Up *= f_time_fraction;
401  m_sActivePlacement.Up += sStart.Up;
402  /* Linear interpolate the focal length */
403  m_sActivePlacement.LensFocalLength = (sEnd.LensFocalLength - sStart.LensFocalLength);
404  m_sActivePlacement.LensFocalLength *= f_time_fraction;
405  m_sActivePlacement.LensFocalLength += sStart.LensFocalLength;
406  /* Calculate the Y field-of-view */
407  m_sActivePlacement.CalculateYFieldOfView();
408  }
409 
410  /****************************************/
411  /****************************************/
412 
414  if(!m_bEnableTimeline)
415  return;
416  /* initialize two iterators to the first keyframe */
417  std::vector<SKeyframe>::const_iterator itCurrent =
418  std::cbegin(m_vecKeyframes);
419  std::vector<SKeyframe>::const_iterator itNext =
420  std::cbegin(m_vecKeyframes);
421  if(itCurrent == std::cend(m_vecKeyframes)) {
422  /* no keyframes defined: nothing to do */
423  return;
424  }
425  UInt32 unStep =
427  /* wrap unStep if we are looping */
428  if(m_unLoop) {
429  unStep %= m_unLoop;
430  }
431  /* search for the current and next keyframes */
432  while(itNext != std::cend(m_vecKeyframes) &&
433  itNext->Step < unStep) {
434  itCurrent = itNext++;
435  }
436  if(m_unLoop == 0) {
437  if(itCurrent == itNext) {
438  /* no keyframes have been defined yet */
439  return;
440  }
441  else if(itNext == std::cend(m_vecKeyframes)) {
442  if(itCurrent->Step == unStep - 1) {
443  SetActivePlacement(itCurrent->PlacementIndex);
444  }
445  }
446  else {
447  /* general case */
448  if(itCurrent->InterpolateToNext) {
449  Real fSegmentTimeFraction =
450  (unStep - itCurrent->Step) /
451  static_cast<Real>(itNext->Step - itCurrent->Step);
452  Interpolate(itCurrent->PlacementIndex,
453  itNext->PlacementIndex,
454  fSegmentTimeFraction);
455  }
456  else {
457  if(itCurrent->Step == unStep - 1) {
458  SetActivePlacement(itCurrent->PlacementIndex);
459  }
460  }
461  }
462  }
463  else /* m_unLoop != 0 */ {
464  if(itCurrent == itNext) {
465  /* no keyframes have been defined yet, since we are looping
466  wrap itCurrent around to the last keyframe */
467  itCurrent = std::prev(std::cend(m_vecKeyframes));
468  if(itCurrent == itNext) {
469  /* we are looping with a single keyframe, apply it once
470  and disable the timeline */
471  SetActivePlacement(itCurrent->PlacementIndex);
472  m_bEnableTimeline = false;
473  }
474  else if(itCurrent->InterpolateToNext) {
475  Real fSegmentTimeFraction =
476  (m_unLoop - itCurrent->Step + unStep) /
477  static_cast<Real>(m_unLoop - itCurrent->Step + itNext->Step);
478  Interpolate(itCurrent->PlacementIndex,
479  itNext->PlacementIndex,
480  fSegmentTimeFraction);
481  }
482  else /* itCurrent->InterpolateToNext == false */ {
483  SetActivePlacement(itCurrent->PlacementIndex);
484  }
485  }
486  else if(itNext == std::cend(m_vecKeyframes)) {
487  itNext = std::cbegin(m_vecKeyframes);
488  if(itCurrent == itNext) {
489  /* we are looping with a single keyframe, apply it once
490  and disable the timeline */
491  SetActivePlacement(itCurrent->PlacementIndex);
492  m_bEnableTimeline = false;
493  }
494  else if(itCurrent->InterpolateToNext) {
495  Real fSegmentTimeFraction =
496  (unStep - itCurrent->Step) /
497  static_cast<Real>(m_unLoop - itCurrent->Step + itNext->Step);
498  Interpolate(itCurrent->PlacementIndex,
499  itNext->PlacementIndex,
500  fSegmentTimeFraction);
501  }
502  else /* itCurrent->InterpolateToNext == false */ {
503  SetActivePlacement(itCurrent->PlacementIndex);
504  }
505  }
506  else {
507  if(itCurrent->InterpolateToNext) {
508  Real fSegmentTimeFraction =
509  (unStep - itCurrent->Step) /
510  static_cast<Real>(itNext->Step - itCurrent->Step);
511  Interpolate(itCurrent->PlacementIndex,
512  itNext->PlacementIndex,
513  fSegmentTimeFraction);
514  }
515  else {
516  SetActivePlacement(itCurrent->PlacementIndex);
517  }
518  }
519  }
520  }
521 
522  /****************************************/
523  /****************************************/
524 
525 }
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
unsigned int UInt32
32-bit unsigned integer.
Definition: datatypes.h:97
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
#define Exp
Definition: general.h:65
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
ticpp::Iterator< ticpp::Element > TConfigurationNodeIterator
The iterator for the ARGoS configuration XML node.
CARGoSLog LOGERR(std::cerr, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_RED))
Definition: argos_log.h:180
TConfigurationNode & GetNode(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns the first of its child nodes with the wanted name.
Real Cos(const CRadians &c_radians)
Computes the cosine of the passed value in radians.
Definition: angles.h:595
bool NodeAttributeExists(TConfigurationNode &t_node, const std::string &str_attribute)
Returns true if the specified attribute of a node exists.
void GetNodeAttributeOrDefault(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer, const T &t_default)
Returns the value of a node's attribute, or the passed default value.
CDegrees ToDegrees(const CRadians &c_radians)
Converts CRadians to CDegrees.
Definition: angles.h:489
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
bool NodeExists(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns true if one of its child nodes has the wanted name.
Real Sin(const CRadians &c_radians)
Computes the sine of the passed value in radians.
Definition: angles.h:586
CRadians ATan2(const Real f_y, const Real f_x)
Computes the arctangent of the passed values.
Definition: angles.h:633
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
CSpace & GetSpace() const
Returns a reference to the simulated space.
Definition: simulator.h:104
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
Definition: simulator.cpp:78
UInt32 GetSimulationClock() const
Returns the current value of the simulation clock.
Definition: space.h:345
const CVector3 & GetArenaSize() const
Returns the arena size.
Definition: space.h:371
const CVector3 & GetArenaCenter() const
Returns the arena center.
Definition: space.h:389
The exception that wraps all errors in ARGoS.
It defines the basic type CRadians, used to store an angle value in radians.
Definition: angles.h:42
static const CRadians PI_OVER_TWO
Set to PI / 2.
Definition: angles.h:59
static const CRadians PI_OVER_SIX
Set to PI / 6.
Definition: angles.h:74
static const CRadians ZERO
Set to zero radians.
Definition: angles.h:79
A 2D vector class.
Definition: vector2.h:27
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector2.h:110
CVector2 & Perpendicularize()
Transforms this vector into its ortogonal.
Definition: vector2.h:247
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector2.h:94
A 3D vector class.
Definition: vector3.h:31
Real Length() const
Returns the length of this vector.
Definition: vector3.h:227
static const CVector3 Y
The y axis.
Definition: vector3.h:39
CVector3 & CrossProduct(const CVector3 &c_vector3)
Calculates the cross product between this vector and the passed one.
Definition: vector3.h:382
void SetY(const Real f_y)
Sets the y coordinate of this vector.
Definition: vector3.h:129
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector3.h:105
void SetX(const Real f_x)
Sets the x coordinate of this vector.
Definition: vector3.h:113
CVector3 & Normalize()
Normalizes this vector.
Definition: vector3.h:237
void Set(const Real f_x, const Real f_y, const Real f_z)
Sets the vector contents from Cartesian coordinates.
Definition: vector3.h:155
void SetZ(const Real f_z)
Sets the z coordinate of this vector.
Definition: vector3.h:145
static const CVector3 X
The x axis.
Definition: vector3.h:36
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector3.h:121
static const CVector3 Z
The z axis.
Definition: vector3.h:42
Real GetZ() const
Returns the z coordinate of this vector.
Definition: vector3.h:137
CRadians GetAngleWith(const CVector3 &c_other)
Returns the angle between this vector and the passed vector.
Definition: vector3.h:335
void SetActivePlacement(UInt32 n_index)
void Interpolate(UInt32 un_start_placement, UInt32 un_end_placement, Real f_time_fraction)
void Move(SInt32 n_forwards_backwards, SInt32 n_sideways, SInt32 n_up_down)
void Init(TConfigurationNode &t_tree)
void Rotate(const QPoint &c_delta)
CVector3 Up
The local Z axis of the camera in the global reference frame.
CVector3 Position
The position of the camera in the global reference frame.
void Init(TConfigurationNode &t_tree)
Initialize from XML.
Real LensFocalLength
The focal length of the lens (if this was a real camera)
CVector3 Target
What we are looking at in the global reference frame.
void CalculateYFieldOfView()
Calculates the value of YFieldOfView.