Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/bullet/LinearMath/btQuaternion.h @ 8988

Last change on this file since 8988 was 8393, checked in by rgrieder, 14 years ago

Updated Bullet from v2.77 to v2.78.
(I'm not going to make a branch for that since the update from 2.74 to 2.77 hasn't been tested that much either).

You will HAVE to do a complete RECOMPILE! I tested with MSVC and MinGW and they both threw linker errors at me.

  • Property svn:eol-style set to native
File size: 14.4 KB
Line 
1/*
2Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
3
4This software is provided 'as-is', without any express or implied warranty.
5In no event will the authors be held liable for any damages arising from the use of this software.
6Permission is granted to anyone to use this software for any purpose,
7including commercial applications, and to alter it and redistribute it freely,
8subject to the following restrictions:
9
101. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
112. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
123. This notice may not be removed or altered from any source distribution.
13*/
14
15
16
17#ifndef BT_SIMD__QUATERNION_H_
18#define BT_SIMD__QUATERNION_H_
19
20
21#include "btVector3.h"
22#include "btQuadWord.h"
23
24/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
25class btQuaternion : public btQuadWord {
26public:
27  /**@brief No initialization constructor */
28        btQuaternion() {}
29
30        //              template <typename btScalar>
31        //              explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
32  /**@brief Constructor from scalars */
33        btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) 
34                : btQuadWord(x, y, z, w) 
35        {}
36  /**@brief Axis angle Constructor
37   * @param axis The axis which the rotation is around
38   * @param angle The magnitude of the rotation around the angle (Radians) */
39        btQuaternion(const btVector3& axis, const btScalar& angle) 
40        { 
41                setRotation(axis, angle); 
42        }
43  /**@brief Constructor from Euler angles
44   * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
45   * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
46   * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
47        btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
48        { 
49#ifndef BT_EULER_DEFAULT_ZYX
50                setEuler(yaw, pitch, roll); 
51#else
52                setEulerZYX(yaw, pitch, roll); 
53#endif
54        }
55  /**@brief Set the rotation using axis angle notation
56   * @param axis The axis around which to rotate
57   * @param angle The magnitude of the rotation in Radians */
58        void setRotation(const btVector3& axis, const btScalar& angle)
59        {
60                btScalar d = axis.length();
61                btAssert(d != btScalar(0.0));
62                btScalar s = btSin(angle * btScalar(0.5)) / d;
63                setValue(axis.x() * s, axis.y() * s, axis.z() * s, 
64                        btCos(angle * btScalar(0.5)));
65        }
66  /**@brief Set the quaternion using Euler angles
67   * @param yaw Angle around Y
68   * @param pitch Angle around X
69   * @param roll Angle around Z */
70        void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
71        {
72                btScalar halfYaw = btScalar(yaw) * btScalar(0.5); 
73                btScalar halfPitch = btScalar(pitch) * btScalar(0.5); 
74                btScalar halfRoll = btScalar(roll) * btScalar(0.5); 
75                btScalar cosYaw = btCos(halfYaw);
76                btScalar sinYaw = btSin(halfYaw);
77                btScalar cosPitch = btCos(halfPitch);
78                btScalar sinPitch = btSin(halfPitch);
79                btScalar cosRoll = btCos(halfRoll);
80                btScalar sinRoll = btSin(halfRoll);
81                setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
82                        cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
83                        sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
84                        cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
85        }
86  /**@brief Set the quaternion using euler angles
87   * @param yaw Angle around Z
88   * @param pitch Angle around Y
89   * @param roll Angle around X */
90        void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
91        {
92                btScalar halfYaw = btScalar(yaw) * btScalar(0.5); 
93                btScalar halfPitch = btScalar(pitch) * btScalar(0.5); 
94                btScalar halfRoll = btScalar(roll) * btScalar(0.5); 
95                btScalar cosYaw = btCos(halfYaw);
96                btScalar sinYaw = btSin(halfYaw);
97                btScalar cosPitch = btCos(halfPitch);
98                btScalar sinPitch = btSin(halfPitch);
99                btScalar cosRoll = btCos(halfRoll);
100                btScalar sinRoll = btSin(halfRoll);
101                setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
102                         cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
103                         cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
104                         cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
105        }
106  /**@brief Add two quaternions
107   * @param q The quaternion to add to this one */
108        SIMD_FORCE_INLINE       btQuaternion& operator+=(const btQuaternion& q)
109        {
110                m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
111                return *this;
112        }
113
114  /**@brief Subtract out a quaternion
115   * @param q The quaternion to subtract from this one */
116        btQuaternion& operator-=(const btQuaternion& q) 
117        {
118                m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
119                return *this;
120        }
121
122  /**@brief Scale this quaternion
123   * @param s The scalar to scale by */
124        btQuaternion& operator*=(const btScalar& s)
125        {
126                m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
127                return *this;
128        }
129
130  /**@brief Multiply this quaternion by q on the right
131   * @param q The other quaternion
132   * Equivilant to this = this * q */
133        btQuaternion& operator*=(const btQuaternion& q)
134        {
135                setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
136                        m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
137                        m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
138                        m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
139                return *this;
140        }
141  /**@brief Return the dot product between this quaternion and another
142   * @param q The other quaternion */
143        btScalar dot(const btQuaternion& q) const
144        {
145                return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
146        }
147
148  /**@brief Return the length squared of the quaternion */
149        btScalar length2() const
150        {
151                return dot(*this);
152        }
153
154  /**@brief Return the length of the quaternion */
155        btScalar length() const
156        {
157                return btSqrt(length2());
158        }
159
160  /**@brief Normalize the quaternion
161   * Such that x^2 + y^2 + z^2 +w^2 = 1 */
162        btQuaternion& normalize() 
163        {
164                return *this /= length();
165        }
166
167  /**@brief Return a scaled version of this quaternion
168   * @param s The scale factor */
169        SIMD_FORCE_INLINE btQuaternion
170        operator*(const btScalar& s) const
171        {
172                return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
173        }
174
175
176  /**@brief Return an inversely scaled versionof this quaternion
177   * @param s The inverse scale factor */
178        btQuaternion operator/(const btScalar& s) const
179        {
180                btAssert(s != btScalar(0.0));
181                return *this * (btScalar(1.0) / s);
182        }
183
184  /**@brief Inversely scale this quaternion
185   * @param s The scale factor */
186        btQuaternion& operator/=(const btScalar& s) 
187        {
188                btAssert(s != btScalar(0.0));
189                return *this *= btScalar(1.0) / s;
190        }
191
192  /**@brief Return a normalized version of this quaternion */
193        btQuaternion normalized() const 
194        {
195                return *this / length();
196        } 
197  /**@brief Return the angle between this quaternion and the other
198   * @param q The other quaternion */
199        btScalar angle(const btQuaternion& q) const 
200        {
201                btScalar s = btSqrt(length2() * q.length2());
202                btAssert(s != btScalar(0.0));
203                return btAcos(dot(q) / s);
204        }
205  /**@brief Return the angle of rotation represented by this quaternion */
206        btScalar getAngle() const 
207        {
208                btScalar s = btScalar(2.) * btAcos(m_floats[3]);
209                return s;
210        }
211
212        /**@brief Return the axis of the rotation represented by this quaternion */
213        btVector3 getAxis() const
214        {
215                btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.));
216                if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
217                        return btVector3(1.0, 0.0, 0.0);  // Arbitrary
218                btScalar s = btSqrt(s_squared);
219                return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s);
220        }
221
222        /**@brief Return the inverse of this quaternion */
223        btQuaternion inverse() const
224        {
225                return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
226        }
227
228  /**@brief Return the sum of this quaternion and the other
229   * @param q2 The other quaternion */
230        SIMD_FORCE_INLINE btQuaternion
231        operator+(const btQuaternion& q2) const
232        {
233                const btQuaternion& q1 = *this;
234                return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
235        }
236
237  /**@brief Return the difference between this quaternion and the other
238   * @param q2 The other quaternion */
239        SIMD_FORCE_INLINE btQuaternion
240        operator-(const btQuaternion& q2) const
241        {
242                const btQuaternion& q1 = *this;
243                return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
244        }
245
246  /**@brief Return the negative of this quaternion
247   * This simply negates each element */
248        SIMD_FORCE_INLINE btQuaternion operator-() const
249        {
250                const btQuaternion& q2 = *this;
251                return btQuaternion( - q2.x(), - q2.y(),  - q2.z(),  - q2.m_floats[3]);
252        }
253  /**@todo document this and it's use */
254        SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 
255        {
256                btQuaternion diff,sum;
257                diff = *this - qd;
258                sum = *this + qd;
259                if( diff.dot(diff) > sum.dot(sum) )
260                        return qd;
261                return (-qd);
262        }
263
264        /**@todo document this and it's use */
265        SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 
266        {
267                btQuaternion diff,sum;
268                diff = *this - qd;
269                sum = *this + qd;
270                if( diff.dot(diff) < sum.dot(sum) )
271                        return qd;
272                return (-qd);
273        }
274
275
276  /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
277   * @param q The other quaternion to interpolate with
278   * @param t The ratio between this and q to interpolate.  If t = 0 the result is this, if t=1 the result is q.
279   * Slerp interpolates assuming constant velocity.  */
280        btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
281        {
282                btScalar theta = angle(q);
283                if (theta != btScalar(0.0))
284                {
285                        btScalar d = btScalar(1.0) / btSin(theta);
286                        btScalar s0 = btSin((btScalar(1.0) - t) * theta);
287                        btScalar s1 = btSin(t * theta);   
288                        if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
289                          return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
290                                              (m_floats[1] * s0 + -q.y() * s1) * d,
291                                              (m_floats[2] * s0 + -q.z() * s1) * d,
292                                              (m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
293                        else
294                          return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
295                                              (m_floats[1] * s0 + q.y() * s1) * d,
296                                              (m_floats[2] * s0 + q.z() * s1) * d,
297                                              (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
298                       
299                }
300                else
301                {
302                        return *this;
303                }
304        }
305
306        static const btQuaternion&      getIdentity()
307        {
308                static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
309                return identityQuat;
310        }
311
312        SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
313
314       
315};
316
317
318/**@brief Return the negative of a quaternion */
319SIMD_FORCE_INLINE btQuaternion
320operator-(const btQuaternion& q)
321{
322        return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w());
323}
324
325
326
327/**@brief Return the product of two quaternions */
328SIMD_FORCE_INLINE btQuaternion
329operator*(const btQuaternion& q1, const btQuaternion& q2) {
330        return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
331                q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
332                q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
333                q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 
334}
335
336SIMD_FORCE_INLINE btQuaternion
337operator*(const btQuaternion& q, const btVector3& w)
338{
339        return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
340                q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
341                q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
342                -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 
343}
344
345SIMD_FORCE_INLINE btQuaternion
346operator*(const btVector3& w, const btQuaternion& q)
347{
348        return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
349                w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
350                w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
351                -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 
352}
353
354/**@brief Calculate the dot product between two quaternions */
355SIMD_FORCE_INLINE btScalar
356dot(const btQuaternion& q1, const btQuaternion& q2) 
357{ 
358        return q1.dot(q2); 
359}
360
361
362/**@brief Return the length of a quaternion */
363SIMD_FORCE_INLINE btScalar
364length(const btQuaternion& q) 
365{ 
366        return q.length(); 
367}
368
369/**@brief Return the angle between two quaternions*/
370SIMD_FORCE_INLINE btScalar
371angle(const btQuaternion& q1, const btQuaternion& q2) 
372{ 
373        return q1.angle(q2); 
374}
375
376/**@brief Return the inverse of a quaternion*/
377SIMD_FORCE_INLINE btQuaternion
378inverse(const btQuaternion& q) 
379{
380        return q.inverse();
381}
382
383/**@brief Return the result of spherical linear interpolation betwen two quaternions
384 * @param q1 The first quaternion
385 * @param q2 The second quaternion
386 * @param t The ration between q1 and q2.  t = 0 return q1, t=1 returns q2
387 * Slerp assumes constant velocity between positions. */
388SIMD_FORCE_INLINE btQuaternion
389slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 
390{
391        return q1.slerp(q2, t);
392}
393
394SIMD_FORCE_INLINE btVector3
395quatRotate(const btQuaternion& rotation, const btVector3& v) 
396{
397        btQuaternion q = rotation * v;
398        q *= rotation.inverse();
399        return btVector3(q.getX(),q.getY(),q.getZ());
400}
401
402SIMD_FORCE_INLINE btQuaternion
403shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
404{
405        btVector3 c = v0.cross(v1);
406        btScalar  d = v0.dot(v1);
407
408        if (d < -1.0 + SIMD_EPSILON)
409        {
410                btVector3 n,unused;
411                btPlaneSpace1(v0,n,unused);
412                return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
413        }
414
415        btScalar  s = btSqrt((1.0f + d) * 2.0f);
416        btScalar rs = 1.0f / s;
417
418        return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
419}
420
421SIMD_FORCE_INLINE btQuaternion
422shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
423{
424        v0.normalize();
425        v1.normalize();
426        return shortestArcQuat(v0,v1);
427}
428
429#endif //BT_SIMD__QUATERNION_H_
430
431
432
433
Note: See TracBrowser for help on using the repository browser.