Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | 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(HostType 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 Jan 24 18:36:35 2005 for Sh by  doxygen 1.4.1