Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

ShQuaternionImpl.hpp

00001 // Sh: A GPU metaprogramming language. 00002 // 00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory 00004 // Project administrator: Michael D. McCool 00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa, 00006 // Michael D. McCool 00007 // 00008 // This software is provided 'as-is', without any express or implied 00009 // warranty. In no event will the authors be held liable for any damages 00010 // arising from the use of this software. 00011 // 00012 // Permission is granted to anyone to use this software for any purpose, 00013 // including commercial applications, and to alter it and redistribute it 00014 // freely, subject to the following restrictions: 00015 // 00016 // 1. The origin of this software must not be misrepresented; you must 00017 // not claim that you wrote the original software. If you use this 00018 // software in a product, an acknowledgment in the product documentation 00019 // would be appreciated but is not required. 00020 // 00021 // 2. Altered source versions must be plainly marked as such, and must 00022 // not be misrepresented as being the original software. 00023 // 00024 // 3. This notice may not be removed or altered from any source 00025 // distribution. 00027 #include "ShQuaternion.hpp" 00028 00029 namespace SH { 00030 template<ShBindingType B, typename T> 00031 ShQuaternion<B, T>::ShQuaternion() 00032 { 00033 if (B == SH_TEMP) 00034 { 00035 m_data = ShVector4f(1.0, 0.0, 0.0, 0.0); 00036 //m_data.setUnit(true); 00037 } 00038 } 00039 00040 template<ShBindingType B, typename T> 00041 template<ShBindingType B2> 00042 ShQuaternion<B, T>::ShQuaternion(const ShQuaternion<B2, T>& other) 00043 : m_data(other.getVector()) 00044 { 00045 } 00046 00047 template<ShBindingType B, typename T> 00048 template<ShBindingType B2> 00049 ShQuaternion<B, T>::ShQuaternion(const ShVector<4, B2, T>& values) 00050 : m_data(values) 00051 { 00052 } 00053 00054 template<ShBindingType B, typename T> 00055 template<ShBindingType B2, ShBindingType B3> 00056 ShQuaternion<B, T>::ShQuaternion(const ShAttrib<1, B2, T>& angle, 00057 const ShVector<3, B3, T>& axis) 00058 { 00059 m_data(0) = cos(angle/2.0); 00060 m_data(1,2,3) = SH::normalize(axis); 00061 m_data(1,2,3) *= sin(angle/2.0); 00062 //m_data.setUnit(true); 00063 } 00064 00065 template<ShBindingType B, typename T> 00066 template<ShBindingType B2> 00067 ShQuaternion<B, T>::ShQuaternion(const ShMatrix<4, 4, B2, T>& mat) 00068 { 00069 ShAttrib1f trace = 1.0 + mat[0](0) + mat[1](1) + mat[2](2); 00070 trace = (trace >= 0.0)*trace + (trace < 0.0)*0.0; 00071 ShAttrib1f c0 = (trace > 0.001); 00072 ShAttrib1f c1 = ((mat[0](0) > mat[1](1))*(mat[0](0) > mat[2](2))); 00073 ShAttrib1f c2 = ( mat[1](1) > mat[2](2) ); 00074 ShVector4f res0, res1, res2, res3; 00075 ShAttrib1f S0 = sqrt(trace) * 2.0; 00076 S0 += (S0 == 0.0)*1.0; 00077 00078 res0(0) = 0.25 * S0; 00079 res0(1) = (mat[1](2) - mat[2](1)) / S0; 00080 res0(2) = (mat[2](0) - mat[0](2)) / S0; 00081 res0(3) = (mat[0](1) - mat[1](0)) / S0; 00082 00083 trace = 1.0 + mat[0](0) - mat[1](1) - mat[2](2); 00084 trace = (trace >= 0.0)*trace + (trace < 0.0)*0.0; 00085 ShAttrib1f S1 = sqrt(trace) * 2.0; 00086 S1 += (S1 == 0.0)*1.0; 00087 00088 res1(0) = (mat[2](1) - mat[1](2)) / S1; 00089 res1(1) = 0.25 * S1; 00090 res1(2) = (mat[0](1) + mat[1](0)) / S1; 00091 res1(3) = (mat[2](0) + mat[0](2)) / S1; 00092 00093 trace = 1.0 - mat[0](0) + mat[1](1) - mat[2](2); 00094 trace = (trace >= 0.0)*trace + (trace < 0.0)*0.0; 00095 ShAttrib1f S2 = sqrt(trace) * 2.0; 00096 S2 += (S2 == 0.0)*1.0; 00097 00098 res2(0) = (mat[2](0) - mat[0](2)) / S2; 00099 res2(1) = (mat[0](1) + mat[1](0)) / S2; 00100 res2(2) = 0.25 * S2; 00101 res2(3) = (mat[1](2) + mat[2](1)) / S2; 00102 00103 trace = 1.0 - mat[0](0) - mat[1](1) + mat[2](2); 00104 trace = (trace >= 0.0)*trace + (trace < 0.0)*0.0; 00105 ShAttrib1f S3 = sqrt(trace) * 2.0; 00106 S3 += (S3 == 0.0)*1.0; 00107 00108 res3(0) = (mat[1](0) - mat[0](1)) / S3; 00109 res3(1) = (mat[2](0) + mat[0](2)) / S3; 00110 res3(2) = (mat[1](2) + mat[2](1)) / S3; 00111 res3(3) = 0.25 * S3; 00112 00113 m_data = c0*res0 + 00114 (c0 == 0.0)*(c1*res1 + (c1 == 0.0)*(c2*res2 + (c2 == 0.0)*res3)); 00115 //m_data.setUnit(true); 00116 } 00117 00118 template<ShBindingType B, typename T> 00119 std::ostream& operator<<(std::ostream& out, const ShQuaternion<B, T>& q) 00120 { 00121 float vals[4]; 00122 q.m_data.getValues(vals); 00123 out << "ShQuaternion: " << vals[0] << " " << vals[1] << " " << vals[2] 00124 << " " << vals[3]; 00125 return out; 00126 } 00127 00128 template<ShBindingType B, typename T> 00129 template<ShBindingType B2> 00130 ShQuaternion<B, T>& 00131 ShQuaternion<B, T>::operator=(const ShQuaternion<B2, T>& other) 00132 { 00133 m_data = other.getVector(); 00134 return *this; 00135 } 00136 00137 template<ShBindingType B, typename T> 00138 template<ShBindingType B2> 00139 ShQuaternion<B, T>& 00140 ShQuaternion<B, T>::operator+=(const ShQuaternion<B2, T>& right) 00141 { 00142 m_data += right.getVector(); 00143 return *this; 00144 } 00145 00146 template<ShBindingType B, typename T> 00147 template<ShBindingType B2> 00148 ShQuaternion<B, T>& 00149 ShQuaternion<B, T>::operator-=(const ShQuaternion<B2, T>& right) 00150 { 00151 m_data -= right.getVector(); 00152 return *this; 00153 } 00154 00155 template<ShBindingType B, typename T> 00156 template<ShBindingType B2> 00157 ShQuaternion<B, T>& 00158 ShQuaternion<B, T>::operator*=(const ShQuaternion<B2, T>& right) 00159 { 00160 ShVector4f result; 00161 ShVector4f rightData = right.getVector(); 00162 result(0) = 00163 m_data(0)*rightData(0) - SH::dot(m_data(1,2,3), rightData(1,2,3)); 00164 result(1,2,3) = 00165 m_data(0)*rightData(1,2,3) + rightData(0)*m_data(1,2,3) + 00166 cross(m_data(1,2,3), rightData(1,2,3)); 00167 00168 //result.setUnit(m_data.isUnit() && rightData.isUnit()); 00169 m_data = result; 00170 return *this; 00171 } 00172 00173 template<ShBindingType B, typename T> 00174 template<ShBindingType B2> 00175 ShQuaternion<B, T>& 00176 ShQuaternion<B, T>::operator*=(const ShAttrib<1, B2, T>& right) 00177 { 00178 m_data = m_data*right; 00179 return *this; 00180 } 00181 00182 template<ShBindingType B, typename T> 00183 template<ShBindingType B2> 00184 ShQuaternion<B, T>& 00185 ShQuaternion<B, T>::operator*=(const ShVector<3, B2, T>& right) 00186 { 00187 ShVector4f v; 00188 v(0) = 0.0; 00189 v(1,2,3) = right; 00190 //v.setUnit(right.isUnit()); 00191 *this *= ShQuaternionf(v); 00192 return *this; 00193 } 00194 00195 template<ShBindingType B, typename T> 00196 template<ShBindingType B2> 00197 ShQuaternion<B, T>& 00198 ShQuaternion<B, T>::operator*=(const ShNormal<3, B2, T>& right) 00199 { 00200 ShVector4f v; 00201 v(0) = 0.0; 00202 v(1,2,3) = right; 00203 //v.setUnit(right.isUnit()); 00204 *this *= ShQuaternionf(v); 00205 return *this; 00206 } 00207 00208 template<ShBindingType B, typename T> 00209 template<ShBindingType B2> 00210 ShAttrib<1, SH_TEMP, T> 00211 ShQuaternion<B, T>::dot(const ShQuaternion<B2, T>& q) const 00212 { 00213 return SH::dot(m_data, q.getVector()); 00214 } 00215 00216 template<ShBindingType B, typename T> 00217 ShQuaternion<SH_TEMP, T> ShQuaternion<B, T>::conjugate() const 00218 { 00219 ShVector4f conjData; 00220 conjData(0) = m_data(0); 00221 conjData(1, 2, 3) = -m_data(1, 2, 3); 00222 //conjData.setUnit(m_data.isUnit()); 00223 00224 return ShQuaternion<SH_TEMP>(conjData); 00225 } 00226 00227 template<ShBindingType B, typename T> 00228 ShQuaternion<SH_TEMP, T> ShQuaternion<B, T>::inverse() const 00229 { 00230 // if (m_data.isUnit()) { 00231 // return conjugate(); 00232 // } else { 00233 ShAttrib1f norm = SH::dot(m_data, m_data); 00234 return conjugate() * (1.0 / norm); 00235 // } 00236 } 00237 00238 template<ShBindingType B, typename T> 00239 ShMatrix<4, 4, SH_TEMP, T> ShQuaternion<B, T>::getMatrix() const 00240 { 00241 SH::ShMatrix4x4f m; 00242 ShAttrib4f x = m_data(1,1,1,1) * m_data(1,2,3,0); 00243 ShAttrib4f y = m_data(2,2,2,2) * m_data(0,2,3,0); 00244 ShAttrib4f z = m_data(3,3,3,3) * m_data(0,0,3,0); 00245 00246 m[0](0) = 1 - 2 * (y(1) + z(2)); 00247 m[1](0) = 2 * (x(1) - z(3)); 00248 m[2](0) = 2 * (x(2) + y(3)); 00249 00250 m[0](1) = 2 * (x(2) + z(3)); 00251 m[1](1) = 1 - 2 * (x(0) + z(2)); 00252 m[2](1) = 2 * (y(2) - x(3)); 00253 00254 m[0](2) = 2 * (x(2) - y(3)); 00255 m[1](2) = 2 * (y(2) + x(3)); 00256 m[2](2) = 1 - 2 * (x(0) + y(1)); 00257 00258 return m; 00259 } 00260 00261 template<ShBindingType B, typename T> 00262 ShVector<4, SH_TEMP, T> ShQuaternion<B, T>::getVector() const 00263 { 00264 return m_data; 00265 } 00266 00267 template<ShBindingType B, typename T> 00268 template<ShBindingType B2> 00269 ShQuaternion<SH_TEMP, T> 00270 ShQuaternion<B, T>::operator+(const ShQuaternion<B2, T>& q) 00271 { 00272 ShQuaternion<B, T> r = *this; 00273 return (r += q); 00274 } 00275 00276 template<ShBindingType B, typename T> 00277 template<ShBindingType B2> 00278 ShQuaternion<SH_TEMP, T> 00279 ShQuaternion<B, T>::operator-(const ShQuaternion<B2, T>& q) 00280 { 00281 ShQuaternion<B, T> r = *this; 00282 return (r -= q); 00283 } 00284 00285 template<ShBindingType B, typename T> 00286 template<ShBindingType B2> 00287 ShQuaternion<SH_TEMP, T> 00288 ShQuaternion<B, T>::operator*(const ShQuaternion<B2, T>& q) 00289 { 00290 ShQuaternion<B, T> r = *this; 00291 return (r *= q); 00292 } 00293 00294 template<ShBindingType B, typename T> 00295 template<ShBindingType B2> 00296 ShQuaternion<SH_TEMP, T> 00297 ShQuaternion<B, T>::operator*(const ShAttrib<1, B2, T>& c) 00298 { 00299 ShQuaternion<B, T> r = *this; 00300 return (r *= c); 00301 } 00302 00303 template<ShBindingType B, typename T> 00304 template<ShBindingType B2> 00305 ShQuaternion<SH_TEMP, T> 00306 ShQuaternion<B, T>::operator*(const ShVector<3, B2, T>& v) 00307 { 00308 ShQuaternion<B, T> r = *this; 00309 return (r *= v); 00310 } 00311 00312 template<ShBindingType B, typename T> 00313 template<ShBindingType B2> 00314 ShQuaternion<SH_TEMP, T> 00315 ShQuaternion<B, T>::operator*(const ShNormal<3, B2, T>& v) 00316 { 00317 ShQuaternion<B, T> r = *this; 00318 return (r *= v); 00319 } 00320 00321 template<ShBindingType B, typename T> 00322 void ShQuaternion<B, T>::normalize() 00323 { 00324 m_data = SH::normalize(m_data); 00325 } 00326 00327 template<ShBindingType B, typename T> 00328 void ShQuaternion<B, T>::setUnit(bool flag) 00329 { 00330 //m_data.setUnit(flag); 00331 } 00332 00333 template<ShBindingType B, typename T> 00334 void ShQuaternion<B, T>::getValues(T values[]) const 00335 { 00336 m_data.getValues(values); 00337 } 00338 00339 template<ShBindingType B, typename T, ShBindingType B2> 00340 ShQuaternion<SH_TEMP, T> 00341 operator*(const ShAttrib<1, B2, T>& c, const ShQuaternion<B, T>& q) 00342 { 00343 ShQuaternion<B, T> r = q; 00344 return (r *= c); 00345 } 00346 00347 template<ShBindingType B1, ShBindingType B2, typename T> 00348 extern ShQuaternion<SH_TEMP, T> 00349 slerp(const ShQuaternion<B1, T>& q1, const ShQuaternion<B2, T>& q2, 00350 const ShAttrib1f& t) 00351 { 00352 //TODO::q1 and q2 must be unit quaternions, we cannot call normalize here 00353 //since it's not a const function. 00354 //TODO: when cosTheta is 1 or -1, we need to fallback to linear interpolation 00355 //not sure how to implement this efficiently yet 00356 ShAttrib<1, SH_TEMP, T> cosTheta = q1.dot(q2); 00357 ShAttrib<1, SH_TEMP, T> sinTheta = sqrt(1.0 - cosTheta*cosTheta); 00358 00359 ShQuaternion<B2, T> q2prime = (cosTheta >= 0.0)*q2 - (cosTheta < 0.0)*q2; 00360 ShAttrib<1, SH_TEMP, T> theta = asin(sinTheta); 00361 00362 return (sin((1.0 - t)*theta)/sinTheta)*q1 + (sin(t*theta)/sinTheta)*q2prime; 00363 } 00364 00365 template<ShBindingType B, typename T> 00366 std::string ShQuaternion<B, T>::name() const 00367 { 00368 return m_data.name(); 00369 } 00370 00371 template<ShBindingType B, typename T> 00372 void ShQuaternion<B, T>::name(const std::string& name) 00373 { 00374 m_data.name(name); 00375 } 00376 00377 00378 }

Generated on Mon Oct 18 14:17:40 2004 for Sh by doxygen 1.3.7