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 bullet-2.66 src\LinearMath\btQuaternion.h
13 * The dependancies on base class btQuadWord have been removed for simplification.
14 * Added gl matrix conversion method.
19 Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
21 This software is provided 'as-is', without any express or implied warranty.
22 In no event will the authors be held liable for any damages arising from the use of this software.
23 Permission is granted to anyone to use this software for any purpose,
24 including commercial applications, and to alter it and redistribute it freely,
25 subject to the following restrictions:
27 1. 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.
28 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
29 3. This notice may not be removed or altered from any source distribution.
33 #ifndef __QUATERNION_H__
34 #define __QUATERNION_H__
47 Quaternion(const Quaternion
& q
)
49 *((Quaternion
*)this) = q
;
52 Quaternion(const float& x
, const float& y
, const float& z
,const float& w
)
54 m_x
= x
, m_y
= y
, m_z
= z
, m_w
= w
;
57 Quaternion(const Vector3
& axis
, const float& angle
)
59 setRotation(axis
, angle
);
62 Quaternion(const float& yaw
, const float& pitch
, const float& roll
)
64 setEuler(yaw
, pitch
, roll
);
67 inline const float& x() const { return m_x
; }
70 inline const float& y() const { return m_y
; }
73 inline const float& z() const { return m_z
; }
76 inline const float& w() const { return m_w
; }
79 void setValue(const float& x
, const float& y
, const float& z
)
88 void setValue(const float& x
, const float& y
, const float& z
,const float& w
)
97 void setRotation(const Vector3
& axis
, const float& angle
)
99 float d
= axis
.length();
101 float s
= sin(angle
* 0.5f
) / d
;
102 setValue(axis
.x() * s
, axis
.y() * s
, axis
.z() * s
,
107 void setEuler(const float& yaw
, const float& pitch
, const float& roll
)
109 float halfYaw
= yaw
* 0.5f
;
110 float halfPitch
= pitch
* 0.5f
;
111 float halfRoll
= roll
* 0.5f
;
112 float cosYaw
= cos(halfYaw
);
113 float sinYaw
= sin(halfYaw
);
114 float cosPitch
= cos(halfPitch
);
115 float sinPitch
= sin(halfPitch
);
116 float cosRoll
= cos(halfRoll
);
117 float sinRoll
= sin(halfRoll
);
118 setValue(cosRoll
* sinPitch
* cosYaw
+ sinRoll
* cosPitch
* sinYaw
,
119 cosRoll
* cosPitch
* sinYaw
- sinRoll
* sinPitch
* cosYaw
,
120 sinRoll
* cosPitch
* cosYaw
- cosRoll
* sinPitch
* sinYaw
,
121 cosRoll
* cosPitch
* cosYaw
+ sinRoll
* sinPitch
* sinYaw
);
125 Quaternion
& operator+=(const Quaternion
& q
)
127 m_x
+= q
.x(); m_y
+= q
.y(); m_z
+= q
.z(); m_w
+= q
.m_w
;
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 float& s
)
141 m_x
*= s
; m_y
*= s
; m_z
*= s
; m_w
*= s
;
146 Quaternion
& operator*=(const Quaternion
& q
)
148 setValue(m_w
* q
.x() + m_x
* q
.m_w
+ m_y
* q
.z() - m_z
* q
.y(),
149 m_w
* q
.y() + m_y
* q
.m_w
+ m_z
* q
.x() - m_x
* q
.z(),
150 m_w
* q
.z() + m_z
* q
.m_w
+ m_x
* q
.y() - m_y
* q
.x(),
151 m_w
* q
.m_w
- m_x
* q
.x() - m_y
* q
.y() - m_z
* q
.z());
156 float dot(const Quaternion
& q
) const
158 return m_x
* q
.x() + m_y
* q
.y() + m_z
* q
.z() + m_w
* q
.m_w
;
162 float length2() const
170 return sqrt(length2());
174 Quaternion
& normalize()
176 return *this /= length();
181 operator*(const float& s
) const
183 return Quaternion(x() * s
, y() * s
, z() * s
, m_w
* s
);
187 Quaternion
operator/(const float& s
) const
190 return *this * (1.0f
/ s
);
194 Quaternion
& operator/=(const float& s
)
197 return *this *= 1.0f
/ s
;
201 Quaternion
normalized() const
203 return *this / length();
207 float angle(const Quaternion
& q
) const
209 float s
= sqrt(length2() * q
.length2());
211 return acos(dot(q
) / s
);
215 float getAngle() const
217 float s
= 2.0f
* acos(m_w
);
222 Quaternion
inverse() const
224 return Quaternion(m_x
, m_y
, m_z
, -m_w
);
229 operator+(const Quaternion
& q2
) const
231 const Quaternion
& q1
= *this;
232 return Quaternion(q1
.x() + q2
.x(), q1
.y() + q2
.y(), q1
.z() + q2
.z(), q1
.m_w
+ q2
.m_w
);
237 operator-(const Quaternion
& q2
) const
239 const Quaternion
& q1
= *this;
240 return Quaternion(q1
.x() - q2
.x(), q1
.y() - q2
.y(), q1
.z() - q2
.z(), q1
.m_w
- q2
.m_w
);
244 inline Quaternion
operator-() const
246 const Quaternion
& q2
= *this;
247 return Quaternion( - q2
.x(), - q2
.y(), - q2
.z(), - q2
.m_w
);
251 inline Quaternion
farthest( const Quaternion
& qd
) const
256 if( diff
.dot(diff
) > sum
.dot(sum
) )
262 Quaternion
slerp(const Quaternion
& q
, const float& t
) const
264 float theta
= angle(q
);
267 float d
= 1.0f
/ sin(theta
);
268 float s0
= sin((1.0f
- t
) * theta
);
269 float s1
= sin(t
* theta
);
270 return Quaternion((m_x
* s0
+ q
.x() * s1
) * d
,
271 (m_y
* s0
+ q
.y() * s1
) * d
,
272 (m_z
* s0
+ q
.z() * s1
) * d
,
273 (m_w
* s0
+ q
.m_w
* s1
) * d
);
282 void toOpenGLMatrix(float m
[4][4]){
284 float wx
, wy
, wz
, xx
, yy
, yz
, xy
, xz
, zz
, x2
, y2
, z2
;
286 // calculate coefficients
287 x2
= m_x
+ m_x
; y2
= m_y
+ m_y
;
289 xx
= m_x
* x2
; xy
= m_x
* y2
; xz
= m_x
* z2
;
290 yy
= m_y
* y2
; yz
= m_y
* z2
; zz
= m_z
* z2
;
291 wx
= m_w
* x2
; wy
= m_w
* y2
; wz
= m_w
* z2
;
294 m
[0][0] = 1.0 - (yy
+ zz
); m
[1][0] = xy
- wz
;
295 m
[2][0] = xz
+ wy
; m
[3][0] = 0.0;
297 m
[0][1] = xy
+ wz
; m
[1][1] = 1.0 - (xx
+ zz
);
298 m
[2][1] = yz
- wx
; m
[3][1] = 0.0;
301 m
[0][2] = xz
- wy
; m
[1][2] = yz
+ wx
;
302 m
[2][2] = 1.0 - (xx
+ yy
); m
[3][2] = 0.0;
305 m
[0][3] = 0; m
[1][3] = 0;
306 m
[2][3] = 0; m
[3][3] = 1;
312 operator-(const Quaternion
& q
)
314 return Quaternion(-q
.x(), -q
.y(), -q
.z(), -q
.w());
319 operator*(const Quaternion
& q1
, const Quaternion
& q2
) {
320 return Quaternion(q1
.w() * q2
.x() + q1
.x() * q2
.w() + q1
.y() * q2
.z() - q1
.z() * q2
.y(),
321 q1
.w() * q2
.y() + q1
.y() * q2
.w() + q1
.z() * q2
.x() - q1
.x() * q2
.z(),
322 q1
.w() * q2
.z() + q1
.z() * q2
.w() + q1
.x() * q2
.y() - q1
.y() * q2
.x(),
323 q1
.w() * q2
.w() - q1
.x() * q2
.x() - q1
.y() * q2
.y() - q1
.z() * q2
.z());
328 operator*(const Quaternion
& q
, const Vector3
& w
)
330 return Quaternion( q
.w() * w
.x() + q
.y() * w
.z() - q
.z() * w
.y(),
331 q
.w() * w
.y() + q
.z() * w
.x() - q
.x() * w
.z(),
332 q
.w() * w
.z() + q
.x() * w
.y() - q
.y() * w
.x(),
333 -q
.x() * w
.x() - q
.y() * w
.y() - q
.z() * w
.z());
338 operator*(const Vector3
& w
, const Quaternion
& q
)
340 return Quaternion( w
.x() * q
.w() + w
.y() * q
.z() - w
.z() * q
.y(),
341 w
.y() * q
.w() + w
.z() * q
.x() - w
.x() * q
.z(),
342 w
.z() * q
.w() + w
.x() * q
.y() - w
.y() * q
.x(),
343 -w
.x() * q
.x() - w
.y() * q
.y() - w
.z() * q
.z());
348 dot(const Quaternion
& q1
, const Quaternion
& q2
)
355 length(const Quaternion
& q
)
362 angle(const Quaternion
& q1
, const Quaternion
& q2
)
369 inverse(const Quaternion
& q
)
376 slerp(const Quaternion
& q1
, const Quaternion
& q2
, const float& t
)
378 return q1
.slerp(q2
, t
);
383 shortestArcQuat(const Vector3
& v0
, const Vector3
& v1
) // Game Programming Gems 2.10. make sure v0,v1 are normalized
385 Vector3 c
= v0
.cross(v1
);
386 float d
= v0
.dot(v1
);
388 if (d
< -1.0 + FLT_EPSILON
)
389 return Quaternion(0.0f
,1.0f
,0.0f
,0.0f
); // just pick any vector
391 float s
= sqrt((1.0f
+ d
) * 2.0f
);
394 return Quaternion(c
.x()*rs
, c
.y()*rs
, c
.z()*rs
, s
* 0.5f
);
399 shortestArcQuatNormalize2(Vector3
& v0
,Vector3
& v1
)
403 return shortestArcQuat(v0
,v1
);