ProtoTracer  1.0
Real-time 3D rendering and animation engine
Loading...
Searching...
No Matches
Rotation.cpp
Go to the documentation of this file.
1#include "Rotation.h"
2#include "Mathematics.h"
3
4// Define the private member functions
7 float scale = sinf(halfRotation);
8
9 return Quaternion(
10 cosf(halfRotation / 2.0f),
11 axisAngle.Axis.X * scale,
12 axisAngle.Axis.Y * scale,
13 axisAngle.Axis.Z * scale
14 );
15}
16
36
40
43
44 float matrixTrace = X.X + Y.Y + Z.Z;
45 float square;
46
47 if (matrixTrace > 0){
48 square = sqrtf(1.0f + matrixTrace) * 2.0f;//4 * qw
49
50 q.W = 0.25f * square;
51 q.X = (Z.Y - Y.Z) / square;
52 q.Y = (X.Z - Z.X) / square;
53 q.Z = (Y.X - X.Y) / square;
54 }
55 else if ((X.X > Y.Y) && (X.X > Z.Z)){
56 square = sqrtf(1.0f + X.X - Y.Y - Z.Z) * 2.0f;//4 * qx
57
58 q.W = (Z.Y - Y.Z) / square;
59 q.X = 0.25f * square;
60 q.Y = (X.Y + Y.X) / square;
61 q.Z = (X.Z + Z.X) / square;
62 }
63 else if (Y.Y > Z.Z){
64 square = sqrtf(1.0f + Y.Y - X.X - Z.Z) * 2.0f;//4 * qy
65
66 q.W = (X.Z - Z.X) / square;
67 q.X = (X.Y + Y.X) / square;
68 q.Y = 0.25f * square;
69 q.Z = (Y.Z + Z.Y) / square;
70 }
71 else{
72 square = sqrtf(1.0f + Z.Z - X.X - Y.Y) * 2.0f;//4 * qz
73
74 q.W = (Y.X - X.Y) / square;
75 q.X = (X.Z + Z.X) / square;
76 q.Y = (Y.Z + Z.Y) / square;
77 q.Z = 0.25f * square;
78 }
79
80 return q.UnitQuaternion().Conjugate();
81}
82
84 Quaternion q = Quaternion(1, 0, 0, 0);
85 Vector3D eA = eulerAngles.Angles;
86 float sx, sy, sz, cx, cy, cz;
87
91
92 if (eulerAngles.Order.FrameTaken == EulerOrder::AxisFrame::Rotating){
93 float t = eA.X;
94 eA.X = eA.Z;
95 eA.Z = t;
96 }
97
98 sx = sinf(eA.X * 0.5f);
99 sy = sinf(eA.Y * 0.5f);
100 sz = sinf(eA.Z * 0.5f);
101 cx = cosf(eA.X * 0.5f);
102 cy = cosf(eA.Y * 0.5f);
103 cz = cosf(eA.Z * 0.5f);
104
105 Quaternion qx = Quaternion(cx, sx, 0, 0);
106 Quaternion qy = Quaternion(cy, 0, sy, 0);
107 Quaternion qz = Quaternion(cz, 0, 0, sz);
108
109 switch(eulerAngles.Order.AxisOrder){
110 case EulerOrder::XYZ:
111 q = qx * qy * qz;
112 break;
113 case EulerOrder::XZY:
114 q = qx * qz * qy;
115 break;
116 case EulerOrder::YXZ:
117 q = qy * qx * qz;
118 break;
119 case EulerOrder::YZX:
120 q = qy * qz * qx;
121 break;
122 case EulerOrder::ZXY:
123 q = qz * qx * qy;
124 break;
125 case EulerOrder::ZYX:
126 q = qz * qy * qx;
127 break;
128 default://XYZ
129 q = qx * qy * qz;
130 break;
131 }
132
133 return q;
134}
135
137 //std::cout << "YPR to Quaternion not implemented." << std::endl;
138
139 return Quaternion();
140}
141
147
153
155 Quaternion q = Quaternion(1, 0, 0, 0);
156 Vector3D tempV = Vector3D(0, 0, 0);
157 Vector3D xAxis = Vector3D(1, 0, 0);
158 Vector3D yAxis = Vector3D(0, 1, 0);
159
161
162 if (dot < -0.999999f)
163 {
165
166 if (tempV.Magnitude() < 0.000001f)
167 {
169 }
170
171 tempV = tempV.UnitSphere();
172
173 q = Rotation(AxisAngle(Mathematics::MPI, tempV)).GetQuaternion();
174 }
175 else if (dot > 0.999999f)
176 {
177 q.W = 1.0f;
178 q.X = 0.0f;
179 q.Y = 0.0f;
180 q.Z = 0.0f;
181 }
182 else
183 {
185
186 q.W = 1.0f + dot;
187 q.X = tempV.X;
188 q.Y = tempV.Y;
189 q.Z = tempV.Z;
190
191 q = q.UnitQuaternion();
192 }
193
194 return q;
195}
196
197// Define the public member functions
201
205
209
213
217
221
225
229
233
237
239 AxisAngle axisAngle = AxisAngle(0, 0, 1, 0);
241
242 q = (fabs(q.W) > 1.0f) ? q.UnitQuaternion() : q;
243
244 axisAngle.Rotation = Mathematics::RadiansToDegrees(2.0f * acosf(q.W));
245
246 float quaternionCheck = sqrtf(1.0f - powf(q.W, 2.0f));//Prevents rotation jumps, and division by zero
247
248 if (quaternionCheck >= 0.001f)//Prevents division by zero
249 {
250 //Normalizes axis
251 axisAngle.Axis.X = q.X / quaternionCheck;
252 axisAngle.Axis.Y = q.Y / quaternionCheck;
253 axisAngle.Axis.Z = q.Z / quaternionCheck;
254 }
255 else
256 {
257 //If X is close to zero the axis doesn't matter
258 axisAngle.Axis.X = 0.0f;
259 axisAngle.Axis.Y = 1.0f;
260 axisAngle.Axis.Z = 0.0f;
261 }
262
263 return axisAngle;
264}
265
268 Vector3D up = Vector3D(0, 1, 0);//up vector
269 Vector3D right = Vector3D(1, 0, 0);
270 Vector3D rotatedUp = q.RotateVector(up);//new direction vector
271 Vector3D rotatedRight = q.RotateVector(right);
273
274 //rotate forward vector by direction vector rotation
275 Vector3D rightXZCompensated = rotationChange.UnrotateVector(rotatedRight);//should only be two points on circle, compare against right
276
277 //define angles that define the forward vector, and the rotated then compensated forward vector
278 float rightAngle = Mathematics::RadiansToDegrees(atan2f(right.Z, right.X));//forward as zero
280
281 //angle about the axis defined by the direction of the object
282 float angle = rightAngle - rightRotatedAngle;
283
284 //returns the angle rotated about the rotated up vector as an axis
285 return DirectionAngle(angle, rotatedUp);
286}
287
299
303 float sqx = q.X * q.X;
304 float sqy = q.Y * q.Y;
305 float sqz = q.Z * q.Z;
306
307 switch (order.AxisOrder) {
308 case EulerOrder::XYZ:
309 eulerAngles.Angles.Y = asinf(-2.0f * (q.X * q.Z - q.W * q.Y));
310 if (fabs(eulerAngles.Angles.Y) < 0.499f) {
311 eulerAngles.Angles.X = atan2f(q.Y * q.Z + q.W * q.X, 0.5f - sqx - sqy);
312 eulerAngles.Angles.Z = atan2f(q.X * q.Y + q.W * q.Z, 0.5f - sqy - sqz);
313 } else {
314 eulerAngles.Angles.X = atan2f(q.X * q.Y - q.W * q.Z, 0.5f - sqx - sqz);
315 eulerAngles.Angles.Z = 0.0f;
316 }
317 break;
318 case EulerOrder::XZY:
319 eulerAngles.Angles.Z = asinf(2.0f * (q.X * q.Y + q.W * q.Z));
320 if (fabs(eulerAngles.Angles.Z) < 0.499f) {
321 eulerAngles.Angles.X = atan2f(q.Y * q.Z - q.W * q.X, 0.5f - sqx - sqz);
322 eulerAngles.Angles.Y = atan2f(q.X * q.Z - q.W * q.Y, 0.5f - sqy - sqz);
323 } else {
324 eulerAngles.Angles.X = atan2f(-q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqy);
325 eulerAngles.Angles.Y = 0.0f;
326 }
327 break;
328 case EulerOrder::YXZ:
329 eulerAngles.Angles.X = asinf(2.0f * (q.Y * q.Z + q.W * q.X));
330 if (fabs(eulerAngles.Angles.X) < 0.499f) {
331 eulerAngles.Angles.Y = atan2f(q.X * q.Z - q.W * q.Y, 0.5f - sqx - sqy);
332 eulerAngles.Angles.Z = atan2f(q.Y * q.Z - q.W * q.X, 0.5f - sqy - sqz);
333 } else {
334 eulerAngles.Angles.Y = atan2f(-q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqz);
335 eulerAngles.Angles.Z = 0.0f;
336 }
337 break;
338 case EulerOrder::YZX:
339 eulerAngles.Angles.Z = asinf(-2.0f * (q.Y * q.X - q.W * q.Z));
340 if (fabs(eulerAngles.Angles.Z) < 0.499f) {
341 eulerAngles.Angles.Y = atan2f(q.X * q.Z + q.W * q.Y, 0.5f - sqx - sqz);
342 eulerAngles.Angles.X = atan2f(q.Y * q.X + q.W * q.Z, 0.5f - sqy - sqz);
343 } else {
344 eulerAngles.Angles.Y = atan2f(-q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqy);
345 eulerAngles.Angles.X = 0.0f;
346 }
347 break;
348 case EulerOrder::ZXY:
349 eulerAngles.Angles.X = asinf(2.0f * (q.Z * q.Y + q.W * q.X));
350 if (fabs(eulerAngles.Angles.X) < 0.499f) {
351 eulerAngles.Angles.Z = atan2f(q.X * q.Z - q.W * q.Y, 0.5f - sqx - sqy);
352 eulerAngles.Angles.Y = atan2f(q.Z * q.Y - q.W * q.X, 0.5f - sqy - sqz);
353 } else {
354 eulerAngles.Angles.Z = atan2f(-q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqz);
355 eulerAngles.Angles.Y = 0.0f;
356 }
357 break;
358 case EulerOrder::ZYX:
359 eulerAngles.Angles.Y = asinf(-2.0f * (q.Z * q.X - q.W * q.Y));
360 if (fabs(eulerAngles.Angles.Y) < 0.499f) {
361 eulerAngles.Angles.Z = atan2f(q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqy);
362 eulerAngles.Angles.X = atan2f(q.Z * q.Y + q.W * q.X, 0.5f - sqy - sqz);
363 } else {
364 eulerAngles.Angles.Z = atan2f(-q.X * q.Y + q.W * q.Z, 0.5f - sqx - sqz);
365 eulerAngles.Angles.X = 0.0f;
366 }
367 break;
368 default: // XYZ
369 eulerAngles.Angles.Y = asinf(-2.0f * (q.X * q.Z - q.W * q.Y));
370 if (fabs(eulerAngles.Angles.Y) < 0.499f) {
371 eulerAngles.Angles.X = atan2f(q.Y * q.Z + q.W * q.X, 0.5f - sqx - sqy);
372 eulerAngles.Angles.Z = atan2f(q.X * q.Y + q.W * q.Z, 0.5f - sqy - sqz);
373 } else {
374 eulerAngles.Angles.X = atan2f(q.X * q.Y - q.W * q.Z, 0.5f - sqx - sqz);
375 eulerAngles.Angles.Z = 0.0f;
376 }
377 break;
378 }
379
380 // Convert radians to degrees
384
385 // Handle frame rotation if necessary
386 if (order.FrameTaken == EulerOrder::Rotating) {
387 float t = eulerAngles.Angles.X;
388 eulerAngles.Angles.X = eulerAngles.Angles.Z;
389 eulerAngles.Angles.Z = t;
390 }
391
392 eulerAngles.Angles = eulerAngles.Angles.Permutate(order.Permutation);
393
394 return eulerAngles;
395}
396
399
400 //intrinsic tait-bryan rotation of order XYZ
401 float yaw = atan2f( 2.0f * (q.Y * q.Z + q.W * q.X), powf(q.W, 2) - powf(q.X, 2) - powf(q.Y, 2) + powf(q.Z, 2));
402 float pitch = asinf(-2.0f * (q.X * q.Z - q.W * q.Y));
403 float roll = atan2f( 2.0f * (q.X * q.Y + q.W * q.Z), powf(q.W, 2) + powf(q.X, 2) - powf(q.Y, 2) - powf(q.Z, 2));
404
408
409 return YawPitchRoll(yaw, pitch, roll);
410}
Provides a collection of mathematical utility functions and constants.
Defines the Rotation class for handling 3D rotations using various representations.
Defines a rotation in 3D space using an axis and an angle.
Definition AxisAngle.h:23
Defines a rotation in 3D space using a direction vector and a rotation angle.
Encapsulates a 3D rotation using Euler angles and a specific order of application.
Definition EulerAngles.h:25
Specifies the order and frame of reference for Euler rotations.
Definition EulerOrder.h:25
@ YZX
Y → Z → X rotation order.
Definition EulerOrder.h:42
@ XZY
X → Z → Y rotation order.
Definition EulerOrder.h:40
@ ZYX
Z → Y → X rotation order.
Definition EulerOrder.h:44
@ YXZ
Y → X → Z rotation order.
Definition EulerOrder.h:41
@ ZXY
Z → X → Y rotation order.
Definition EulerOrder.h:43
@ XYZ
X → Y → Z rotation order.
Definition EulerOrder.h:39
@ Rotating
Rotations relative to a rotating frame.
Definition EulerOrder.h:56
Implements a generic Kalman Filter for 1D data.
static T RadiansToDegrees(T radians)
Converts radians to degrees.
static const float MPI
Mathematical constant (3.14159265358979323846...).
Definition Mathematics.h:42
static T DegreesToRadians(T degrees)
Converts degrees to radians.
A mathematical construct representing a rotation in 3D space.
Definition Quaternion.h:30
Quaternion UnitQuaternion() const
Returns a unit quaternion (normalized) version of this quaternion.
Vector2D RotateVector(const Vector2D &v) const
Rotates a 2D vector by this quaternion, projecting it in 2D.
Represents a 3D rotation matrix and provides operations for rotation and matrix manipulation.
static Vector3D RotateVector(Vector3D rotate, Vector3D coordinates)
Rotates a vector using the rotation matrix.
EulerAngles RotationMatrixToEulerAngles(const RotationMatrix &rM, const EulerOrder &order)
Converts a RotationMatrix to Euler angles.
Definition Rotation.cpp:142
YawPitchRoll GetYawPitchRoll()
Gets the yaw-pitch-roll representation of the rotation.
Definition Rotation.cpp:397
RotationMatrix EulerAnglesToRotationMatrix(const EulerAngles &eulerAngles)
Converts Euler angles to a RotationMatrix.
Definition Rotation.cpp:148
Quaternion EulerAnglesToQuaternion(const EulerAngles &eulerAngles)
Converts Euler angles to a Quaternion.
Definition Rotation.cpp:83
Quaternion YawPitchRollToQuaternion(const YawPitchRoll &ypr)
Converts a YawPitchRoll representation to a Quaternion.
Definition Rotation.cpp:136
AxisAngle GetAxisAngle()
Gets the axis-angle representation of the rotation.
Definition Rotation.cpp:238
RotationMatrix GetRotationMatrix()
Gets the rotation matrix representation of the rotation.
Definition Rotation.cpp:288
EulerAngles GetEulerAngles(const EulerOrder &order)
Gets the Euler angles representation of the rotation.
Definition Rotation.cpp:300
Rotation()
Default constructor.
Definition Rotation.cpp:198
Quaternion GetQuaternion()
Gets the quaternion representation of the rotation.
Definition Rotation.cpp:234
DirectionAngle GetDirectionAngle()
Gets the direction-angle representation of the rotation.
Definition Rotation.cpp:266
Quaternion RotationMatrixToQuaternion(const RotationMatrix &rM)
Converts a RotationMatrix to a Quaternion.
Definition Rotation.cpp:37
Quaternion quaternionRotation
Quaternion representation of the rotation.
Definition Rotation.h:34
Quaternion DirectionAngleToQuaternion(const DirectionAngle &directionAngle)
Converts a DirectionAngle to a Quaternion.
Definition Rotation.cpp:17
Quaternion AxisAngleToQuaternion(const AxisAngle &axisAngle)
Converts an AxisAngle to a Quaternion.
Definition Rotation.cpp:5
Quaternion QuaternionFromDirectionVectors(const Vector3D &initial, const Vector3D &target)
Creates a Quaternion from direction vectors.
Definition Rotation.cpp:154
Represents a 3D vector (X, Y, Z) and provides methods for vector arithmetic.
Definition Vector3D.h:26
Vector3D CrossProduct(const Vector3D &vector) const
Computes the cross product of this vector with another Vector3D.
Definition Vector3D.cpp:98
float Z
The Z-component of the 3D vector.
Definition Vector3D.h:30
float X
The X-component of the 3D vector.
Definition Vector3D.h:28
float Y
The Y-component of the 3D vector.
Definition Vector3D.h:29
float DotProduct(const Vector3D &vector) const
Computes the dot product of this vector with another Vector3D.
Definition Vector3D.cpp:155
A class to represent yaw, pitch, and roll angles for orientation.