dungeon_crawler
diff prototype/vmath/quat.cc @ 1:96de911d05d4
started a rough prototype
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 28 Jun 2012 06:05:50 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/prototype/vmath/quat.cc Thu Jun 28 06:05:50 2012 +0300 1.3 @@ -0,0 +1,159 @@ 1.4 +#include "quat.h" 1.5 + 1.6 +Quaternion::Quaternion() { 1.7 + s = 1.0; 1.8 + v.x = v.y = v.z = 0.0; 1.9 +} 1.10 + 1.11 +Quaternion::Quaternion(scalar_t s, const Vector3 &v) { 1.12 + this->s = s; 1.13 + this->v = v; 1.14 +} 1.15 + 1.16 +Quaternion::Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z) { 1.17 + v.x = x; 1.18 + v.y = y; 1.19 + v.z = z; 1.20 + this->s = s; 1.21 +} 1.22 + 1.23 +Quaternion::Quaternion(const Vector3 &axis, scalar_t angle) { 1.24 + set_rotation(axis, angle); 1.25 +} 1.26 + 1.27 +Quaternion::Quaternion(const quat_t &quat) 1.28 +{ 1.29 + v.x = quat.x; 1.30 + v.y = quat.y; 1.31 + v.z = quat.z; 1.32 + s = quat.w; 1.33 +} 1.34 + 1.35 +Quaternion Quaternion::operator +(const Quaternion &quat) const { 1.36 + return Quaternion(s + quat.s, v + quat.v); 1.37 +} 1.38 + 1.39 +Quaternion Quaternion::operator -(const Quaternion &quat) const { 1.40 + return Quaternion(s - quat.s, v - quat.v); 1.41 +} 1.42 + 1.43 +Quaternion Quaternion::operator -() const { 1.44 + return Quaternion(-s, -v); 1.45 +} 1.46 + 1.47 +/** Quaternion Multiplication: 1.48 + * Q1*Q2 = [s1*s2 - v1.v2, s1*v2 + s2*v1 + v1(x)v2] 1.49 + */ 1.50 +Quaternion Quaternion::operator *(const Quaternion &quat) const { 1.51 + Quaternion newq; 1.52 + newq.s = s * quat.s - dot_product(v, quat.v); 1.53 + newq.v = quat.v * s + v * quat.s + cross_product(v, quat.v); 1.54 + return newq; 1.55 +} 1.56 + 1.57 +void Quaternion::operator +=(const Quaternion &quat) { 1.58 + *this = Quaternion(s + quat.s, v + quat.v); 1.59 +} 1.60 + 1.61 +void Quaternion::operator -=(const Quaternion &quat) { 1.62 + *this = Quaternion(s - quat.s, v - quat.v); 1.63 +} 1.64 + 1.65 +void Quaternion::operator *=(const Quaternion &quat) { 1.66 + *this = *this * quat; 1.67 +} 1.68 + 1.69 +void Quaternion::reset_identity() { 1.70 + s = 1.0; 1.71 + v.x = v.y = v.z = 0.0; 1.72 +} 1.73 + 1.74 +Quaternion Quaternion::conjugate() const { 1.75 + return Quaternion(s, -v); 1.76 +} 1.77 + 1.78 +scalar_t Quaternion::length() const { 1.79 + return (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); 1.80 +} 1.81 + 1.82 +/** Q * ~Q = ||Q||^2 */ 1.83 +scalar_t Quaternion::length_sq() const { 1.84 + return v.x*v.x + v.y*v.y + v.z*v.z + s*s; 1.85 +} 1.86 + 1.87 +void Quaternion::normalize() { 1.88 + scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); 1.89 + v.x /= len; 1.90 + v.y /= len; 1.91 + v.z /= len; 1.92 + s /= len; 1.93 +} 1.94 + 1.95 +Quaternion Quaternion::normalized() const { 1.96 + Quaternion nq = *this; 1.97 + scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); 1.98 + nq.v.x /= len; 1.99 + nq.v.y /= len; 1.100 + nq.v.z /= len; 1.101 + nq.s /= len; 1.102 + return nq; 1.103 +} 1.104 + 1.105 +/** Quaternion Inversion: Q^-1 = ~Q / ||Q||^2 */ 1.106 +Quaternion Quaternion::inverse() const { 1.107 + Quaternion inv = conjugate(); 1.108 + scalar_t lensq = length_sq(); 1.109 + inv.v /= lensq; 1.110 + inv.s /= lensq; 1.111 + 1.112 + return inv; 1.113 +} 1.114 + 1.115 + 1.116 +void Quaternion::set_rotation(const Vector3 &axis, scalar_t angle) { 1.117 + scalar_t half_angle = angle / 2.0; 1.118 + s = cos(half_angle); 1.119 + v = axis * sin(half_angle); 1.120 +} 1.121 + 1.122 +void Quaternion::rotate(const Vector3 &axis, scalar_t angle) { 1.123 + Quaternion q; 1.124 + scalar_t half_angle = angle / 2.0; 1.125 + q.s = cos(half_angle); 1.126 + q.v = axis * sin(half_angle); 1.127 + 1.128 + *this *= q; 1.129 +} 1.130 + 1.131 +void Quaternion::rotate(const Quaternion &q) { 1.132 + *this = q * *this * q.conjugate(); 1.133 +} 1.134 + 1.135 +Matrix3x3 Quaternion::get_rotation_matrix() const { 1.136 + return Matrix3x3( 1.0 - 2.0 * v.y*v.y - 2.0 * v.z*v.z, 2.0 * v.x * v.y + 2.0 * s * v.z, 2.0 * v.z * v.x - 2.0 * s * v.y, 1.137 + 2.0 * v.x * v.y - 2.0 * s * v.z, 1.0 - 2.0 * v.x*v.x - 2.0 * v.z*v.z, 2.0 * v.y * v.z + 2.0 * s * v.x, 1.138 + 2.0 * v.z * v.x + 2.0 * s * v.y, 2.0 * v.y * v.z - 2.0 * s * v.x, 1.0 - 2.0 * v.x*v.x - 2.0 * v.y*v.y); 1.139 +} 1.140 + 1.141 + 1.142 +/** Spherical linear interpolation (slerp) */ 1.143 +Quaternion slerp(const Quaternion &q1, const Quaternion &q2, scalar_t t) { 1.144 + scalar_t angle = acos(q1.s * q2.s + q1.v.x * q2.v.x + q1.v.y * q2.v.y + q1.v.z * q2.v.z); 1.145 + scalar_t a = sin((1.0f - t) * angle); 1.146 + scalar_t b = sin(t * angle); 1.147 + scalar_t c = sin(angle); 1.148 + 1.149 + scalar_t x = (q1.v.x * a + q2.v.x * b) / c; 1.150 + scalar_t y = (q1.v.y * a + q2.v.y * b) / c; 1.151 + scalar_t z = (q1.v.z * a + q2.v.z * b) / c; 1.152 + scalar_t s = (q1.s * a + q2.s * b) / c; 1.153 + 1.154 + return Quaternion(s, Vector3(x, y, z)).normalized(); 1.155 +} 1.156 + 1.157 + 1.158 + 1.159 +std::ostream &operator <<(std::ostream &out, const Quaternion &q) { 1.160 + out << "(" << q.s << ", " << q.v << ")"; 1.161 + return out; 1.162 +}