00001
00002
00003
00004
00005
00006 #ifndef _GMTL_VEC_OPS_H_
00007 #define _GMTL_VEC_OPS_H_
00008
00009 #include <gmtl/Defines.h>
00010 #include <gmtl/Math.h>
00011 #include <gmtl/Vec.h>
00012 #ifndef GMTL_NO_METAPROG
00013 #include <gmtl/VecOpsMeta.h>
00014 #include <gmtl/VecExprMeta.h>
00015 #endif
00016
00017 namespace gmtl
00018 {
00019
00025
00026
00034 #ifdef GMTL_NO_METAPROG
00035 template<typename DATA_TYPE, unsigned SIZE>
00036 Vec<DATA_TYPE, SIZE> operator- (const VecBase<DATA_TYPE, SIZE>& v1)
00037 {
00038 Vec<DATA_TYPE, SIZE> ret_val;
00039 for ( unsigned i=0; i < SIZE; ++i )
00040 {
00041 ret_val[i] = -v1[i];
00042 }
00043 return ret_val;
00044 }
00045 #else
00046 template<typename T, unsigned SIZE, typename R1>
00047 inline VecBase<T,SIZE, meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary> >
00048 operator-(const VecBase<T,SIZE,R1>& v1)
00049 {
00050 return VecBase<T,SIZE,
00051 meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary> >
00052 ( meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary>(v1) );
00053 }
00054 #endif
00055
00065 #ifdef GMTL_NO_METAPROG
00066 template<class DATA_TYPE, unsigned SIZE>
00067 VecBase<DATA_TYPE, SIZE>& operator +=(VecBase<DATA_TYPE, SIZE>& v1,
00068 const VecBase<DATA_TYPE, SIZE>& v2)
00069 #else
00070 template<class DATA_TYPE, unsigned SIZE, typename REP2>
00071 VecBase<DATA_TYPE, SIZE>& operator +=(VecBase<DATA_TYPE, SIZE>& v1,
00072 const VecBase<DATA_TYPE, SIZE, REP2>& v2)
00073 #endif
00074 {
00075 for(unsigned i=0;i<SIZE;++i)
00076 {
00077 v1[i] += v2[i];
00078 }
00079
00080 return v1;
00081 }
00082
00091 #ifdef GMTL_NO_METAPROG
00092 template<class DATA_TYPE, unsigned SIZE>
00093 VecBase<DATA_TYPE, SIZE> operator +(const VecBase<DATA_TYPE, SIZE>& v1,
00094 const VecBase<DATA_TYPE, SIZE>& v2)
00095 {
00096 VecBase<DATA_TYPE, SIZE> ret_val(v1);
00097 ret_val += v2;
00098 return ret_val;
00099 }
00100 #else
00101 template<typename T, unsigned SIZE, typename R1, typename R2>
00102 inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,R2>, meta::VecPlusBinary> >
00103 operator+(const VecBase<T,SIZE,R1>& v1, const VecBase<T,SIZE,R2>& v2)
00104 {
00105 return VecBase<T,SIZE,
00106 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00107 VecBase<T,SIZE,R2>,
00108 meta::VecPlusBinary> >( meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00109 VecBase<T,SIZE,R2>,
00110 meta::VecPlusBinary>(v1,v2) );
00111 }
00112 #endif
00113
00123 #ifdef GMTL_NO_METAPROG
00124 template<class DATA_TYPE, unsigned SIZE>
00125 VecBase<DATA_TYPE, SIZE>& operator -=(VecBase<DATA_TYPE, SIZE>& v1,
00126 const VecBase<DATA_TYPE, SIZE>& v2)
00127 #else
00128 template<class DATA_TYPE, unsigned SIZE, typename REP2>
00129 VecBase<DATA_TYPE, SIZE>& operator -=(VecBase<DATA_TYPE, SIZE>& v1,
00130 const VecBase<DATA_TYPE, SIZE, REP2>& v2)
00131 #endif
00132 {
00133 for(unsigned i=0;i<SIZE;++i)
00134 {
00135 v1[i] -= v2[i];
00136 }
00137
00138 return v1;
00139 }
00140
00149 #ifdef GMTL_NO_METAPROG
00150 template < class DATA_TYPE, unsigned SIZE>
00151 Vec<DATA_TYPE, SIZE> operator -(const VecBase<DATA_TYPE, SIZE>& v1,
00152 const VecBase<DATA_TYPE, SIZE>& v2)
00153 {
00154 Vec<DATA_TYPE, SIZE> ret_val(v1);
00155 ret_val -= v2;
00156 return ret_val;
00157 }
00158 #else
00159 template<typename T, unsigned SIZE, typename R1, typename R2>
00160 inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,R2>, meta::VecMinusBinary> >
00161 operator-(const VecBase<T,SIZE,R1>& v1, const VecBase<T,SIZE,R2>& v2)
00162 {
00163 return VecBase<T,SIZE,
00164 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00165 VecBase<T,SIZE,R2>,
00166 meta::VecMinusBinary> >( meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00167 VecBase<T,SIZE,R2>,
00168 meta::VecMinusBinary>(v1,v2) );
00169 }
00170 #endif
00171
00181 template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
00182 VecBase<DATA_TYPE, SIZE>& operator *=(VecBase<DATA_TYPE, SIZE>& v1,
00183 const SCALAR_TYPE& scalar)
00184 {
00185 for(unsigned i=0;i<SIZE;++i)
00186 {
00187 v1[i] *= (DATA_TYPE)scalar;
00188 }
00189
00190 return v1;
00191 }
00192
00202 #ifdef GMTL_NO_METAPROG
00203 template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
00204 VecBase<DATA_TYPE, SIZE> operator *(const VecBase<DATA_TYPE, SIZE>& v1,
00205 const SCALAR_TYPE& scalar)
00206 {
00207 VecBase<DATA_TYPE, SIZE> ret_val(v1);
00208 ret_val *= scalar;
00209 return ret_val;
00210
00211
00212 }
00213 #else
00214 template<typename T, unsigned SIZE, typename R1>
00215 inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE, meta::ScalarArg<T> >, meta::VecMultBinary> >
00216 operator*(const VecBase<T,SIZE,R1>& v1, const T scalar)
00217 {
00218 return VecBase<T,SIZE,
00219 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00220 VecBase<T,SIZE, meta::ScalarArg<T> >,
00221 meta::VecMultBinary> >(
00222 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00223 VecBase<T,SIZE, meta::ScalarArg<T> >,
00224 meta::VecMultBinary>(v1,
00225 meta::ScalarArg<T>(scalar)) );
00226 }
00227
00228 template<typename T, unsigned SIZE, typename R1>
00229 inline VecBase<T,SIZE, meta::VecBinaryExpr< VecBase<T,SIZE, meta::ScalarArg<T> >,
00230 VecBase<T,SIZE,R1>,
00231 meta::VecMultBinary> >
00232 operator*(const T scalar, const VecBase<T,SIZE,R1>& v1)
00233 {
00234 return VecBase<T,SIZE,
00235 meta::VecBinaryExpr<VecBase<T,SIZE, meta::ScalarArg<T> >,
00236 VecBase<T,SIZE,R1>,
00237 meta::VecMultBinary> >(
00238 meta::VecBinaryExpr<VecBase<T,SIZE, meta::ScalarArg<T> >,
00239 VecBase<T,SIZE,R1>,
00240 meta::VecMultBinary>(meta::ScalarArg<T>(scalar), v1 ) );
00241 }
00242 #endif
00243
00253 #ifdef GMTL_NO_METAPROG
00254 template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
00255 VecBase<DATA_TYPE, SIZE> operator *(const SCALAR_TYPE& scalar,
00256 const VecBase<DATA_TYPE, SIZE>& v1)
00257 {
00258 VecBase<DATA_TYPE, SIZE> ret_val(v1);
00259 ret_val *= scalar;
00260 return ret_val;
00261
00262
00263 }
00264 #endif
00265
00275 template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
00276 VecBase<DATA_TYPE, SIZE>& operator /=(VecBase<DATA_TYPE, SIZE>& v1,
00277 const SCALAR_TYPE& scalar)
00278 {
00279 for(unsigned i=0;i<SIZE;++i)
00280 {
00281 v1[i] /= scalar;
00282 }
00283
00284 return v1;
00285 }
00286
00296 #ifdef GMTL_NO_METAPROG
00297 template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
00298 VecBase<DATA_TYPE, SIZE> operator /(const VecBase<DATA_TYPE, SIZE>& v1,
00299 const SCALAR_TYPE& scalar)
00300 {
00301 VecBase<DATA_TYPE, SIZE> ret_val(v1);
00302 ret_val /= scalar;
00303 return ret_val;
00304
00305 }
00306 #else
00307 template<typename T, unsigned SIZE, typename R1>
00308 inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE, meta::ScalarArg<T> >, meta::VecDivBinary> >
00309 operator/(const VecBase<T,SIZE,R1>& v1, const T scalar)
00310 {
00311 return VecBase<T,SIZE,
00312 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00313 VecBase<T,SIZE, meta::ScalarArg<T> >,
00314 meta::VecDivBinary> >(
00315 meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
00316 VecBase<T,SIZE, meta::ScalarArg<T> >,
00317 meta::VecDivBinary>(v1,
00318 meta::ScalarArg<T>(scalar)) );
00319 }
00320 #endif
00321
00338 #ifdef GMTL_NO_METAPROG
00339 template<class DATA_TYPE, unsigned SIZE>
00340 DATA_TYPE dot(const VecBase<DATA_TYPE, SIZE>& v1, const VecBase<DATA_TYPE, SIZE>& v2)
00341 {
00342 DATA_TYPE ret_val(0);
00343 for(unsigned i=0;i<SIZE;++i)
00344 {
00345 ret_val += (v1[i] * v2[i]);
00346 }
00347 return ret_val;
00348 }
00349 #else
00350 template<class DATA_TYPE, unsigned SIZE, typename REP1, typename REP2>
00351 DATA_TYPE dot(const VecBase<DATA_TYPE, SIZE, REP1>& v1, const VecBase<DATA_TYPE, SIZE, REP2>& v2)
00352 {
00353 return gmtl::meta::DotVecUnrolled<SIZE-1,
00354 VecBase<DATA_TYPE,SIZE,REP1>,
00355 VecBase<DATA_TYPE,SIZE,REP2> >::func(v1,v2);
00356 }
00357 #endif
00358
00366 template<class DATA_TYPE, unsigned SIZE>
00367 DATA_TYPE length(const Vec<DATA_TYPE, SIZE>& v1)
00368 {
00369 DATA_TYPE ret_val = lengthSquared(v1);
00370 if (ret_val == DATA_TYPE(0.0f))
00371 return DATA_TYPE(0.0f);
00372 else
00373 return Math::sqrt(ret_val);
00374 }
00375
00385 template<class DATA_TYPE, unsigned SIZE>
00386 DATA_TYPE lengthSquared(const Vec<DATA_TYPE, SIZE>& v1)
00387 {
00388 #ifdef GMTL_NO_METAPROG
00389 DATA_TYPE ret_val(0);
00390 for(unsigned i=0;i<SIZE;++i)
00391 {
00392 ret_val += (v1[i] * v1[i]);
00393 }
00394
00395 return ret_val;
00396 #else
00397 return gmtl::meta::LenSqrVecUnrolled<SIZE-1,Vec<DATA_TYPE,SIZE> >::func(v1);
00398 #endif
00399 }
00400
00412 template<class DATA_TYPE, unsigned SIZE>
00413 DATA_TYPE normalize(Vec<DATA_TYPE, SIZE>& v1)
00414 {
00415 DATA_TYPE len = length(v1);
00416
00417 if(len != 0.0f)
00418 {
00419 for(unsigned i=0;i<SIZE;++i)
00420 {
00421 v1[i] /= len;
00422 }
00423 }
00424
00425 return len;
00426 }
00427
00437 template< class DATA_TYPE, unsigned SIZE >
00438 bool isNormalized( const Vec<DATA_TYPE, SIZE>& v1,
00439 const DATA_TYPE eps = (DATA_TYPE) 0.0001f )
00440 {
00441 return Math::isEqual( lengthSquared( v1 ), DATA_TYPE(1.0), eps );
00442 }
00443
00459 template<class DATA_TYPE>
00460 Vec<DATA_TYPE,3>& cross( Vec<DATA_TYPE,3>& result, const Vec<DATA_TYPE, 3>& v1,
00461 const Vec<DATA_TYPE, 3>& v2 )
00462 {
00463 result.set( (v1[Yelt]*v2[Zelt]) - (v1[Zelt]*v2[Yelt]),
00464 (v1[Zelt]*v2[Xelt]) - (v1[Xelt]*v2[Zelt]),
00465 (v1[Xelt]*v2[Yelt]) - (v1[Yelt]*v2[Xelt]) );
00466 return result;
00467 }
00468
00490 template<class DATA_TYPE, unsigned SIZE>
00491 VecBase<DATA_TYPE, SIZE>& reflect( VecBase<DATA_TYPE, SIZE>& result, const
00492 VecBase<DATA_TYPE, SIZE>& vec,
00493 const Vec<DATA_TYPE, SIZE>& normal )
00494 {
00495 result = vec - (DATA_TYPE( 2.0 ) * (dot( (Vec<DATA_TYPE, SIZE>)vec, normal ) * normal));
00496 return result;
00497 }
00498
00519 template <typename DATA_TYPE, unsigned SIZE>
00520 VecBase<DATA_TYPE, SIZE>& lerp( VecBase<DATA_TYPE, SIZE>& result,
00521 const DATA_TYPE& lerpVal,
00522 const VecBase<DATA_TYPE, SIZE>& from,
00523 const VecBase<DATA_TYPE, SIZE>& to )
00524 {
00526 for (unsigned int x = 0; x < SIZE; ++x)
00527 {
00528 Math::lerp( result[x], lerpVal, from[x], to[x] );
00529 }
00530 return result;
00531 }
00540
00541
00550 template<class DATA_TYPE, unsigned SIZE>
00551 inline bool operator==(const VecBase<DATA_TYPE, SIZE>& v1,
00552 const VecBase<DATA_TYPE, SIZE>& v2)
00553 {
00554 #ifdef GMTL_NO_METAPROG
00555 for(unsigned i=0;i<SIZE;++i)
00556 {
00557 if(v1[i] != v2[i])
00558 {
00559 return false;
00560 }
00561 }
00562
00563 return true;
00564 #else
00565 return gmtl::meta::EqualVecUnrolled<SIZE-1,Vec<DATA_TYPE,SIZE> >::func(v1,v2);
00566 #endif
00567
00568
00569
00570
00571
00572 }
00573
00583 template<class DATA_TYPE, unsigned SIZE>
00584 inline bool operator!=(const VecBase<DATA_TYPE, SIZE>& v1,
00585 const VecBase<DATA_TYPE, SIZE>& v2)
00586 {
00587 return(! (v1 == v2));
00588 }
00589
00602 template<class DATA_TYPE, unsigned SIZE>
00603 inline bool isEqual(const VecBase<DATA_TYPE, SIZE>& v1,
00604 const VecBase<DATA_TYPE, SIZE>& v2, const DATA_TYPE eps)
00605 {
00606 gmtlASSERT(eps >= 0);
00607
00608 for(unsigned i=0;i<SIZE;++i)
00609 {
00610 if ( gmtl::Math::abs(v1[i] - v2[i]) > eps )
00611 {
00612 return false;
00613 }
00614 }
00615 return true;
00616 }
00617
00620 }
00621
00622 #endif