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

Generated on Wed Jun 15 18:12:41 2005 for Sh by  doxygen 1.4.3-20050530