ProtoTracer  1.0
Real-time 3D rendering and animation engine
Loading...
Searching...
No Matches
Quaternion.cpp
Go to the documentation of this file.
1#include "Quaternion.h"
2
3// Default constructor
4Quaternion::Quaternion() : W(1.0f), X(0.0f), Y(0.0f), Z(0.0f) {}
5
6// Copy constructor
8 this->W = quaternion.W;
9 this->X = quaternion.X;
10 this->Y = quaternion.Y;
11 this->Z = quaternion.Z;
12}
13
14// Constructor from Vector3D
16 this->W = 0;
17 this->X = vector.X;
18 this->Y = vector.Y;
19 this->Z = vector.Z;
20}
21
22// Constructor with individual components
23Quaternion::Quaternion(const float& w, const float& x, const float& y, const float& z) {
24 this->W = w;
25 this->X = x;
26 this->Y = y;
27 this->Z = z;
28}
29
30// Rotate vector
33
35
36 float s2 = q.W * 2.0f;
37 float dPUV = (q.X * v.X + q.Y * v.Y) * 2.0f;
38 float dPUU = q.W * q.W - (q.X * q.X + q.Y * q.Y + q.Z * q.Z);
39
40 return Vector2D{
41 X * dPUV + v.X * dPUU + (-(q.Z * v.Y)) * s2,
42 Y * dPUV + v.Y * dPUU + ((q.Z * v.X)) * s2
43 };
44}
45
46// Rotate vector with a unit quaternion
49
50 float s2 = q.W * 2.0f;
51 float dPUV = (q.X * v.X + q.Y * v.Y) * 2.0f;
52 float dPUU = q.W * q.W - (q.X * q.X + q.Y * q.Y + q.Z * q.Z);
53
54 return Vector2D{
55 X * dPUV + v.X * dPUU + (-(q.Z * v.Y)) * s2,
56 Y * dPUV + v.Y * dPUU + ((q.Z * v.X)) * s2
57 };
58}
59
60// Unrotate vector
66
67// Rotate vector
70
71 Quaternion qV = Quaternion(0.0f, v.X, v.Y, v.Z);
73 Quaternion qConj = q.Conjugate();
75
76 return Vector3D(rotated.X, rotated.Y, rotated.Z);
77}
78
79// Unrotate vector
85
86// Get Bivector
88 return Vector3D{
89 this->X,
90 this->Y,
91 this->Z
92 };
93}
94
96 return this->RotateVector(Vector3D(0, 0, 1.0f));
97}
98
99// Spherical interpolation
101 if (ratio <= Mathematics::EPSILON) return q1;
102 if (ratio >= 1.0f - Mathematics::EPSILON) return q2;
103
104 Quaternion q1U = q1;
105 Quaternion q2U = q2;
106
107 q1U = q1U.UnitQuaternion();
108 q2U = q2U.UnitQuaternion();
109
110 float dot = q1U.DotProduct(q2U);//Cosine between the two quaternions
111
112 if (dot < 0.0f){//Shortest path correction
113 q1U = q1U.AdditiveInverse();
114 dot = -dot;
115 }
116
117 if (dot > 0.999f){//Linearly interpolates if results are close
118 return (q1U.Add( (q2U.Subtract(q1U)).Multiply(ratio) )).UnitQuaternion();
119 }
120 else
121 {
122 dot = Mathematics::Constrain<float>(dot, -1, 1);
123
124 float theta0 = acosf(dot);
125 float theta = theta0 * ratio;
126
127 //Quaternion q3 = (q2.Subtract(q1.Multiply(dot))).UnitQuaternion();//UQ for orthonomal
128 float f1 = cosf(theta) - dot * sinf(theta) / sinf(theta0);
129 float f2 = sinf(theta) / sinf(theta0);
130
131 return q1U.Multiply(f1).Add(q2U.Multiply(f2)).UnitQuaternion();
132 }
133}
134
135// Delta rotation
137 Quaternion current = Quaternion(this->W, this->X, this->Y, this->Z);
140 float halfAngleLength = halfAngle.Magnitude();
141
142 if(halfAngleLength > Mathematics::EPSILON){//exponential map
145 }
146 else{//first taylor series
147 return (current * Quaternion(1.0f, halfAngle.X, halfAngle.Y, halfAngle.Z)).UnitQuaternion();
148 }
149}
150
151// Add quaternion
153 return Quaternion {
154 W + quaternion.W,
155 X + quaternion.X,
156 Y + quaternion.Y,
157 Z + quaternion.Z
158 };
159}
160
161// Subtract quaternion
163 return Quaternion{
164 W - quaternion.W,
165 X - quaternion.X,
166 Y - quaternion.Y,
167 Z - quaternion.Z
168 };
169}
170
171// Multiply quaternion
173 if(quaternion.IsClose(Quaternion(), Mathematics::EPSILON)) return Quaternion(W, X, Y, Z);
174
175 #ifndef _ARM_MATH_H
176 return Quaternion{
177 W * quaternion.W - X * quaternion.X - Y * quaternion.Y - Z * quaternion.Z,
178 W * quaternion.X + X * quaternion.W + Y * quaternion.Z - Z * quaternion.Y,
179 W * quaternion.Y - X * quaternion.Z + Y * quaternion.W + Z * quaternion.X,
180 W * quaternion.Z + X * quaternion.Y - Y * quaternion.X + Z * quaternion.W
181 };
182 #else
183 // 1 5 9 13
184 // 2 6 10 14
185 // 3 7 11 15
186 // 4 8 12 16
187 uint32_t multBlockSize = 16; // Increased to 4 for SIMD optimization
188
189 // Input vectors with an additional zero for padding
190 float32_t multA[multBlockSize] = {W, W, W, W, X, X, X, X, Y, Y, Y, Y, Z, Z, Z, Z};
195 };
196
197 // Output vector to store the result of the multiplication
199
200 // Call the function
202
203 Quaternion q = Quaternion( multDst[0] - multDst[4] - multDst[8] - multDst[12],
204 multDst[1] + multDst[5] + multDst[9] - multDst[13],
205 multDst[2] - multDst[6] + multDst[10] + multDst[14],
206 multDst[3] + multDst[7] - multDst[11] + multDst[15]
207 );
208
209 return q;
210
211 #endif
212}
213
214// Multiply with scalar
218
219 return Quaternion{
220 W * scalar,
221 X * scalar,
222 Y * scalar,
223 Z * scalar
224 };
225}
226
227// Divide quaternion
229 if(quaternion.IsClose(Quaternion(), Mathematics::EPSILON)) return Quaternion(W, X, Y, Z);
230
231 return Quaternion(
232 (W * quaternion.W - X * quaternion.X - Y * quaternion.Y - Z * quaternion.Z),
233 (W * quaternion.X + X * quaternion.W + Y * quaternion.Z - Z * quaternion.Y),
234 (W * quaternion.Y - X * quaternion.Z + Y * quaternion.W + Z * quaternion.X),
235 (W * quaternion.Z + X * quaternion.Y - Y * quaternion.X + Z * quaternion.W)
236 );
237}
238
239// Divide by scalar
243
244 float invert = 1.0f / scalar;
245
246 return Quaternion
247 {
248 W * invert,
249 X * invert,
250 Y * invert,
251 Z * invert
252 };
253}
254
255// Power of quaternion
264
265// Power with scalar exponent
274
275// Permutate quaternion
277 Quaternion q = Quaternion(this->W, this->X, this->Y, this->Z);
278 float perm[3];
279
280 perm[(int)permutation.X] = q.X;
281 perm[(int)permutation.Y] = q.Y;
282 perm[(int)permutation.Z] = q.Z;
283
284 q.X = perm[0];
285 q.Y = perm[1];
286 q.Z = perm[2];
287
288 return q;
289}
290
291// Absolute value of quaternion
293 return Quaternion {
294 fabsf(W),
295 fabsf(X),
296 fabsf(Y),
297 fabsf(Z)
298 };
299}
300
301// Additive inverse of quaternion
303 return Quaternion {
304 -W,
305 -X,
306 -Y,
307 -Z
308 };
309}
310
311// Multiplicative inverse of quaternion
313 float invNorm = 1.0f / Normal();
314
316 if(Mathematics::IsClose(invNorm, 1.0f, Mathematics::EPSILON)) return *this;
317
318 return Conjugate().Multiply(invNorm);
319}
320
321// Conjugate of quaternion
323 return Quaternion {
324 W,
325 -X,
326 -Y,
327 -Z
328 };
329}
330
331// Normalize quaternion to unit quaternion
333 float n = 1.0f / Normal();
334
335 return Quaternion{
336 W * n,
337 X * n,
338 Y * n,
339 Z * n
340 };
341}
342
343// Magnitude of quaternion
345 return Mathematics::Sqrt(Normal());
346}
347
348// Dot product of two quaternions
350 return (W * q.W) + (X * q.X) + (Y * q.Y) + (Z * q.Z);
351}
352
353// Norm of quaternion
354float Quaternion::Normal() const {
355 return Mathematics::Sqrt(W * W + X * X + Y * Y + Z * Z);
356}
357
358// Check if quaternion is NaN
362
363// Check if quaternion is finite
367
368// Check if quaternion is infinite
372
373// Check if quaternion is non-zero
375 return W != 0 && X != 0 && Y != 0 && Z != 0;
376}
377
378// Check if two quaternions are equal
380 return !IsNaN() && !quaternion.IsNaN() &&
381 W == quaternion.W &&
382 X == quaternion.X &&
383 Y == quaternion.Y &&
384 Z == quaternion.Z;
385}
386
387// Check if two quaternions are close within an epsilon
388bool Quaternion::IsClose(const Quaternion& quaternion, const float& epsilon) const {
389 return fabsf(W - quaternion.W) < epsilon &&
390 fabsf(X - quaternion.X) < epsilon &&
391 fabsf(Y - quaternion.Y) < epsilon &&
392 fabsf(Z - quaternion.Z) < epsilon;
393}
394
395// Convert quaternion to string
401
402 return "[" + w + ", " + x + ", " + y + ", " + z + "]";
403}
404
405// Operator overloads
407 return this->IsEqual(quaternion);
408}
409
411 return !(this->IsEqual(quaternion));
412}
413
415 this->W = quaternion.W;
416 this->X = quaternion.X;
417 this->Y = quaternion.Y;
418 this->Z = quaternion.Z;
419
420 return quaternion;
421}
422
426
430
434
438
440 return Divide(scalar);
441}
442
443// Friend operator overloads
444Quaternion operator *(const float& scalar, const Quaternion& q) {
445 return q.Multiply(scalar);
446}
447
448Quaternion operator *(const Quaternion& q, const float& scalar) {
449 return q.Multiply(scalar);
450}
451
452
453// Static function definitions
454
456 return q1.Add(q2);
457}
458
460 return q1.Subtract(q2);
461}
462
464 return q1.Multiply(q2);
465}
466
468 return q1.Divide(q2);
469}
470
472 return q1.Power(q2);
473}
474
476 return q1.DotProduct(q2);
477}
478
480 return quaternion.Power(exponent);
481}
482
486
488 return quaternion.Absolute();
489}
490
492 return quaternion.AdditiveInverse();
493}
494
496 return quaternion.MultiplicativeInverse();
497}
498
500 return quaternion.Conjugate();
501}
502
504 return quaternion.UnitQuaternion();
505}
506
508 return quaternion.Magnitude();
509}
510
512 return quaternion.Normal();
513}
Quaternion operator*(const float &scalar, const Quaternion &q)
Defines the Quaternion class for 3D rotations and transformations.
Implements a generic Kalman Filter for 1D data.
static float Sqrt(float value)
Computes the square root of a value.
static bool IsClose(float v1, float v2, float epsilon)
Checks if two values are close within a specified epsilon.
static String DoubleToCleanString(float value)
Converts a floating-point value to a String, removing trailing decimals if not needed.
static bool IsFinite(float value)
Checks if a floating-point value is finite.
static float Pow(float value, float exponent)
Raises a value to a given exponent.
static bool IsInfinite(float value)
Checks if a floating-point value is infinite.
static const float EPSILON
A small constant used for floating-point comparisons.
Definition Mathematics.h:37
static bool IsNaN(float value)
Checks if a floating-point value is NaN (Not a Number).
A mathematical construct representing a rotation in 3D space.
Definition Quaternion.h:30
Vector3D GetBiVector() const
Retrieves the bi-vector (X, Y, Z) portion of the quaternion (with W=0).
float DotProduct(const Quaternion &q) const
Computes the dot product between this quaternion and another.
Quaternion Power(const Quaternion &exponent) const
Raises this quaternion to the power of another quaternion (component-wise).
bool IsFinite() const
Checks if all components are finite.
Quaternion Divide(const Quaternion &quaternion) const
Divides this quaternion by another quaternion component-wise (not a typical quaternion operation).
static Quaternion SphericalInterpolation(const Quaternion &q1, const Quaternion &q2, const float &ratio)
Performs spherical linear interpolation (slerp) between two quaternions.
Quaternion Conjugate() const
Returns the conjugate of this quaternion (W stays the same, X/Y/Z get negated).
bool IsInfinite() const
Checks if any component is infinite.
Quaternion AdditiveInverse() const
Negates each component (an additive inverse).
Quaternion UnitQuaternion() const
Returns a unit quaternion (normalized) version of this quaternion.
bool IsNaN() const
Checks if any component of this quaternion is NaN.
Quaternion operator/(const Quaternion &quaternion) const
Divides this quaternion by another quaternion, component-wise.
Quaternion operator+(const Quaternion &quaternion) const
Adds two quaternions (component-wise).
Quaternion operator-(const Quaternion &quaternion) const
Subtracts one quaternion from another (component-wise).
bool operator==(const Quaternion &quaternion) const
Equality operator. Checks if two quaternions match exactly (component-wise).
Quaternion()
Default constructor. Initializes the quaternion to identity (1,0,0,0).
Definition Quaternion.cpp:4
bool operator!=(const Quaternion &quaternion) const
Inequality operator. Checks if two quaternions differ in any component.
Quaternion MultiplicativeInverse() const
Returns the multiplicative inverse of this quaternion, such that q * q^-1 = identity.
Quaternion DeltaRotation(const Vector3D &angularVelocity, const float &timeDelta) const
Computes a small rotation quaternion given an angular velocity and time delta.
Quaternion Permutate(const Vector3D &permutation) const
Performs a permutation operation using a 3D vector (custom transform).
Vector2D RotateVector(const Vector2D &v) const
Rotates a 2D vector by this quaternion, projecting it in 2D.
Vector2D RotateVectorUnit(const Vector2D &v, const Quaternion &q) const
Rotates a 2D vector by a unit quaternion (assumes normalized), allowing a different quaternion to be ...
float W
Scalar part of the quaternion.
Definition Quaternion.h:32
bool IsEqual(const Quaternion &quaternion) const
Checks if two quaternions are exactly equal (component-wise).
String ToString() const
Converts this quaternion to a string representation (e.g. "(W, X, Y, Z)").
bool IsClose(const Quaternion &quaternion, const float &epsilon) const
Checks if two quaternions are nearly equal within a tolerance.
float Z
Z component of the quaternion's vector part.
Definition Quaternion.h:35
float X
X component of the quaternion's vector part.
Definition Quaternion.h:33
Vector3D GetNormal() const
Retrieves the normal vector part of the quaternion, typically its axis of rotation.
float Normal() const
Computes the quaternion's norm (equivalent to squared magnitude).
float Y
Y component of the quaternion's vector part.
Definition Quaternion.h:34
Quaternion Absolute() const
Returns a quaternion where each component is the absolute value of the original.
Quaternion Add(const Quaternion &quaternion) const
Adds two quaternions component-wise.
Vector2D UnrotateVector(const Vector2D &coordinate) const
Applies the inverse of this quaternion's rotation to a 2D vector.
friend Quaternion operator*(const float &scalar, const Quaternion &q)
Scalar multiplication operator (on the left).
float Magnitude() const
Computes the magnitude (length) of this quaternion.
Quaternion Multiply(const Quaternion &quaternion) const
Multiplies (composes) this quaternion with another (order matters).
Quaternion operator=(const Quaternion &quaternion)
Assignment operator. Copies another quaternion's components to this one.
bool IsNonZero() const
Checks if the quaternion is non-zero (i.e., any component != 0).
Quaternion Subtract(const Quaternion &quaternion) const
Subtracts a quaternion from this quaternion component-wise.
Represents a 2D vector (X, Y) and provides methods for vector arithmetic.
Definition Vector2D.h:27
Represents a 3D vector (X, Y, Z) and provides methods for vector arithmetic.
Definition Vector3D.h:26
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