1 /* Copyright 2011 Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file Quat.h
16         @author Jukka Jyl�nki
17         @brief Quaternions represent rotations and orientations of 3D objects. */
18 #pragma once
19
20 #ifdef MATH_ENABLE_STL_SUPPORT
21 #include <string>
22 #endif
23 #include "Math/MathFwd.h"
24
25 #ifdef MATH_QT_INTEROP
26 #include <QQuaternion>
27 #endif
28 /*
29 #ifdef MATH_IRRLICHT_INTEROP
30 #include "Quaternion.h"
31 #endif
32 */
33 #ifdef MATH_OGRE_INTEROP
34 #include <OgreQuaternion.h>
35 #endif
36
37 MATH_BEGIN_NAMESPACE
38
39 /// Represents a rotation or an orientation of a 3D object.
40 class Quat
41 {
42 public:
43         float x///< The factor of i.
44         float y///< The factor of j.
45         float z///< The factor of k.
46         float w///< The scalar part. Sometimes also referred to as 'r'.
47
48         /// @note The default ctor does not initialize any member values.
49         Quat() {}
50
51         /// The copy-ctor for Quat is the trivial copy-ctor, but it is explicitly written to be able to automatically pick up this function for QtScript bindings.
52         Quat(const Quat &rhs) { x = rhs.xy = rhs.yz = rhs.zw = rhs.w; }
53
54         /// Constructs a quaternion from the given data buffer.
55         /// @param data An array of four floats to use for the quaternion, in the order 'x, y, z, w'. (== 'i, j, k, r')
56         /// @note The input data is not normalized after construction, this has to be done manually.
57         explicit Quat(const float *data);
58
59         explicit Quat(const float3x3 &rotationMatrix);
60         explicit Quat(const float3x4 &rotationMatrix);
61         explicit Quat(const float4x4 &rotationMatrix);
62
63         /// @param x The factor of i.
64         /// @param y The factor of j.
65         /// @param z The factor of k.
66         /// @param w The scalar factor (or 'w').
67         /// @note The input data is not normalized after construction, this has to be done manually.
68         Quat(float xfloat yfloat zfloat w);
69
70         /// Constructs this quaternion by specifying a rotation axis and the amount of rotation to be performed
71         /// about that axis.
72         /// @param rotationAxis The normalized rotation axis to rotate about.
73         Quat(const float3 &rotationAxis, float rotationAngleRadians);
74
75         /// Returns the local +X axis in the post-transformed coordinate space. This is the same as transforming the vector (1,0,0) by this quaternion.
76         float3 WorldX() const;
77         /// Returns the local +Y axis in the post-transformed coordinate space. This is the same as transforming the vector (0,1,0) by this quaternion.
78         float3 WorldY() const;
79         /// Returns the local +Z axis in the post-transformed coordinate space. This is the same as transforming the vector (0,0,1) by this quaternion.
80         float3 WorldZ() const;
81
82         /// Returns the axis of rotation for this quaternion.
83         float3 Axis() const;
84
85         /// Returns the angle of rotation for this quaternion, in radians.
86         float Angle() const;
87
88         /// Computes the dot product of this and the given quaternion.
89         /// Dot product is commutative.
90         float Dot(const Quat &rhs) const;
91
92         float LengthSq() const;
93
94         float Length() const;
95
96         /// Normalizes this quaternion in-place.
97         /// Returns the old length of this quaternion, or 0 if normalization failed.
98         float Normalize();
99
100         /// Returns a normalized copy of this quaternion.
101         Quat Normalized() const;
102
103         /// Returns true if the length of this quaternion is one.
104         bool IsNormalized(float epsilon = 1e-3f) const;
105
106         bool IsInvertible(float epsilon = 1e-3f) const;
107
108         /// Returns true if the entries of this quaternion are all finite.
109         bool IsFinite() const;
110
111         /// Returns true if this quaternion equals rhs, up to the given epsilon.
112         bool Equals(const Quat &rhs, float epsilon = 1e-3f) const;
113
114         /// @return A pointer to the first element (x). The data is contiguous in memory.
115         /// ptr[0] gives x, ptr[1] is y, ptr[2] is z and ptr[3] is w.
116         float *ptr();
117         const float *ptr() const;
118
119         /// Inverses this quaternion in-place.
120         /// @note For optimization purposes, this function assumes that the quaternion is unitary, in which
121         ///        case the inverse of the quaternion is simply just the same as its conjugate. This function
122         ///        does not detect whether the operation succeeded or failed.
123         void Inverse();
124
125         /// Returns an inverted copy of this quaternion.
126         Quat Inverted() const;
127
128         /// Inverses this quaternion in-place.
129         /// Call this function when the quaternion is not known beforehand to be normalized. This function
130         /// computes the inverse proper, and normalizes the result.
131         /// @note Because of the normalization, it does not necessarily hold that q * q.InverseAndNormalize() == id.
132         /// @return Returns the old length of this quaternion (not the old length of the inverse quaternion).
133         float InverseAndNormalize();
134
135         /// Computes the conjugate of this quaternion in-place.
136         void Conjugate();
137
138         /// Returns a conjugated copy of this quaternion.
139         Quat Conjugated() const;
140
141         /// Rotates the given vector by this quaternion.
142         float3 Transform(float xfloat yfloat zconst;
143         float3 Transform(const float3 &vec) const;
144
145         /// Rotates the given vector by this quaternion. The w component of the vector is assumed to be zero or one.
146         float4 Transform(const float4 &vec) const;
147
148         Quat Lerp(const Quat &target, float t) const;
149         static Quat Lerp(const Quat &source, const Quat &target, float t);
150         Quat Slerp(const Quat &target, float t) const;
151         static Quat Slerp(const Quat &source, const Quat &target, float t);
152
153         /// Returns the angle between this and the target orientation (the shortest route) in radians.
154         float AngleBetween(const Quat &target) const;
155         /// Returns the axis of rotation to get from this orientation to target orientation (the shortest route).
156         float3 AxisFromTo(const Quat &target) const;
157
158         /// Returns the rotation axis and angle of this quaternion.
159         void ToAxisAngle(float3 &rotationAxis, float &rotationAngleRadians) const;
160         /// Sets this quaternion by specifying the axis about which the rotation is performed, and the angle of rotation.
161         /// @param rotationAxis The axis of rotation. This vector must be normalized to call this function.
162         /// @param rotationAngle The angle of rotation in radians.
163         void SetFromAxisAngle(const float3 &rotationAxis, float rotationAngleRadians);
164
165         /// Sets this quaternion to represent the same rotation as the given matrix.
166         void Set(const float3x3 &matrix);
167         void Set(const float3x4 &matrix);
168         void Set(const float4x4 &matrix);
169         /// Sets all elements of this quaternion.
170         /// @note This sets the raw elements, which do *not* correspond directly to the axis and angle of the rotation. Use
171         ///        SetFromAxisAngle to define this Quat using a rotation axis and an angle.
172         void Set(float xfloat yfloat zfloat w);
173
174         /// Creates a LookAt quaternion.
175         /** A LookAt quaternion is a quaternion that orients an object to face towards a specified target direction.
176                 @param localForward Specifies the forward direction in the local space of the object. This is the direction
177                         the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The
178                         vector to pass in here depends on the conventions you or your modeling software is using, and it is best
179                         pick one convention for all your objects, and be consistent.                    
180                         This input parameter must be a normalized vector.
181                 @param targetDirection Specifies the desired world space direction the object should look at. This function
182                         will compute a quaternion which will rotate the localForward vector to orient towards this targetDirection
183                         vector. This input parameter must be a normalized vector.
184                 @param localUp Specifies the up direction in the local space of the object. This is the up direction the model
185                         was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
186                         or your modeling software is using, and it is best to pick one convention for all your objects, and be
187                         consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
188                         vector localForward, i.e. localForward.Dot(localUp) == 0.
189                 @param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
190                         coincide with another (localForward->targetDirection) would cause the up direction of the resulting
191                         orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep 
192                         the up direction straight, this function orients the localUp direction of the model to point towards the 
193                         specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be 
194                         collinear, but they do not need to be perpendicular either.
195                 @return A quaternion that maps the given local space forward direction vector to point towards the given target
196                         direction, and the given local up direction towards the given target world up direction. For the returned 
197                         quaternion Q it holds that M * localForward = targetDirection, and M * localUp lies in the plane spanned 
198                         by the vectors targetDirection and worldUp.
199                 @see RotateFromTo(). */
200         static Quat LookAt(const float3 &localForward, const float3 &targetDirection, const float3 &localUp, const float3 &worldUp);
201
202         /// Creates a new quaternion that rotates about the positive X axis by the given angle.
203         static Quat RotateX(float angleRadians);
204         /// Creates a new quaternion that rotates about the positive Y axis by the given angle.
205         static Quat RotateY(float angleRadians);
206         /// Creates a new quaternion that rotates about the positive Z axis by the given angle.
207         static Quat RotateZ(float angleRadians);
208
209         /// Creates a new Quat that rotates about the given axis by the given angle.
210         static Quat RotateAxisAngle(const float3 &axisDirection, float angleRadians);
211
212         /// Creates a new quaternion that rotates sourceDirection vector (in world space) to coincide with the 
213         /// targetDirection vector (in world space).
214         /// Rotation is performed around the origin.
215         /// The vectors sourceDirection and targetDirection are assumed to be normalized.
216         /// @note There are multiple such rotations - this function returns the rotation that has the shortest angle
217         /// (when decomposed to axis-angle notation).
218         static Quat RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection);
219
220         /// Creates a new quaternion that
221         /// 1. rotates sourceDirection vector to coincide with the targetDirection vector, and then 
222         /// 2. rotates sourceDirection2 (which was transformed by 1.) to targetDirection2, but keeping the constraint that 
223         ///     sourceDirection must look at targetDirection.
224         static Quat RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection,
225                 const float3 &sourceDirection2, const float3 &targetDirection2);
226
227         /// Creates a new Quat from the given sequence of Euler rotation angles (in radians).
228         /** The FromEulerABC function returns a matrix M = A(a) * B(b) * C(c). Rotation
229                 C is applied first, followed by B and then A. [indexTitle: FromEuler***] */
230         static Quat FromEulerXYX(float x2, float yfloat x);
231         static Quat FromEulerXZX(float x2, float zfloat x); ///< [similarOverload: FromEulerXYX] [hideIndex]
232         static Quat FromEulerYXY(float y2, float xfloat y); ///< [similarOverload: FromEulerXYX] [hideIndex]
233         static Quat FromEulerYZY(float y2, float zfloat y); ///< [similarOverload: FromEulerXYX] [hideIndex]
234         static Quat FromEulerZXZ(float z2, float xfloat z); ///< [similarOverload: FromEulerXYX] [hideIndex]
235         static Quat FromEulerZYZ(float z2, float yfloat z); ///< [similarOverload: FromEulerXYX] [hideIndex]
236         static Quat FromEulerXYZ(float xfloat yfloat z); ///< [similarOverload: FromEulerXYX] [hideIndex]
237         static Quat FromEulerXZY(float xfloat zfloat y); ///< [similarOverload: FromEulerXYX] [hideIndex]
238         static Quat FromEulerYXZ(float yfloat xfloat z); ///< [similarOverload: FromEulerXYX] [hideIndex]
239         static Quat FromEulerYZX(float yfloat zfloat x); ///< [similarOverload: FromEulerXYX] [hideIndex]
240         static Quat FromEulerZXY(float zfloat xfloat y); ///< [similarOverload: FromEulerXYX] [hideIndex]
241         static Quat FromEulerZYX(float zfloat yfloat x); ///< [similarOverload: FromEulerXYX] [hideIndex]
242
243         /// Returns a uniformly random unitary quaternion.
244         static Quat RandomRotation(LCG &lcg);
245
246         /// Extracts the rotation part of this quaternion into Euler rotation angles (in radians).
247         /** @note It is better to think about the returned float3 as an array of three floats, and
248                         not as a triple of xyz, because e.g. the .y component returned by ToEulerYXZ() does
249                         not return the amount of rotation about the y axis, but contains the amount of rotation
250                         in the second axis, in this case the x axis.
251                 @return A float3 which specifies the rotation of this quaternion in radian Euler angles.
252                         The function ToEulerABC returns a float3 where the first
253                         element ([0], or x) specifies the rotation about the axis A (not necessarily the X axis!), 
254                         [1] or y specifies the rotation about the B axis (not necessarily the Y axis!) and
255                         [2] or z specifies the rotation about the C axis (not necessarily the Z axis!). The
256                         order of rotations follows the M*v convention, meaning that ToEulerXYZ returns the Euler
257                         angles for rotating a vector v in the order X * (Y * (Z * v))), i.e. right-to-left. */
258         float3 ToEulerXYX() const;
259         float3 ToEulerXZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
260         float3 ToEulerYXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
261         float3 ToEulerYZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
262         float3 ToEulerZXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
263         float3 ToEulerZYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
264         float3 ToEulerXYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
265         float3 ToEulerXZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
266         float3 ToEulerYXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
267         float3 ToEulerYZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
268         float3 ToEulerZXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
269         float3 ToEulerZYX() const///< [similarOverload: ToEulerXYX] [hideIndex]
270
271         float3x3 ToFloat3x3() const;
272         float3x4 ToFloat3x4() const;
273         float4x4 ToFloat4x4() const;
274
275 #ifdef MATH_ENABLE_STL_SUPPORT
276         /// Returns "(x,y,z,w)".
277         std::string ToString() const;
278
279         /// Returns "Quat(axis:(x,y,z) angle:degrees)".
280         std::string ToString2() const;
281
282         /// Returns "x y z w". This is the preferred format for the quaternion if it has to be serialized to a string for machine transfer.
283         std::string SerializeToString() const;
284 #endif
285         /// Parses a string that is of form "x,y,z,w" or "(x,y,z,w)" or "(x;y;z;w)" or "x y z w" to a new quaternion.
286         static Quat FromString(const char *str);
287 #ifdef MATH_ENABLE_STL_SUPPORT
288         static Quat FromString(const std::string &str) { return FromString(str.c_str()); }
289 #endif
290
291         /// Multiplies two quaternions together.
292         /// The product q1 * q2 returns a quaternion that concatenates the two orientation rotations. The rotation
293         /// q2 is applied first before q1.
294         Quat operator *(const Quat &rhs) const;
295
296         /// Transforms the given vector by this Quaternion.
297         /// @note Technically, this function does not perform a simple multiplication of 'q * v', 
298         /// but instead performs a conjugation operation 'q*v*q^-1'. This corresponds to transforming
299         /// the given vector by this Quaternion.
300         float3 operator *(const float3 &rhs) const;
301
302         /// The identity quaternion performs no rotation when applied to a vector.
303         /// For quaternions, the identity has the value r = 1, i,j,k = 0.
304         static const Quat identity;
305         /// A compile-time constant Quat with value (NaN, NaN, NaN, NaN).
306         /// For this constant, each element has the value of quiet NaN, or Not-A-Number.
307         /// @note Never compare a Quat to this value! Due to how IEEE floats work, for each float x, both the expression "x == nan" and "x == nan" returns false!
308         ///        That is, nothing is equal to NaN, not even NaN itself!
309         static const Quat nan;
310
311         /// Divides a quaternion by another. Division "a / b" results in a quaternion that rotates the orientation b to coincide with the orientation a.
312         Quat operator /(const Quat &rhs) const;
313
314 #ifdef MATH_OGRE_INTEROP
315         Quat(const Ogre::Quaternion &other) { w = other.w; x = other.x; y = other.y; z = other.z; }
316         operator Ogre::Quaternion() const return Ogre::Quaternion(wxyz); }
317 #endif
318 /*
319 #ifdef MATH_IRRLICHT_INTEROP
320         Quat(const Quaternion &other) { w = other.w; x = other.x; y = other.y; z = other.z; }
321         operator Quaternion() const { return Quaternion(x, y, z, w); }
322 #endif
323 */
324 #ifdef MATH_QT_INTEROP
325         Quat(const QQuaternion &other) { w = other.scalar(); x = other.x(); y = other.y(); z = other.z(); }
326         operator QQuaternion() const return QQuaternion(wxyz); }
327         operator QString() const return toString(); }
328         QString toString() const return ToString2().c_str(); }
329         QQuaternion ToQQuaternion() const return (QQuaternion)*this; }
330         static Quat FromQQuaternion(const QQuaternion &q) { return (Quat)q; }
331         static Quat FromString(const QString &str) { return FromString(str.toStdString()); }
332 #endif
333 #ifdef MATH_BULLET_INTEROP
334         Quat(const btQuaternion &other) { w = other.w(); x = other.x(); y = other.y(); z = other.z(); }
335         operator btQuaternion() const return btQuaternion(xyzw); }
336 #endif
337
338         /// Multiplies two quaternions in the order 'this * rhs'.
339         /// This corresponds to the concatenation of the two operations ('this * rhs * vector' applies the rotation 'rhs' first, followed by the rotation 'this'.
340         Quat Mul(const Quat &rhs) const;
341         /// Converts the given matrix to a quaternion and computes the concatenated transform 'this * rhs'.
342         Quat Mul(const float3x3 &rhs) const;
343         /// Transforms the given vector by this Quaternion.
344         /// @note Technically, this function does not perform a simple multiplication of 'q * v', 
345         /// but instead performs a conjugation operation 'q*v*q^-1'. This corresponds to transforming
346         /// the given vector by this Quaternion.
347         float3 Mul(const float3 &vector) const;
348         float4 Mul(const float4 &vector) const;
349
350 private// Hide the unsafe operations from the user, so that he doesn't accidentally invoke an unintended operation.
351
352         /// Multiplies a quaternion by a scalar.
353         /// @note Technically, multiplication by scalar would not affect the rotation this quaternion represents, but since
354         /// Quat uses conjugation to compute the inverse (to optimize), an unnormalized quaternion will not produce a proper rotation transform.
355         /// @important Multiplication by a scalar does not "accumulate" rotations, e.g. "quat * 5.f" will not produce a quaternion that would rotate
356         ///                     "5 times more".
357         Quat operator *(float scalar) const;
358
359         Quat operator /(float scalar) const;
360
361         /// Adds two quaternions.
362         /// @important Adding two quaternions does not concatenate the two rotation operations. Use quaternion multiplication to achieve that.
363         Quat operator +(const Quat &rhs) const;
364
365         Quat operator -(const Quat &rhs) const;
366
367         /// Negates the quaternion.
368         /// @important Negating a quaternion will not produce the inverse rotation. Call Quat::Inverse() to generate the inverse rotation.
369         Quat operator -() const;
370 };
371
372 #ifdef MATH_ENABLE_STL_SUPPORT
373 /// Prints this Quat to the given stream.
374 std::ostream &operator <<(std::ostream &out, const Quat &rhs);
375 #endif
376
377 Quat Lerp(const Quat &a, const Quat &b, float t);
378 Quat Slerp(const Quat &a, const Quat &b, float t);
379
380 MATH_END_NAMESPACE
381
382 #ifdef MATH_QT_INTEROP
383 Q_DECLARE_METATYPE(Quat)
384 Q_DECLARE_METATYPE(Quat*)
385 #endif

Go back to previous page