3 Copyright (c) 2005 Gino van den Bergen / Erwin Coumans <www.erwincoumans.com>
5 Permission is hereby granted, free of charge, to any person or organization
6 obtaining a copy of the software and accompanying documentation covered by
7 this license (the "Software") to use, reproduce, display, distribute,
8 execute, and transmit the Software, and to prepare derivative works of the
9 Software, and to permit third-parties to whom the Software is furnished to
10 do so, all subject to the following:
12 The copyright notices in the Software and this entire statement, including
13 the above license grant, this restriction and the following disclaimer,
14 must be included in all copies of the Software, in whole or in part, and
15 all derivative works of the Software, unless such copies or derivative
16 works are solely in the form of machine-executable object code generated by
17 a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
29 #ifndef SIMD__QUATERNION_H_
30 #define SIMD__QUATERNION_H_
32 #include "SimdVector3.h"
34 class SimdQuaternion : public SimdQuadWord {
38 // template <typename SimdScalar>
39 // explicit Quaternion(const SimdScalar *v) : Tuple4<SimdScalar>(v) {}
41 SimdQuaternion(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z, const SimdScalar& w)
42 : SimdQuadWord(x, y, z, w)
45 SimdQuaternion(const SimdVector3& axis, const SimdScalar& angle)
47 setRotation(axis, angle);
50 SimdQuaternion(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
52 setEuler(yaw, pitch, roll);
55 void setRotation(const SimdVector3& axis, const SimdScalar& angle)
57 SimdScalar d = axis.length();
58 assert(d != SimdScalar(0.0));
59 SimdScalar s = sinf(angle * SimdScalar(0.5)) / d;
60 setValue(axis.x() * s, axis.y() * s, axis.z() * s,
61 cosf(angle * SimdScalar(0.5)));
64 void setEuler(const SimdScalar& yaw, const SimdScalar& pitch, const SimdScalar& roll)
66 SimdScalar halfYaw = SimdScalar(yaw) * SimdScalar(0.5);
67 SimdScalar halfPitch = SimdScalar(pitch) * SimdScalar(0.5);
68 SimdScalar halfRoll = SimdScalar(roll) * SimdScalar(0.5);
69 SimdScalar cosYaw = cosf(halfYaw);
70 SimdScalar sinYaw = sinf(halfYaw);
71 SimdScalar cosPitch = cosf(halfPitch);
72 SimdScalar sinPitch = sinf(halfPitch);
73 SimdScalar cosRoll = cosf(halfRoll);
74 SimdScalar sinRoll = sinf(halfRoll);
75 setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
76 cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
77 sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
78 cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
81 SimdQuaternion& operator+=(const SimdQuaternion& q)
83 m_x += q.x(); m_y += q.y(); m_z += q.z(); m_unusedW += q[3];
87 SimdQuaternion& operator-=(const SimdQuaternion& q)
89 m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_unusedW -= q[3];
93 SimdQuaternion& operator*=(const SimdScalar& s)
95 m_x *= s; m_y *= s; m_z *= s; m_unusedW *= s;
100 SimdQuaternion& operator*=(const SimdQuaternion& q)
102 setValue(m_unusedW * q.x() + m_x * q[3] + m_y * q.z() - m_z * q.y(),
103 m_unusedW * q.y() + m_y * q[3] + m_z * q.x() - m_x * q.z(),
104 m_unusedW * q.z() + m_z * q[3] + m_x * q.y() - m_y * q.x(),
105 m_unusedW * q[3] - m_x * q.x() - m_y * q.y() - m_z * q.z());
109 SimdScalar dot(const SimdQuaternion& q) const
111 return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_unusedW * q[3];
114 SimdScalar length2() const
119 SimdScalar length() const
121 return sqrtf(length2());
124 SimdQuaternion& normalize()
126 return *this /= length();
129 SIMD_FORCE_INLINE SimdQuaternion
130 operator*(const SimdScalar& s) const
132 return SimdQuaternion(x() * s, y() * s, z() * s, m_unusedW * s);
137 SimdQuaternion operator/(const SimdScalar& s) const
139 assert(s != SimdScalar(0.0));
140 return *this * (SimdScalar(1.0) / s);
144 SimdQuaternion& operator/=(const SimdScalar& s)
146 assert(s != SimdScalar(0.0));
147 return *this *= SimdScalar(1.0) / s;
151 SimdQuaternion normalized() const
153 return *this / length();
156 SimdScalar angle(const SimdQuaternion& q) const
158 SimdScalar s = sqrtf(length2() * q.length2());
159 assert(s != SimdScalar(0.0));
160 return acosf(dot(q) / s);
163 SimdScalar getAngle() const
165 SimdScalar s = 2.f * acosf(m_unusedW);
171 SimdQuaternion inverse() const
173 return SimdQuaternion(m_x, m_y, m_z, -m_unusedW);
176 SIMD_FORCE_INLINE SimdQuaternion
177 operator+(const SimdQuaternion& q2) const
179 const SimdQuaternion& q1 = *this;
180 return SimdQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1[3] + q2[3]);
183 SIMD_FORCE_INLINE SimdQuaternion
184 operator-(const SimdQuaternion& q2) const
186 const SimdQuaternion& q1 = *this;
187 return SimdQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1[3] - q2[3]);
190 SIMD_FORCE_INLINE SimdQuaternion operator-() const
192 const SimdQuaternion& q2 = *this;
193 return SimdQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2[3]);
196 SIMD_FORCE_INLINE SimdQuaternion farthest( const SimdQuaternion& qd) const
198 SimdQuaternion diff,sum;
201 if( diff.dot(diff) > sum.dot(sum) )
206 SimdQuaternion slerp(const SimdQuaternion& q, const SimdScalar& t) const
208 SimdScalar theta = angle(q);
209 if (theta != SimdScalar(0.0))
211 SimdScalar d = SimdScalar(1.0) / sinf(theta);
212 SimdScalar s0 = sinf((SimdScalar(1.0) - t) * theta);
213 SimdScalar s1 = sinf(t * theta);
214 return SimdQuaternion((m_x * s0 + q.x() * s1) * d,
215 (m_y * s0 + q.y() * s1) * d,
216 (m_z * s0 + q.z() * s1) * d,
217 (m_unusedW * s0 + q[3] * s1) * d);
231 SIMD_FORCE_INLINE SimdQuaternion
232 operator-(const SimdQuaternion& q)
234 return SimdQuaternion(-q.x(), -q.y(), -q.z(), -q[3]);
240 SIMD_FORCE_INLINE SimdQuaternion
241 operator*(const SimdQuaternion& q1, const SimdQuaternion& q2) {
242 return SimdQuaternion(q1[3] * q2.x() + q1.x() * q2[3] + q1.y() * q2.z() - q1.z() * q2.y(),
243 q1[3] * q2.y() + q1.y() * q2[3] + q1.z() * q2.x() - q1.x() * q2.z(),
244 q1[3] * q2.z() + q1.z() * q2[3] + q1.x() * q2.y() - q1.y() * q2.x(),
245 q1[3] * q2[3] - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
248 SIMD_FORCE_INLINE SimdQuaternion
249 operator*(const SimdQuaternion& q, const SimdVector3& w)
251 return SimdQuaternion( q[3] * w.x() + q.y() * w.z() - q.z() * w.y(),
252 q[3] * w.y() + q.z() * w.x() - q.x() * w.z(),
253 q[3] * w.z() + q.x() * w.y() - q.y() * w.x(),
254 -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
257 SIMD_FORCE_INLINE SimdQuaternion
258 operator*(const SimdVector3& w, const SimdQuaternion& q)
260 return SimdQuaternion( w.x() * q[3] + w.y() * q.z() - w.z() * q.y(),
261 w.y() * q[3] + w.z() * q.x() - w.x() * q.z(),
262 w.z() * q[3] + w.x() * q.y() - w.y() * q.x(),
263 -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
266 SIMD_FORCE_INLINE SimdScalar
267 dot(const SimdQuaternion& q1, const SimdQuaternion& q2)
273 SIMD_FORCE_INLINE SimdScalar
274 length(const SimdQuaternion& q)
279 SIMD_FORCE_INLINE SimdScalar
280 angle(const SimdQuaternion& q1, const SimdQuaternion& q2)
286 SIMD_FORCE_INLINE SimdQuaternion
287 inverse(const SimdQuaternion& q)
292 SIMD_FORCE_INLINE SimdQuaternion
293 slerp(const SimdQuaternion& q1, const SimdQuaternion& q2, const SimdScalar& t)
295 return q1.slerp(q2, t);