/src/ogre/OgreMain/include/OgreQuaternion.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | // This file is based on material originally from: |
29 | | // Geometric Tools, LLC |
30 | | // Copyright (c) 1998-2010 |
31 | | // Distributed under the Boost Software License, Version 1.0. |
32 | | // http://www.boost.org/LICENSE_1_0.txt |
33 | | // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt |
34 | | |
35 | | |
36 | | #ifndef __Quaternion_H__ |
37 | | #define __Quaternion_H__ |
38 | | |
39 | | #include "OgrePrerequisites.h" |
40 | | #include "OgreMath.h" |
41 | | |
42 | | namespace Ogre { |
43 | | |
44 | | /** \addtogroup Core |
45 | | * @{ |
46 | | */ |
47 | | /** \addtogroup Math |
48 | | * @{ |
49 | | */ |
50 | | /** Implementation of a Quaternion, i.e. a rotation around an axis. |
51 | | For more information about Quaternions and the theory behind it, we recommend reading: |
52 | | http://www.ogre3d.org/tikiwiki/Quaternion+and+Rotation+Primer and |
53 | | http://www.cprogramming.com/tutorial/3d/quaternions.html and |
54 | | http://www.gamedev.net/page/resources/_/reference/programming/math-and-physics/quaternions/quaternion-powers-r1095 |
55 | | */ |
56 | | class _OgreExport Quaternion |
57 | | { |
58 | | public: |
59 | | /// Default constructor, initializes to identity rotation (aka 0°) |
60 | | inline Quaternion () |
61 | 0 | : w(1), x(0), y(0), z(0) |
62 | 0 | { |
63 | 0 | } |
64 | | /// Copy constructor |
65 | | inline Quaternion(const Ogre::Quaternion& rhs) |
66 | 0 | : w(rhs.w), x(rhs.x), y(rhs.y), z(rhs.z) |
67 | 0 | {} |
68 | | /// Construct from an explicit list of values |
69 | | inline Quaternion ( |
70 | | Real fW, |
71 | | Real fX, Real fY, Real fZ) |
72 | | : w(fW), x(fX), y(fY), z(fZ) |
73 | | { |
74 | | } |
75 | | /// Construct a quaternion from a rotation matrix |
76 | | inline Quaternion(const Matrix3& rot) |
77 | 0 | { |
78 | 0 | this->FromRotationMatrix(rot); |
79 | 0 | } |
80 | | /// Construct a quaternion from an angle/axis |
81 | | inline Quaternion(const Radian& rfAngle, const Vector3& rkAxis) |
82 | 0 | { |
83 | 0 | this->FromAngleAxis(rfAngle, rkAxis); |
84 | 0 | } |
85 | | /// Construct a quaternion from 3 orthonormal local axes |
86 | | inline Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis) |
87 | 0 | { |
88 | 0 | this->FromAxes(xaxis, yaxis, zaxis); |
89 | 0 | } |
90 | | /// Construct a quaternion from 3 orthonormal local axes |
91 | | inline Quaternion(const Vector3* akAxis) |
92 | 0 | { |
93 | 0 | this->FromAxes(akAxis); |
94 | 0 | } |
95 | | /// Construct a quaternion from 4 manual w/x/y/z values |
96 | | inline Quaternion(Real* valptr) |
97 | 0 | { |
98 | 0 | memcpy(&w, valptr, sizeof(Real)*4); |
99 | 0 | } |
100 | | |
101 | | /** Exchange the contents of this quaternion with another. |
102 | | */ |
103 | | inline void swap(Quaternion& other) |
104 | 0 | { |
105 | 0 | std::swap(w, other.w); |
106 | 0 | std::swap(x, other.x); |
107 | 0 | std::swap(y, other.y); |
108 | 0 | std::swap(z, other.z); |
109 | 0 | } |
110 | | |
111 | | /// Array accessor operator |
112 | | inline Real operator [] ( const size_t i ) const |
113 | 0 | { |
114 | 0 | assert( i < 4 ); |
115 | 0 |
|
116 | 0 | return *(&w+i); |
117 | 0 | } |
118 | | |
119 | | /// Array accessor operator |
120 | | inline Real& operator [] ( const size_t i ) |
121 | 0 | { |
122 | 0 | assert( i < 4 ); |
123 | 0 |
|
124 | 0 | return *(&w+i); |
125 | 0 | } |
126 | | |
127 | | /// Pointer accessor for direct copying |
128 | | inline Real* ptr() |
129 | 0 | { |
130 | 0 | return &w; |
131 | 0 | } |
132 | | |
133 | | /// Pointer accessor for direct copying |
134 | | inline const Real* ptr() const |
135 | 0 | { |
136 | 0 | return &w; |
137 | 0 | } |
138 | | |
139 | | void FromRotationMatrix (const Matrix3& kRot); |
140 | | void ToRotationMatrix (Matrix3& kRot) const; |
141 | | /** Setups the quaternion using the supplied vector, and "roll" around |
142 | | that vector by the specified radians. |
143 | | */ |
144 | | void FromAngleAxis (const Radian& rfAngle, const Vector3& rkAxis); |
145 | | void ToAngleAxis (Radian& rfAngle, Vector3& rkAxis) const; |
146 | 0 | inline void ToAngleAxis (Degree& dAngle, Vector3& rkAxis) const { |
147 | 0 | Radian rAngle; |
148 | 0 | ToAngleAxis ( rAngle, rkAxis ); |
149 | 0 | dAngle = rAngle; |
150 | 0 | } |
151 | | /** Constructs the quaternion using 3 axes, the axes are assumed to be orthonormal |
152 | | @see FromAxes |
153 | | */ |
154 | | void FromAxes (const Vector3* akAxis); |
155 | | void FromAxes (const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis); |
156 | | /** Gets the 3 orthonormal axes defining the quaternion. @see FromAxes */ |
157 | | void ToAxes (Vector3* akAxis) const; |
158 | | void ToAxes (Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) const; |
159 | | |
160 | | /** Returns the X orthonormal axis defining the quaternion. Same as doing |
161 | | xAxis = Vector3::UNIT_X * this. Also called the local X-axis |
162 | | */ |
163 | | Vector3 xAxis(void) const; |
164 | | |
165 | | /** Returns the Y orthonormal axis defining the quaternion. Same as doing |
166 | | yAxis = Vector3::UNIT_Y * this. Also called the local Y-axis |
167 | | */ |
168 | | Vector3 yAxis(void) const; |
169 | | |
170 | | /** Returns the Z orthonormal axis defining the quaternion. Same as doing |
171 | | zAxis = Vector3::UNIT_Z * this. Also called the local Z-axis |
172 | | */ |
173 | | Vector3 zAxis(void) const; |
174 | | |
175 | | inline Quaternion& operator= (const Quaternion& rkQ) |
176 | 0 | { |
177 | 0 | w = rkQ.w; |
178 | 0 | x = rkQ.x; |
179 | 0 | y = rkQ.y; |
180 | 0 | z = rkQ.z; |
181 | 0 | return *this; |
182 | 0 | } |
183 | | Quaternion operator+ (const Quaternion& rkQ) const; |
184 | | Quaternion operator- (const Quaternion& rkQ) const; |
185 | | Quaternion operator*(const Quaternion& rkQ) const; |
186 | | Quaternion operator*(Real s) const |
187 | 0 | { |
188 | 0 | return Quaternion(s * w, s * x, s * y, s * z); |
189 | 0 | } |
190 | | friend Quaternion operator*(Real s, const Quaternion& q) |
191 | 0 | { |
192 | 0 | return q * s; |
193 | 0 | } |
194 | 0 | Quaternion operator-() const { return Quaternion(-w, -x, -y, -z); } |
195 | | inline bool operator== (const Quaternion& rhs) const |
196 | 0 | { |
197 | 0 | return (rhs.x == x) && (rhs.y == y) && |
198 | 0 | (rhs.z == z) && (rhs.w == w); |
199 | 0 | } |
200 | | inline bool operator!= (const Quaternion& rhs) const |
201 | 0 | { |
202 | 0 | return !operator==(rhs); |
203 | 0 | } |
204 | | // functions of a quaternion |
205 | | /// Returns the dot product of the quaternion |
206 | | Real Dot(const Quaternion& rkQ) const |
207 | 0 | { |
208 | 0 | return w * rkQ.w + x * rkQ.x + y * rkQ.y + z * rkQ.z; |
209 | 0 | } |
210 | | /// Returns the normal length of this quaternion. |
211 | 0 | Real Norm() const { return Math::Sqrt(w * w + x * x + y * y + z * z); } |
212 | | /// Normalises this quaternion, and returns the previous length |
213 | | Real normalise(void) |
214 | 0 | { |
215 | 0 | Real len = Norm(); |
216 | 0 | *this = 1.0f / len * *this; |
217 | 0 | return len; |
218 | 0 | } |
219 | | Quaternion Inverse () const; /// Apply to non-zero quaternion |
220 | | Quaternion UnitInverse () const; /// Apply to unit-length quaternion |
221 | | Quaternion Exp () const; |
222 | | Quaternion Log () const; |
223 | | |
224 | | /// Rotation of a vector by a quaternion |
225 | | Vector3 operator* (const Vector3& rkVector) const; |
226 | | |
227 | | /** Calculate the local roll element of this quaternion. |
228 | | @param reprojectAxis By default the method returns the 'intuitive' result |
229 | | that is, if you projected the local X of the quaternion onto the XY plane, |
230 | | the angle between it and global X is returned. The co-domain of the returned |
231 | | value is from -180 to 180 degrees. If set to false though, the result is |
232 | | the rotation around Z axis that could be used to implement the quaternion |
233 | | using some non-intuitive order of rotations. This behavior is preserved for |
234 | | backward compatibility, to decompose quaternion into yaw, pitch and roll use |
235 | | q.ToRotationMatrix().ToEulerAnglesYXZ(yaw, pitch, roll) instead. |
236 | | */ |
237 | | Radian getRoll(bool reprojectAxis = true) const; |
238 | | /** Calculate the local pitch element of this quaternion |
239 | | @param reprojectAxis By default the method returns the 'intuitive' result |
240 | | that is, if you projected the local Y of the quaternion onto the YZ plane, |
241 | | the angle between it and global Y is returned. The co-domain of the returned |
242 | | value is from -180 to 180 degrees. If set to false though, the result is |
243 | | the rotation around X axis that could be used to implement the quaternion |
244 | | using some non-intuitive order of rotations. This behavior is preserved for |
245 | | backward compatibility, to decompose quaternion into yaw, pitch and roll use |
246 | | q.ToRotationMatrix().ToEulerAnglesYXZ(yaw, pitch, roll) instead. |
247 | | */ |
248 | | Radian getPitch(bool reprojectAxis = true) const; |
249 | | /** Calculate the local yaw element of this quaternion |
250 | | @param reprojectAxis By default the method returns the 'intuitive' result |
251 | | that is, if you projected the local Z of the quaternion onto the ZX plane, |
252 | | the angle between it and global Z is returned. The co-domain of the returned |
253 | | value is from -180 to 180 degrees. If set to false though, the result is |
254 | | the rotation around Y axis that could be used to implement the quaternion |
255 | | using some non-intuitive order of rotations. This behavior is preserved for |
256 | | backward compatibility, to decompose quaternion into yaw, pitch and roll use |
257 | | q.ToRotationMatrix().ToEulerAnglesYXZ(yaw, pitch, roll) instead. |
258 | | */ |
259 | | Radian getYaw(bool reprojectAxis = true) const; |
260 | | |
261 | | /** Equality with tolerance (tolerance is max angle difference) |
262 | | @remark Both equals() and orientationEquals() measure the exact same thing. |
263 | | One measures the difference by angle, the other by a different, non-linear metric. |
264 | | */ |
265 | | bool equals(const Quaternion& rhs, const Radian& tolerance) const |
266 | 0 | { |
267 | 0 | Real d = Dot(rhs); |
268 | 0 | Radian angle = Math::ACos(2.0f * d*d - 1.0f); |
269 | 0 |
|
270 | 0 | return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); |
271 | 0 | } |
272 | | |
273 | | /** Compare two quaternions which are assumed to be used as orientations. |
274 | | @remark Both equals() and orientationEquals() measure the exact same thing. |
275 | | One measures the difference by angle, the other by a different, non-linear metric. |
276 | | @return true if the two orientations are the same or very close, relative to the given tolerance. |
277 | | Slerp ( 0.75f, A, B ) != Slerp ( 0.25f, B, A ); |
278 | | therefore be careful if your code relies in the order of the operands. |
279 | | This is specially important in IK animation. |
280 | | */ |
281 | | inline bool orientationEquals( const Quaternion& other, Real tolerance = 1e-3f ) const |
282 | 0 | { |
283 | 0 | Real d = this->Dot(other); |
284 | 0 | return 1 - d*d < tolerance; |
285 | 0 | } |
286 | | |
287 | | /** Performs Spherical linear interpolation between two quaternions, and returns the result. |
288 | | Slerp ( 0.0f, A, B ) = A |
289 | | Slerp ( 1.0f, A, B ) = B |
290 | | @return Interpolated quaternion |
291 | | |
292 | | Slerp has the proprieties of performing the interpolation at constant |
293 | | velocity, and being torque-minimal (unless shortestPath=false). |
294 | | However, it's NOT commutative, which means |
295 | | Slerp ( 0.75f, A, B ) != Slerp ( 0.25f, B, A ); |
296 | | therefore be careful if your code relies in the order of the operands. |
297 | | This is specially important in IK animation. |
298 | | */ |
299 | | static Quaternion Slerp (Real fT, const Quaternion& rkP, |
300 | | const Quaternion& rkQ, bool shortestPath = false); |
301 | | |
302 | | /** @see Slerp. It adds extra "spins" (i.e. rotates several times) specified |
303 | | by parameter 'iExtraSpins' while interpolating before arriving to the |
304 | | final values |
305 | | */ |
306 | | static Quaternion SlerpExtraSpins (Real fT, |
307 | | const Quaternion& rkP, const Quaternion& rkQ, |
308 | | int iExtraSpins); |
309 | | |
310 | | /// Setup for spherical quadratic interpolation |
311 | | static void Intermediate (const Quaternion& rkQ0, |
312 | | const Quaternion& rkQ1, const Quaternion& rkQ2, |
313 | | Quaternion& rka, Quaternion& rkB); |
314 | | |
315 | | /// Spherical quadratic interpolation |
316 | | static Quaternion Squad (Real fT, const Quaternion& rkP, |
317 | | const Quaternion& rkA, const Quaternion& rkB, |
318 | | const Quaternion& rkQ, bool shortestPath = false); |
319 | | |
320 | | /** Performs Normalised linear interpolation between two quaternions, and returns the result. |
321 | | nlerp ( 0.0f, A, B ) = A |
322 | | nlerp ( 1.0f, A, B ) = B |
323 | | |
324 | | Nlerp is faster than Slerp. |
325 | | Nlerp has the proprieties of being commutative (@see Slerp; |
326 | | commutativity is desired in certain places, like IK animation), and |
327 | | being torque-minimal (unless shortestPath=false). However, it's performing |
328 | | the interpolation at non-constant velocity; sometimes this is desired, |
329 | | sometimes it is not. Having a non-constant velocity can produce a more |
330 | | natural rotation feeling without the need of tweaking the weights; however |
331 | | if your scene relies on the timing of the rotation or assumes it will point |
332 | | at a specific angle at a specific weight value, Slerp is a better choice. |
333 | | */ |
334 | | static Quaternion nlerp(Real fT, const Quaternion& rkP, |
335 | | const Quaternion& rkQ, bool shortestPath = false); |
336 | | |
337 | | /// Cutoff for sine near zero |
338 | | static const Real msEpsilon; |
339 | | |
340 | | // special values |
341 | | static const Quaternion ZERO; |
342 | | static const Quaternion IDENTITY; |
343 | | |
344 | | Real w, x, y, z; |
345 | | |
346 | | #ifndef OGRE_FAST_MATH |
347 | | /// Check whether this quaternion contains valid values |
348 | | inline bool isNaN() const |
349 | 0 | { |
350 | 0 | return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w); |
351 | 0 | } |
352 | | #endif |
353 | | |
354 | | /** Function for writing to a stream. Outputs "Quaternion(w, x, y, z)" with w,x,y,z |
355 | | being the member values of the quaternion. |
356 | | */ |
357 | | inline friend std::ostream& operator << |
358 | | ( std::ostream& o, const Quaternion& q ) |
359 | 0 | { |
360 | 0 | o << "Quaternion(" << q.w << ", " << q.x << ", " << q.y << ", " << q.z << ")"; |
361 | 0 | return o; |
362 | 0 | } |
363 | | |
364 | | }; |
365 | | /** @} */ |
366 | | /** @} */ |
367 | | |
368 | | } |
369 | | |
370 | | |
371 | | |
372 | | |
373 | | #endif |