00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef quat_h
00022 #define quat_h
00023
00024 #include <../mathGutz/vec4.h>
00025
00026 namespace gutz {
00027
00028 template <class T> class vec3;
00029 template <class T> class mat3;
00030
00031 template <class T>
00032 class quat
00033 : public vec4<T>
00034 {
00035 public:
00036 inline quat ();
00037 inline quat (const T, const T, const T, const T);
00038 inline quat (const vec4<T>&);
00039 inline quat (const quat<T>&);
00040 inline quat (const vec3<T>&);
00041 inline quat (const T, const vec3<T>&);
00042 inline quat (const mat3<T>&);
00043 inline ~quat () {}
00044
00045 inline quat mult (const quat&) const;
00046 inline quat conj () const;
00047 inline quat inv () const;
00048
00049 inline vec3<T> rot (const vec3<T>&) const;
00050 inline quat rot (const quat&) const;
00051
00052 inline void set (const T phi, const vec3<T>& k);
00053 inline void set (const mat3<T>& M);
00054 };
00055
00056
00057
00058
00059
00060 typedef quat<float> quatf;
00061 typedef quat<double> quatd;
00062
00063
00064
00065
00066
00067 template <class T>
00068 quat<T>::quat ()
00069 : vec4<T>(0, 0, 0, 1)
00070 {}
00071
00072 template <class T>
00073 quat<T>::quat (T x0, T y0, T z0, T w0)
00074 : vec4<T>(x0, y0, z0, w0)
00075 {}
00076
00077 template <class T>
00078 quat<T>::quat (const vec4<T>& v)
00079 : vec4<T>(v)
00080 {}
00081
00082 template <class T>
00083 quat<T>::quat (const quat<T>& v)
00084 : vec4<T>((vec4<T>)v)
00085 {}
00086
00087 template <class T>
00088 quat<T>::quat (const vec3<T>& v)
00089 : vec4<T>(v.x, v.y, v.z, 0)
00090 {}
00091
00092 template <class T>
00093 quat<T>::quat (const T phi, const vec3<T>& k)
00094 {
00095 set(phi, k);
00096 }
00097
00098 template <class T>
00099 quat<T>::quat (const mat3<T>& M)
00100 {
00101 set(M);
00102 }
00103
00104 template <class T>
00105 quat<T>
00106 quat<T>::mult (const quat<T>& q) const
00107 {
00108 return quat( w*q.x + q.w*x + y*q.z - q.y*z,
00109 w*q.y + q.w*y + z*q.x - q.z*x,
00110 w*q.z + q.w*z + x*q.y - q.x*y,
00111 w*q.w - x*q.x - y*q.y - z*q.z);
00112 }
00113
00114 template <class T>
00115 quat<T>
00116 quat<T>::conj () const
00117 {
00118 return quat(-x, -y, -z, w);
00119 }
00120
00121 template <class T>
00122 quat<T>
00123 quat<T>::inv () const
00124 {
00125 T n = 1/(w*w + x*x + y*y + z*z);
00126 return quat(-x*n, -y*n, -z*n, w*n);
00127 }
00128
00129 template <class T>
00130 vec3<T>
00131 quat<T>::rot (const vec3<T>& v) const
00132 {
00133
00134 quat tmp(w*v.x + y*v.z - v.y*z,
00135 w*v.y + z*v.x - v.z*x,
00136 w*v.z + x*v.y - v.x*y,
00137 - x*v.x - y*v.y - z*v.z);
00138
00139 return vec3<T>(- tmp.w*x + w*tmp.x - tmp.y*z + y*tmp.z,
00140 - tmp.w*y + w*tmp.y - tmp.z*x + z*tmp.x,
00141 - tmp.w*z + w*tmp.z - tmp.x*y + x*tmp.y);
00142 }
00143
00144 template <class T>
00145 quat<T>
00146 quat<T>::rot (const quat& r) const
00147 {
00148
00149 quat tmp(w*r.x + r.w*x + y*r.z - r.y*z,
00150 w*r.y + r.w*y + z*r.x - r.z*x,
00151 w*r.z + r.w*z + x*r.y - r.x*y,
00152 w*r.w - x*r.x - y*r.y - z*r.z);
00153
00154 return quat(- tmp.w*x + w*tmp.x - tmp.y*z + y*tmp.z,
00155 - tmp.w*y + w*tmp.y - tmp.z*x + z*tmp.x,
00156 - tmp.w*z + w*tmp.z - tmp.x*y + x*tmp.y,
00157 tmp.w*w + tmp.x*x + tmp.y*y + tmp.z*z);
00158 }
00159
00160 template <class T>
00161 void
00162 quat<T>::set (const T phi, const vec3<T>& k)
00163 {
00164 vec3<T> axis = k;
00165 axis.normalize();
00166 T sphi = T(sin(phi*0.5));
00167 x = axis.x*sphi;
00168 y = axis.y*sphi;
00169 z = axis.z*sphi;
00170 w = T(cos(phi*0.5));
00171 }
00172
00173 template <class T>
00174 void
00175 quat<T>::set (const mat3<T>& M)
00176 {
00177 T M11 = M.m[0];
00178 T M22 = M.m[4];
00179 T M33 = M.m[8];
00180 T M00 = M11 + M22 + M33;
00181 switch (maxi4<T>(M00, M11, M22, M33))
00182 {
00183 case 0:
00184 w = sqrt(1 + M00);
00185 x = (M.m[5] - M.m[7])/w;
00186 y = (M.m[6] - M.m[2])/w;
00187 z = (M.m[1] - M.m[3])/w;
00188 break;
00189 case 1:
00190 x = sqrt(1 + 2*M11 - M00);
00191 w = (M.m[5] - M.m[7])/x;
00192 y = (M.m[1] + M.m[3])/x;
00193 z = (M.m[2] + M.m[6])/x;
00194 break;
00195 case 2:
00196 y = sqrt(1 + 2*M22 - M00);
00197 w = (M.m[6] - M.m[2])/y;
00198 x = (M.m[1] + M.m[3])/y;
00199 z = (M.m[5] + M.m[7])/y;
00200 break;
00201 case 3:
00202 z = sqrt(1 + 2*M33 - M00);
00203 w = (M.m[1] - M.m[3])/z;
00204 x = (M.m[6] + M.m[2])/z;
00205 y = (M.m[5] + M.m[7])/z;
00206 break;
00207 }
00208 x *= 0.5;
00209 y *= 0.5;
00210 z *= 0.5;
00211 w *= 0.5;
00212 }
00213
00214
00215 template <class T1, class T2>
00216 inline quat<T2>
00217 mm_cast(quat<T1> v)
00218 {
00219 return quat<T2>(v.x, v.y, v.z, v.w);
00220 }
00221
00222 }
00223
00224 #endif // quat_h
00225