2 * Copyright 2008 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
12 * This is a refactored and stripped down version of
13 * bullet-2.66 src\LinearMath\btQuaternion.h
14 * The dependancies on base class btQuadWord have been removed for
16 * Added gl matrix conversion method.
21 Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans
22 http://continuousphysics.com/Bullet/
24 This software is provided 'as-is', without any express or implied warranty.
25 In no event will the authors be held liable for any damages arising from the
27 Permission is granted to anyone to use this software for any purpose,
28 including commercial applications, and to alter it and redistribute it freely,
29 subject to the following restrictions:
31 1. The origin of this software must not be misrepresented; you must not claim
32 that you wrote the original software. If you use this software in a product,
33 an acknowledgment in the product documentation would be appreciated but is
35 2. Altered source versions must be plainly marked as such, and must not be
36 misrepresented as being the original software.
37 3. This notice may not be removed or altered from any source distribution.
39 #ifndef __QUATERNION_H__
40 #define __QUATERNION_H__
43 #include <SupportDefs.h>
54 Quaternion(const Quaternion
& q
)
56 *((Quaternion
*)this) = q
;
59 Quaternion(const float& x
, const float& y
, const float& z
, const float& w
)
61 m_x
= x
, m_y
= y
, m_z
= z
, m_w
= w
;
64 Quaternion(const Vector3
& axis
, const float& angle
)
66 setRotation(axis
, angle
);
69 Quaternion(const float& yaw
, const float& pitch
, const float& roll
)
71 setEuler(yaw
, pitch
, roll
);
74 inline const float& x() const { return m_x
; }
77 inline const float& y() const { return m_y
; }
80 inline const float& z() const { return m_z
; }
83 inline const float& w() const { return m_w
; }
86 void setValue(const float& x
, const float& y
, const float& z
)
95 void setValue(const float& x
, const float& y
, const float& z
, const float& w
)
104 void setRotation(const Vector3
& axis
, const float& angle
)
106 float d
= axis
.length();
108 float s
= sin(angle
* 0.5f
) / d
;
109 setValue(axis
.x() * s
, axis
.y() * s
, axis
.z() * s
,
114 void setEuler(const float& yaw
, const float& pitch
, const float& roll
)
116 float halfYaw
= yaw
* 0.5f
;
117 float halfPitch
= pitch
* 0.5f
;
118 float halfRoll
= roll
* 0.5f
;
119 float cosYaw
= cos(halfYaw
);
120 float sinYaw
= sin(halfYaw
);
121 float cosPitch
= cos(halfPitch
);
122 float sinPitch
= sin(halfPitch
);
123 float cosRoll
= cos(halfRoll
);
124 float sinRoll
= sin(halfRoll
);
125 setValue(cosRoll
* sinPitch
* cosYaw
+ sinRoll
* cosPitch
* sinYaw
,
126 cosRoll
* cosPitch
* sinYaw
- sinRoll
* sinPitch
* cosYaw
,
127 sinRoll
* cosPitch
* cosYaw
- cosRoll
* sinPitch
* sinYaw
,
128 cosRoll
* cosPitch
* cosYaw
+ sinRoll
* sinPitch
* sinYaw
);
132 Quaternion
& operator+=(const Quaternion
& q
)
134 m_x
+= q
.x(); m_y
+= q
.y(); m_z
+= q
.z(); m_w
+= q
.m_w
;
139 Quaternion
& operator-=(const Quaternion
& q
)
141 m_x
-= q
.x(); m_y
-= q
.y(); m_z
-= q
.z(); m_w
-= q
.m_w
;
146 Quaternion
& operator*=(const float& s
)
148 m_x
*= s
; m_y
*= s
; m_z
*= s
; m_w
*= s
;
153 Quaternion
& operator*=(const Quaternion
& q
)
155 setValue(m_w
* q
.x() + m_x
* q
.m_w
+ m_y
* q
.z() - m_z
* q
.y(),
156 m_w
* q
.y() + m_y
* q
.m_w
+ m_z
* q
.x() - m_x
* q
.z(),
157 m_w
* q
.z() + m_z
* q
.m_w
+ m_x
* q
.y() - m_y
* q
.x(),
158 m_w
* q
.m_w
- m_x
* q
.x() - m_y
* q
.y() - m_z
* q
.z());
163 float dot(const Quaternion
& q
) const
165 return m_x
* q
.x() + m_y
* q
.y() + m_z
* q
.z() + m_w
* q
.m_w
;
169 float length2() const
177 return sqrt(length2());
181 Quaternion
& normalize()
183 return *this /= length();
188 operator*(const float& s
) const
190 return Quaternion(x() * s
, y() * s
, z() * s
, m_w
* s
);
194 Quaternion
operator/(const float& s
) const
197 return *this * (1.0f
/ s
);
201 Quaternion
& operator/=(const float& s
)
204 return *this *= 1.0f
/ s
;
208 Quaternion
normalized() const
210 return *this / length();
214 float angle(const Quaternion
& q
) const
216 float s
= sqrt(length2() * q
.length2());
218 return acos(dot(q
) / s
);
222 float getAngle() const
224 float s
= 2.0f
* acos(m_w
);
229 Quaternion
inverse() const
231 return Quaternion(m_x
, m_y
, m_z
, -m_w
);
236 operator+(const Quaternion
& q2
) const
238 const Quaternion
& q1
= *this;
239 return Quaternion(q1
.x() + q2
.x(), q1
.y() + q2
.y(), q1
.z() + q2
.z(),
245 operator-(const Quaternion
& q2
) const
247 const Quaternion
& q1
= *this;
248 return Quaternion(q1
.x() - q2
.x(), q1
.y() - q2
.y(), q1
.z() - q2
.z(),
253 inline Quaternion
operator-() const
255 const Quaternion
& q2
= *this;
256 return Quaternion( - q2
.x(), - q2
.y(), - q2
.z(), - q2
.m_w
);
260 inline Quaternion
farthest( const Quaternion
& qd
) const
262 Quaternion diff
, sum
;
265 if (diff
.dot(diff
) > sum
.dot(sum
))
271 Quaternion
slerp(const Quaternion
& q
, const float& t
) const
273 float theta
= angle(q
);
275 float d
= 1.0f
/ sin(theta
);
276 float s0
= sin((1.0f
- t
) * theta
);
277 float s1
= sin(t
* theta
);
278 return Quaternion((m_x
* s0
+ q
.x() * s1
) * d
,
279 (m_y
* s0
+ q
.y() * s1
) * d
,
280 (m_z
* s0
+ q
.z() * s1
) * d
,
281 (m_w
* s0
+ q
.m_w
* s1
) * d
);
288 void toOpenGLMatrix(float m
[4][4])
290 float wx
, wy
, wz
, xx
, yy
, yz
, xy
, xz
, zz
, x2
, y2
, z2
;
292 // calculate coefficients
293 x2
= m_x
+ m_x
; y2
= m_y
+ m_y
;
295 xx
= m_x
* x2
; xy
= m_x
* y2
; xz
= m_x
* z2
;
296 yy
= m_y
* y2
; yz
= m_y
* z2
; zz
= m_z
* z2
;
297 wx
= m_w
* x2
; wy
= m_w
* y2
; wz
= m_w
* z2
;
300 m
[0][0] = 1.0 - (yy
+ zz
); m
[1][0] = xy
- wz
;
301 m
[2][0] = xz
+ wy
; m
[3][0] = 0.0;
303 m
[0][1] = xy
+ wz
; m
[1][1] = 1.0 - (xx
+ zz
);
304 m
[2][1] = yz
- wx
; m
[3][1] = 0.0;
307 m
[0][2] = xz
- wy
; m
[1][2] = yz
+ wx
;
308 m
[2][2] = 1.0 - (xx
+ yy
); m
[3][2] = 0.0;
311 m
[0][3] = 0; m
[1][3] = 0;
312 m
[2][3] = 0; m
[3][3] = 1;
318 operator-(const Quaternion
& q
)
320 return Quaternion(-q
.x(), -q
.y(), -q
.z(), -q
.w());
325 operator*(const Quaternion
& q1
, const Quaternion
& q2
) {
327 q1
.w() * q2
.x() + q1
.x() * q2
.w() + q1
.y() * q2
.z() - q1
.z() * q2
.y(),
328 q1
.w() * q2
.y() + q1
.y() * q2
.w() + q1
.z() * q2
.x() - q1
.x() * q2
.z(),
329 q1
.w() * q2
.z() + q1
.z() * q2
.w() + q1
.x() * q2
.y() - q1
.y() * q2
.x(),
330 q1
.w() * q2
.w() - q1
.x() * q2
.x() - q1
.y() * q2
.y() - q1
.z() * q2
.z());
335 operator*(const Quaternion
& q
, const Vector3
& w
)
337 return Quaternion( q
.w() * w
.x() + q
.y() * w
.z() - q
.z() * w
.y(),
338 q
.w() * w
.y() + q
.z() * w
.x() - q
.x() * w
.z(),
339 q
.w() * w
.z() + q
.x() * w
.y() - q
.y() * w
.x(),
340 -q
.x() * w
.x() - q
.y() * w
.y() - q
.z() * w
.z());
345 operator*(const Vector3
& w
, const Quaternion
& q
)
347 return Quaternion( w
.x() * q
.w() + w
.y() * q
.z() - w
.z() * q
.y(),
348 w
.y() * q
.w() + w
.z() * q
.x() - w
.x() * q
.z(),
349 w
.z() * q
.w() + w
.x() * q
.y() - w
.y() * q
.x(),
350 -w
.x() * q
.x() - w
.y() * q
.y() - w
.z() * q
.z());
355 dot(const Quaternion
& q1
, const Quaternion
& q2
)
362 length(const Quaternion
& q
)
369 angle(const Quaternion
& q1
, const Quaternion
& q2
)
376 inverse(const Quaternion
& q
)
383 slerp(const Quaternion
& q1
, const Quaternion
& q2
, const float& t
)
385 return q1
.slerp(q2
, t
);
389 // Game Programming Gems 2.10. make sure v0,v1 are normalized
391 shortestArcQuat(const Vector3
& v0
, const Vector3
& v1
)
393 Vector3 c
= v0
.cross(v1
);
394 float d
= v0
.dot(v1
);
396 if (d
< -1.0 + FLT_EPSILON
)
397 return Quaternion(0.0f
, 1.0f
, 0.0f
, 0.0f
); // just pick any vector
399 float s
= sqrt((1.0f
+ d
) * 2.0f
);
402 return Quaternion(c
.x() * rs
, c
.y() * rs
, c
.z() * rs
, s
* 0.5f
);
407 shortestArcQuatNormalize2(Vector3
& v0
, Vector3
& v1
)
411 return shortestArcQuat(v0
, v1
);