00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef CAL_QUATERNION_H
00012 #define CAL_QUATERNION_H
00013
00014
00015
00016
00017
00018 #include "cal3d/global.h"
00019 #include "cal3d/vector.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00035 class CAL3D_API CalQuaternion
00036 {
00037
00038 public:
00039 float x;
00040 float y;
00041 float z;
00042 float w;
00043
00044
00045 public:
00046 inline CalQuaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f){};
00047 inline CalQuaternion(const CalQuaternion& q): x(q.x), y(q.y), z(q.z), w(q.w) {};
00048 inline CalQuaternion(float qx, float qy, float qz, float qw): x(qx), y(qy), z(qz), w(qw) {};
00049 inline ~CalQuaternion() {};
00050
00051
00052 public:
00053 inline float& operator[](unsigned int index)
00054 {
00055 return (&x)[index];
00056 }
00057
00058 inline const float& operator[](unsigned int index) const
00059 {
00060 return (&x)[index];
00061 }
00062
00063 inline void operator=(const CalQuaternion& q)
00064 {
00065 x = q.x;
00066 y = q.y;
00067 z = q.z;
00068 w = q.w;
00069 }
00070
00071 inline void operator*=(const CalQuaternion& q)
00072 {
00073 float qx, qy, qz, qw;
00074 qx = x;
00075 qy = y;
00076 qz = z;
00077 qw = w;
00078
00079 x = qw * q.x + qx * q.w + qy * q.z - qz * q.y;
00080 y = qw * q.y - qx * q.z + qy * q.w + qz * q.x;
00081 z = qw * q.z + qx * q.y - qy * q.x + qz * q.w;
00082 w = qw * q.w - qx * q.x - qy * q.y - qz * q.z;
00083 }
00084
00085 inline void operator*=(const CalVector& v)
00086 {
00087 float qx, qy, qz, qw;
00088 qx = x;
00089 qy = y;
00090 qz = z;
00091 qw = w;
00092
00093 x = qw * v.x + qy * v.z - qz * v.y;
00094 y = qw * v.y - qx * v.z + qz * v.x;
00095 z = qw * v.z + qx * v.y - qy * v.x;
00096 w = - qx * v.x - qy * v.y - qz * v.z;
00097 }
00098
00099 inline bool operator==(const CalQuaternion& rhs) const
00100 {
00101 return x == rhs.x &&
00102 y == rhs.y &&
00103 z == rhs.z &&
00104 w == rhs.w;
00105 }
00106
00107 inline bool operator!=(const CalQuaternion& rhs) const
00108 {
00109 return !operator==(rhs);
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 inline void blend(float d, const CalQuaternion& q)
00123 {
00124 float norm;
00125 norm = x * q.x + y * q.y + z * q.z + w * q.w;
00126
00127 bool bFlip;
00128 bFlip = false;
00129
00130 if(norm < 0.0f)
00131 {
00132 norm = -norm;
00133 bFlip = true;
00134 }
00135
00136 float inv_d;
00137 if(1.0f - norm < 0.000001f)
00138 {
00139 inv_d = 1.0f - d;
00140 }
00141 else
00142 {
00143 float theta;
00144 theta = (float) acos(norm);
00145
00146 float s;
00147 s = (float) (1.0f / sin(theta));
00148
00149 inv_d = (float) sin((1.0f - d) * theta) * s;
00150 d = (float) sin(d * theta) * s;
00151 }
00152
00153 if(bFlip)
00154 {
00155 d = -d;
00156 }
00157
00158 x = inv_d * x + d * q.x;
00159 y = inv_d * y + d * q.y;
00160 z = inv_d * z + d * q.z;
00161 w = inv_d * w + d * q.w;
00162 }
00163
00164 inline void clear()
00165 {
00166 x = 0.0f;
00167 y = 0.0f;
00168 z = 0.0f;
00169 w = 1.0f;
00170 }
00171 inline void conjugate()
00172 {
00173 x = -x;
00174 y = -y;
00175 z = -z;
00176 }
00177
00178 inline void invert()
00179 {
00180 conjugate();
00181 const float norm = (x*x) + (y*y) + (z*z) + (w*w);
00182
00183 if (norm == 0.0f) return;
00184
00185 const float inv_norm = 1 / norm;
00186 x *= inv_norm;
00187 y *= inv_norm;
00188 z *= inv_norm;
00189 w *= inv_norm;
00190 }
00191
00192 inline void set(float qx, float qy, float qz, float qw)
00193 {
00194 x = qx;
00195 y = qy;
00196 z = qz;
00197 w = qw;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 };
00217
00218
00219 static inline CalQuaternion operator*(const CalQuaternion& q, const CalQuaternion& r)
00220 {
00221 return CalQuaternion(
00222 r.w * q.x + r.x * q.w + r.y * q.z - r.z * q.y,
00223 r.w * q.y - r.x * q.z + r.y * q.w + r.z * q.x,
00224 r.w * q.z + r.x * q.y - r.y * q.x + r.z * q.w,
00225 r.w * q.w - r.x * q.x - r.y * q.y - r.z * q.z
00226 );
00227 }
00228
00229 static inline CalQuaternion shortestArc( const CalVector& from, const CalVector& to )
00230 {
00231 CalVector cross = from % to;
00232 float dot = from * to ;
00233
00234 dot = (float) sqrt( 2*(dot+1) ) ;
00235
00236 cross /= dot ;
00237
00238
00239
00240 return CalQuaternion( cross[0], cross[1], cross[2], -dot/2 ) ;
00241
00242 }
00243
00244
00245 #endif
00246
00247