ARGoS 3
A parallel, multi-engine simulator for swarm robotics
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
14namespace 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;
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 Exp
Definition general.h:65
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 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.
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
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.
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 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
const CVector3 & GetArenaCenter() const
Returns the arena center.
Definition space.h:389
const CVector3 & GetArenaSize() const
Returns the arena size.
Definition space.h:371
UInt32 GetSimulationClock() const
Returns the current value of the simulation clock.
Definition space.h:345
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
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
CVector3 & CrossProduct(const CVector3 &c_vector3)
Calculates the cross product between this vector and the passed one.
Definition vector3.h:382
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.