18 void Set(T x, T y, T z, T w);
34 Matrix3 <T> ToMatrix3()
const;
36 Matrix4 <T> ToMatrix4()
const;
68 inline QuaternionT<T>::QuaternionT(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {
72 void QuaternionT<T>::Set(T x, T y, T z, T w) {
80 QuaternionT<T> QuaternionT<T>::Clone()
const {
81 return QuaternionT<T>(x, y, z, w);
85 inline QuaternionT<T> QuaternionT<T>::Lerp(
float t,
const QuaternionT<T>& q)
const {
87 QuaternionT<T> result = QuaternionT<T>(0, 0, 0, 1);
88 float dot = w * q.w + x * q.x + y * q.y + z * q.z;
89 float deltaTime = 1.f - t;
91 result.w = deltaTime * w + t * -q.w;
92 result.x = deltaTime * x + t * -q.x;
93 result.y = deltaTime * y + t * -q.y;
94 result.z = deltaTime * z + t * -q.z;
96 result.w = deltaTime * w + t * q.w;
97 result.x = deltaTime * x + t * q.x;
98 result.y = deltaTime * y + t * q.y;
99 result.z = deltaTime * z + t * q.z;
106 template <
typename T>
107 inline QuaternionT<T> QuaternionT<T>::Slerp(
float t,
const QuaternionT<T>& q)
const {
110 const float rawCosom = x * q.x + y * q.y + z * q.z + w * q.w;
112 const auto cosom = ValueSelect<float>(rawCosom, rawCosom, -rawCosom);
114 float scale0, scale1;
116 if (cosom < 0.9999f) {
117 const float omega = acosf(cosom);
118 const float invSin = 1.f / sinf(omega);
119 scale0 = sinf((1.f - t) * omega) * invSin;
120 scale1 = sinf(t * omega) * invSin;
129 scale1 = ValueSelect<float>(rawCosom, scale1, -scale1);
131 QuaternionT<T> result;
133 result.x = scale0 * x + scale1 * q.x;
134 result.y = scale0 * y + scale1 * q.y;
135 result.z = scale0 * z + scale1 * q.z;
136 result.w = scale0 * w + scale1 * q.w;
141 template <
typename T>
142 inline QuaternionT<T> QuaternionT<T>::Rotated(
const QuaternionT<T>& b)
const {
144 q.w = w * b.w - x * b.x - y * b.y - z * b.z;
145 q.x = w * b.x + x * b.w + y * b.z - z * b.y;
146 q.y = w * b.y + y * b.w + z * b.x - x * b.z;
147 q.z = w * b.z + z * b.w + x * b.y - y * b.x;
152 template <
typename T>
153 inline QuaternionT<T> QuaternionT<T>::Multiplied(
const QuaternionT<T>& q2)
const {
155 T A, B, C, D, E, F, G, H;
157 A = (w + x) * (q2.w + q2.x);
159 B = (z - y) * (q2.y - q2.z);
161 C = (w - x) * (q2.y + q2.z);
163 D = (y + z) * (q2.w - q2.x);
165 E = (x + z) * (q2.x + q2.y);
167 F = (x - z) * (q2.x - q2.y);
169 G = (w + y) * (q2.w - q2.z);
171 H = (w - y) * (q2.w + q2.z);
174 res.w = B + (-E - F + G + H) / 2;
176 res.x = A - (E + F + G + H) / 2;
178 res.y = C + (E - F + G - H) / 2;
180 res.z = D + (E - F - G + H) / 2;
186 template <
typename T>
187 inline QuaternionT<T> QuaternionT<T>::Scaled(T s)
const {
188 return QuaternionT<T>(x * s, y * s, z * s, w * s);
191 template <
typename T>
192 inline T QuaternionT<T>::Dot(
const QuaternionT<T>& q)
const {
193 return x * q.x + y * q.y + z * q.z + w * q.w;
196 template <
typename T>
197 inline Matrix3 <T> QuaternionT<T>::ToMatrix3()
const {
198 QuaternionT<T> q = *
this;
201 float result[9] = { 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z, 2.0f * q.x * q.y - 2.0f * q.z * q.w,
202 2.0f * q.x * q.z + 2.0f * q.y * q.w,
203 2.0f * q.x * q.y + 2.0f * q.z * q.w, 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z,
204 2.0f * q.y * q.z - 2.0f * q.x * q.w,
205 2.0f * q.x * q.z - 2.0f * q.y * q.w, 2.0f * q.y * q.z + 2.0f * q.x * q.w,
206 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y };
207 return Matrix3<T>(result);
224 template <
typename T>
225 inline Matrix4 <T> QuaternionT<T>::ToMatrix4()
const {
226 Matrix4<T> matrix = Matrix4<T>::Identity();
236 matrix.x.x = 1 - 2 * (ySquared + zSquared);
237 matrix.x.y = 2 * (xy - zw);
238 matrix.x.z = 2 * (xz + yw);
240 matrix.y.x = 2 * (xy + zw);
241 matrix.y.y = 1 - 2 * (xSquared + zSquared);
242 matrix.y.z = 2 * (yz - xw);
244 matrix.z.x = 2 * (xz - yw);
245 matrix.z.y = 2 * (yz + xw);
246 matrix.z.z = 1 - 2 * (xSquared + ySquared);
255 template <
typename T>
256 inline Vector4<T> QuaternionT<T>::ToVector()
const {
257 return Vector4<T>(x, y, z, w);
260 template <
typename T>
261 inline Vector3<T> QuaternionT<T>::ToEulerAngle()
const {
292 T unit = sqx + sqy + sqz + sqw;
293 T test = x * y + z * w;
294 if (test > 0.499 * unit) {
295 heading = 2 * atan2(x, w);
298 return Vector3<T>(bank, heading, attitude);
300 if (test < -0.499 * unit) {
301 heading = -2 * atan2(x, w);
302 attitude = -M_PI / 2;
304 return Vector3<T>(bank, heading, attitude);
307 heading = atan2(2 * y * w - 2 * x * z, sqx - sqy - sqz + sqw);
308 attitude = asin(2 * test / unit);
309 bank = atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw);
311 return Vector3<T>(bank, heading, attitude);
314 template <
typename T>
315 QuaternionT<T> QuaternionT<T>::operator-(
const QuaternionT<T>& q)
const {
316 return QuaternionT<T>(x - q.x, y - q.y, z - q.z, w - q.w);
319 template <
typename T>
320 QuaternionT<T> QuaternionT<T>::operator+(
const QuaternionT<T>& q)
const {
321 return QuaternionT<T>(x + q.x, y + q.y, z + q.z, w + q.w);
324 template <
typename T>
325 bool QuaternionT<T>::operator==(
const QuaternionT<T>& q)
const {
326 return x == q.x && y == q.y && z == q.z && w == q.w;
329 template <
typename T>
330 bool QuaternionT<T>::operator!=(
const QuaternionT<T>& q)
const {
336 template <
typename T>
337 inline QuaternionT<T> QuaternionT<T>::CreateFromVectors(
const Vector3<T>& v0,
const Vector3<T>& v1) {
339 return QuaternionT<T>::AngleAxis(vec3(1, 0, 0), Pi);
341 Vector3<T> c = v0.Cross(v1);
343 T s = std::sqrt((1 + d) * 2);
353 template <
typename T>
354 inline QuaternionT<T> QuaternionT<T>::AngleAxis(
const Vector3<T>& axis,
float radians) {
356 q.w = std::cos(radians / 2);
357 q.x = q.y = q.z = std::sin(radians / 2);
378 template <
typename T>
379 inline void QuaternionT<T>::Normalize() {
380 *
this = Scaled(1 / std::sqrt(Dot(*
this)));
383 template <
typename T>
384 inline void QuaternionT<T>::Rotate(
const QuaternionT<T>& q2) {
386 QuaternionT<T>& q1 = *
this;
388 q.w = w * q2.w - x * q2.x - y * q2.y - z * q2.z;
389 q.x = w * q2.x + x * q2.w + y * q2.z - z * q2.y;
390 q.y = w * q2.y + y * q2.w + z * q2.x - x * q2.z;
391 q.z = w * q2.z + z * q2.w + x * q2.y - y * q2.x;
397 template <
typename T>
398 inline void QuaternionT<T>::Conjugate() {
400 QuaternionT<T>& q1 = *
this;
410 template <
typename T>
411 QuaternionT<T> QuaternionT<T>::ToQuaternion(
const Matrix4 <T>& matrix) {
413 q.w = sqrt(fmax(0, 1 + matrix.x.x + matrix.y.y + matrix.z.z)) / 2;
414 q.x = sqrt(fmax(0, 1 + matrix.x.x - matrix.y.y - matrix.z.z)) / 2;
415 q.y = sqrt(fmax(0, 1 - matrix.x.x + matrix.y.y - matrix.z.z)) / 2;
416 q.z = sqrt(fmax(0, 1 - matrix.x.x - matrix.y.y + matrix.z.z)) / 2;
417 q.x *= sign<T>(q.x * (matrix.z.y - matrix.y.z));
418 q.y *= sign<T>(q.y * (matrix.x.z - matrix.z.x));
419 q.z *= sign<T>(q.z * (matrix.y.x - matrix.x.y));
423 typedef QuaternionT<float> Quaternion;