00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include <cmath> 00026 #include <cstring> 00027 #include <iostream> 00028 #include <cassert> 00029 #include <limits> 00030 00031 #include "cinder/CinderMath.h" 00032 00033 namespace cinder { 00034 00035 template<typename T, typename Y> 00036 struct VEC3CONV { 00037 static T getX( const Y &v ) { return static_cast<T>( v.x ); } 00038 static T getY( const Y &v ) { return static_cast<T>( v.y ); } 00039 static T getZ( const Y &v ) { return static_cast<T>( v.z ); } 00040 }; 00041 00042 template<typename T> 00043 class Vec2 00044 { 00045 public: 00046 T x,y; 00047 00048 typedef T TYPE; 00049 static const int DIM = 2; 00050 00051 Vec2() {} 00052 Vec2( T nx, T ny ) : x( nx ), y( ny ) {} 00053 Vec2( const Vec2<T>& src ) : x( src.x ), y( src.y ) {} 00054 explicit Vec2( const T *d ) : x( d[0] ), y( d[1] ) {} 00055 00056 template<typename FromT> 00057 Vec2( const Vec2<FromT>& src ) 00058 : x( static_cast<T>( src.x ) ),y( static_cast<T>( src.y ) ) 00059 {} 00060 00061 void set( T ax, T ay ) 00062 { 00063 x = ax; y = ay; 00064 } 00065 00066 void set( const Vec2<T> &rhs ) 00067 { 00068 x = rhs.x; y = rhs.y; 00069 } 00070 00071 // Operators 00072 template<typename FromT> 00073 Vec2<T>& operator=( const Vec2<FromT>& rhs ) 00074 { 00075 x = static_cast<T>( rhs.x ); 00076 y = static_cast<T>( rhs.y ); 00077 return * this; 00078 } 00079 00080 Vec2<T>& operator=( const Vec2<T>& rhs ) 00081 { 00082 x = rhs.x; 00083 y = rhs.y; 00084 return * this; 00085 } 00086 00087 T& operator[]( int n ) 00088 { 00089 assert( n >= 0 && n <= 1 ); 00090 return (&x)[n]; 00091 } 00092 00093 const T& operator[]( int n ) const 00094 { 00095 assert( n >= 0 && n <= 1 ); 00096 return (&x)[n]; 00097 } 00098 00099 const Vec2<T> operator+( const Vec2<T>& rhs ) const { return Vec2<T>( x + rhs.x, y + rhs.y ); } 00100 const Vec2<T> operator-( const Vec2<T>& rhs ) const { return Vec2<T>( x - rhs.x, y - rhs.y ); } 00101 const Vec2<T> operator*( const Vec2<T>& rhs ) const { return Vec2<T>( x * rhs.x, y * rhs.y ); } 00102 const Vec2<T> operator/( const Vec2<T>& rhs ) const { return Vec2<T>( x / rhs.x, y / rhs.y ); } 00103 Vec2<T>& operator+=( const Vec2<T>& rhs ) { x += rhs.x; y += rhs.y; return *this; } 00104 Vec2<T>& operator-=( const Vec2<T>& rhs ) { x -= rhs.x; y -= rhs.y; return *this; } 00105 Vec2<T>& operator*=( const Vec2<T>& rhs ) { x *= rhs.x; y *= rhs.y; return *this; } 00106 Vec2<T>& operator/=( const Vec2<T>& rhs ) { x /= rhs.x; y /= rhs.y; return *this; } 00107 const Vec2<T> operator/( T rhs ) const { return Vec2<T>( x / rhs, y / rhs ); } 00108 Vec2<T>& operator+=( T rhs ) { x += rhs; y += rhs; return *this; } 00109 Vec2<T>& operator-=( T rhs ) { x -= rhs; y -= rhs; return *this; } 00110 Vec2<T>& operator*=( T rhs ) { x *= rhs; y *= rhs; return *this; } 00111 Vec2<T>& operator/=( T rhs ) { x /= rhs; y /= rhs; return *this; } 00112 00113 Vec2<T> operator-() const { return Vec2<T>( -x, -y ); } // unary negation 00114 00115 bool operator==( const Vec2<T> &rhs ) const 00116 { 00117 return ( x == rhs.x ) && ( y == rhs.y ); 00118 } 00119 00120 bool operator!=( const Vec2<T> &rhs ) const 00121 { 00122 return ! ( *this == rhs ); 00123 } 00124 00125 T dot( const Vec2<T> &rhs ) const 00126 { 00127 return x * rhs.x + y * rhs.y; 00128 } 00129 00130 T distance( const Vec2<T> &rhs ) const 00131 { 00132 return ( *this - rhs ).length(); 00133 } 00134 00135 T distanceSquared( const Vec2<T> &rhs ) const 00136 { 00137 return ( *this - rhs ).lengthSquared(); 00138 } 00139 00140 T length() const 00141 { 00142 return (T)std::sqrt( x*x + y*y ); 00143 } 00144 00145 void normalize() 00146 { 00147 T invS = ((T)1) / length(); 00148 x *= invS; 00149 y *= invS; 00150 } 00151 00152 Vec2<T> normalized() const 00153 { 00154 T invS = ((T)1) / length(); 00155 return Vec2<T>( x * invS, y * invS ); 00156 } 00157 00158 // tests for zero-length 00159 void safeNormalize() 00160 { 00161 T s = lengthSquared(); 00162 if( s > 0 ) { 00163 T invL = ((T)1) / math<T>::sqrt( s ); 00164 x *= invL; 00165 y *= invL; 00166 } 00167 } 00168 00169 Vec2<T> safeNormalized() 00170 { 00171 T s = lengthSquared(); 00172 if( s > 0 ) { 00173 T invL = ((T)1) / math<T>::sqrt( s ); 00174 return Vec2<T>( x * invL, y * invL ); 00175 } 00176 else 00177 return Vec2<T>::zero(); 00178 } 00179 00180 T lengthSquared() const 00181 { 00182 return x * x + y * y; 00183 } 00184 00185 void invert() 00186 { 00187 x - -x; 00188 y = -y; 00189 } 00190 00191 Vec2<T> inverse() 00192 { 00193 return Vec2<T>( -x, -y ); 00194 } 00195 00196 Vec2<T> lerp( T fact, const Vec2<T>& r ) const 00197 { 00198 return (*this) + ( r - (*this) ) * fact; 00199 } 00200 00201 static Vec2<T> max() 00202 { 00203 return Vec2<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00204 } 00205 00206 static Vec2<T> zero() 00207 { 00208 return Vec2<T>( static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00209 } 00210 00211 static Vec2<T> one() 00212 { 00213 return Vec2<T>( static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00214 } 00215 00216 operator T*(){ return (T*) this; } 00217 operator const T*() const { return (const T*) this; } 00218 00219 friend std::ostream& operator<<( std::ostream& lhs, const Vec2<T>& rhs ) 00220 { 00221 lhs << "[" << rhs.x << "," << rhs.y << "]"; 00222 return lhs; 00223 } 00224 00225 static Vec2<T> xAxis() { return Vec2<T>( 1, 0 ); } 00226 static Vec2<T> yAxis() { return Vec2<T>( 0, 1 ); } 00227 }; 00228 00229 template<typename T> 00230 class Vec3 00231 { 00232 public: 00233 T x,y,z; 00234 00235 typedef T TYPE; 00236 static const int DIM = 3; 00237 00238 Vec3() {} 00239 Vec3( T nx, T ny, T nz ) 00240 : x( nx ), y( ny ), z( nz ) 00241 {} 00242 Vec3( const Vec3<T> &src ) 00243 : x( src.x ), y( src.y ), z( src.z ) 00244 {} 00245 Vec3( const Vec2<T> &v2, T aZ ) 00246 : x( v2.x ), y ( v2.y ), z( aZ ) 00247 {} 00248 explicit Vec3( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ) {} 00249 template<typename FromT> 00250 Vec3( const Vec3<FromT> &src ) 00251 : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ) 00252 {} 00253 template<typename Y> 00254 explicit Vec3( const Y &v ) 00255 : x( VEC3CONV<Vec3<typename T::TYPE>,Y>::getX( v ) ), y( VEC3CONV<typename T::TYPE,Y>::getY( v ) ), z( VEC3CONV<typename T::TYPE,Y>::getZ( v ) ) 00256 { 00257 } 00258 00259 void set( T ax, T ay, T az ) 00260 { 00261 x = ax; y = ay; z = az; 00262 } 00263 00264 void set( const Vec3<T> &rhs ) 00265 { 00266 x = rhs.x; y = rhs.y; z = rhs.z; 00267 } 00268 00269 Vec3<T>& operator=( const Vec3<T> &rhs ) 00270 { 00271 x = rhs.x; 00272 y = rhs.y; 00273 z = rhs.z; 00274 return * this; 00275 } 00276 00277 template<typename FromT> 00278 Vec3<T>& operator=( const Vec3<FromT> &rhs ) 00279 { 00280 x = static_cast<T>( rhs.x ); 00281 y = static_cast<T>( rhs.y ); 00282 z = static_cast<T>( rhs.z ); 00283 return * this; 00284 } 00285 00286 T& operator[]( int n ) 00287 { 00288 assert( n >= 0 && n <= 2 ); 00289 return (&x)[n]; 00290 } 00291 00292 const T& operator[]( int n ) const 00293 { 00294 assert( n >= 0 && n <= 2 ); 00295 return (&x)[n]; 00296 } 00297 00298 const Vec3<T> operator+( const Vec3<T>& rhs ) const { return Vec3<T>( x + rhs.x, y + rhs.y, z + rhs.z ); } 00299 const Vec3<T> operator-( const Vec3<T>& rhs ) const { return Vec3<T>( x - rhs.x, y - rhs.y, z - rhs.z ); } 00300 const Vec3<T> operator*( const Vec3<T>& rhs ) const { return Vec3<T>( x * rhs.x, y * rhs.y, z * rhs.z ); } 00301 const Vec3<T> operator/( const Vec3<T>& rhs ) const { return Vec3<T>( x / rhs.x, y / rhs.y, z / rhs.z ); } 00302 Vec3<T>& operator+=( const Vec3<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } 00303 Vec3<T>& operator-=( const Vec3<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } 00304 Vec3<T>& operator*=( const Vec3<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this; } 00305 Vec3<T>& operator/=( const Vec3<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; return *this; } 00306 const Vec3<T> operator/( T rhs ) const { T invRhs = static_cast<T>( 1.0 ) / rhs; return Vec3<T>( x * invRhs, y * invRhs, z * invRhs ); } 00307 Vec3<T>& operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; return *this; } 00308 Vec3<T>& operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; return *this; } 00309 Vec3<T>& operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; return *this; } 00310 Vec3<T>& operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; return *this; } 00311 00312 Vec3<T> operator-() const { return Vec3<T>( -x, -y, -z ); } // unary negation 00313 00314 bool operator==( const Vec3<T>& rhs ) const 00315 { 00316 return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ); 00317 } 00318 00319 bool operator!=( const Vec3<T>& rhs ) const 00320 { 00321 return !( *this == rhs ); 00322 } 00323 00324 T dot( const Vec3<T> &rhs ) const 00325 { 00326 return x*rhs.x + y*rhs.y + z*rhs.z; 00327 } 00328 00329 Vec3<T> cross( const Vec3<T> &rhs ) const 00330 { 00331 return Vec3<T>( y * rhs.z - rhs.y * z, z * rhs.x - rhs.z * x, x * rhs.y - rhs.x * y ); 00332 } 00333 00334 T distance( const Vec3<T> &rhs ) const 00335 { 00336 return ( *this - rhs ).length(); 00337 } 00338 00339 T distanceSquared( const Vec3<T> &rhs ) const 00340 { 00341 return ( *this - rhs ).lengthSquared(); 00342 } 00343 00344 T length() const 00345 { 00346 return (T)std::sqrt( x*x + y*y + z*z ); 00347 } 00348 00349 T lengthSquared() const 00350 { 00351 return x*x + y*y + z*z; 00352 } 00353 00354 void invert() 00355 { 00356 x - -x; y = -y; z = -z; 00357 } 00358 00359 Vec3<T> inverse() 00360 { 00361 return Vec3<T>( -x, -y, -z ); 00362 } 00363 00364 void normalize() 00365 { 00366 T invS = ((T)1) / length(); 00367 x *= invS; 00368 y *= invS; 00369 z *= invS; 00370 } 00371 00372 Vec3<T> normalized() const 00373 { 00374 T invS = ((T)1) / length(); 00375 return Vec3<T>( x * invS, y * invS, z * invS ); 00376 } 00377 00378 // tests for zero-length 00379 void safeNormalize() 00380 { 00381 T s = lengthSquared(); 00382 if( s > 0 ) { 00383 T invS = ((T)1) / math<T>::sqrt( s ); 00384 x *= invS; 00385 y *= invS; 00386 z *= invS; 00387 } 00388 } 00389 00390 Vec3<T> safeNormalized() 00391 { 00392 T s = lengthSquared(); 00393 if( s > 0 ) { 00394 float invS = ((T)1) / math<T>::sqrt( s ); 00395 return Vec3<T>( x * invS, y * invS, z * invS ); 00396 } 00397 else 00398 return *this; 00399 } 00400 00401 Vec3<T> randomOrthogonal() const 00402 { 00403 if( dot( Vec3<T>::xAxis() ) >= (T)0.01 ) { 00404 return cross( Vec3<T>::xAxis() ); 00405 } 00406 else 00407 return cross( Vec3<T>::yAxis() ); 00408 } 00409 00410 void rotate( T ax, T ay, T az ) 00411 { 00412 T a = cos( toRadians( ax ) ); 00413 T b = sin( toRadians( ax ) ); 00414 T c = cos( toRadians( ay ) ); 00415 T d = sin( toRadians( ay ) ); 00416 T e = cos( toRadians( az ) ); 00417 T f = sin( toRadians( az ) ); 00418 T nx = c*e*x - c*f*y + d*z; 00419 T ny = ( a*f + b*d*e ) * x + (a*e - b*d*f) * y - b*c*z; 00420 T nz = ( b*f - a*d*e ) * x + (a*d*f + b*e) * y + a*c*z; 00421 x = nx; 00422 y = ny; 00423 z = nz; 00424 } 00425 00426 Vec3<T> lerp( T fact, const Vec3<T> &rhs ) const 00427 { 00428 return (*this) + (rhs - (*this)) * fact; 00429 } 00430 00431 void lerpEq( T fact, const Vec3<T> &rhs ) 00432 { 00433 x = x + ( rhs.x - x ) * fact; y = y + ( rhs.y - y ) * fact; z = z + ( rhs.z - z ) * fact; 00434 } 00435 00436 static Vec3<T> max() 00437 { 00438 return Vec3<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00439 } 00440 00441 static Vec3<T> zero() 00442 { 00443 return Vec3<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00444 } 00445 00446 static Vec3<T> one() 00447 { 00448 return Vec3<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00449 } 00450 00451 Vec3<T> slerp( T fact, const Vec3<T> &r ) const 00452 { 00453 T cosAlpha, alpha, sinAlpha; 00454 T t1, t2; 00455 Vec3<T> result; 00456 00457 // get cosine of angle between vectors (-1 -> 1) 00458 cosAlpha = this->dot( r ); 00459 00460 // get angle (0 -> pi) 00461 alpha = math<T>::acos( cosAlpha ); 00462 00463 // get sine of angle between vectors (0 -> 1) 00464 sinAlpha = math<T>::sin( alpha ); 00465 00466 // this breaks down when sinAlpha = 0, i.e. alpha = 0 or pi 00467 t1 = math<T>::sin( ((T)1 - fact) * alpha) / sinAlpha; 00468 t2 = math<T>::sin( fact * alpha ) / sinAlpha; 00469 00470 // interpolate src vectors 00471 return *this * t1 + r * t2; 00472 } 00473 00474 // derived from but not equivalent to Quaternion::squad 00475 Vec3<T> squad( T t, const Vec3<T> &tangentA, const Vec3<T> &tangentB, const Vec3<T> &end ) 00476 { 00477 Vec3<T> r1 = this->slerp( t, end ); 00478 Vec3<T> r2 = tangentA.slerp( t, tangentB ); 00479 return r1.slerp( 2 * t * (1-t), r2 ); 00480 } 00481 00482 operator T*(){ return (T*) this; } 00483 operator const T*() const { return (const T*) this; } 00484 00485 friend std::ostream& operator<<( std::ostream& lhs, const Vec3<T> rhs ) 00486 { 00487 lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "]"; 00488 return lhs; 00489 } 00490 00491 static Vec3<T> xAxis() { return Vec3<T>( 1, 0, 0 ); } 00492 static Vec3<T> yAxis() { return Vec3<T>( 0, 1, 0 ); } 00493 static Vec3<T> zAxis() { return Vec3<T>( 0, 0, 1 ); } 00494 }; 00495 00496 template <class T> 00497 class Vec4{ 00498 public: 00499 T x,y,z,w; 00500 00501 typedef T TYPE; 00502 static const int DIM = 4; 00503 00504 Vec4() 00505 : x( 0 ), y( 0 ), z( 0 ), w( 0 ) 00506 {} 00507 Vec4( T nx, T ny, T nz, T nw ) 00508 : x( nx ), y( ny ), z( nz ), w( nw ) 00509 {} 00510 Vec4( const Vec3<T>& src, T aW ) 00511 : x( src.x ), y( src.y ), z( src.z ), w( aW ) 00512 {} 00513 Vec4( const Vec4<T>& src ) 00514 : x( src.x ), y( src.y ), z( src.z ), w( src.w ) 00515 {} 00516 template<typename FromT> 00517 Vec4( const Vec4<FromT>& src ) 00518 : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ),w( static_cast<T>( src.w ) ) 00519 {} 00520 explicit Vec4( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ), w( d[3] ) {} 00521 00522 Vec4<T>& operator=( const Vec4<T>& rhs ) 00523 { 00524 x = rhs.x; y = rhs.y; z = rhs.z; w = rhs.w; 00525 return *this; 00526 } 00527 00528 template<typename FromT> 00529 Vec4<T>& operator=( const Vec4<FromT>& rhs ) 00530 { 00531 x = static_cast<T>(rhs.x); y = static_cast<T>(rhs.y); z = static_cast<T>(rhs.z); w = static_cast<T>(rhs.w); 00532 return *this; 00533 } 00534 00535 T& operator[]( int n ) 00536 { 00537 assert( n >= 0 && n <= 3 ); 00538 return (&x)[n]; 00539 } 00540 00541 const T& operator[]( int n ) const 00542 { 00543 assert( n >= 0 && n <= 3 ); 00544 return (&x)[n]; 00545 } 00546 00547 const Vec4<T> operator+( const Vec4<T>& rhs ) const { return Vec4<T>( x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w ); } 00548 const Vec4<T> operator-( const Vec4<T>& rhs ) const { return Vec4<T>( x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w ); } 00549 const Vec4<T> operator*( const Vec4<T>& rhs ) const { return Vec4<T>( x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w ); } 00550 const Vec4<T> operator/( const Vec4<T>& rhs ) const { return Vec4<T>( x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w ); } 00551 Vec4<T>& operator+=( const Vec4<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; } 00552 Vec4<T>& operator-=( const Vec4<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; } 00553 Vec4<T>& operator*=( const Vec4<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; w *= rhs.w; return *this; } 00554 Vec4<T>& operator/=( const Vec4<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; w /= rhs.w; return *this; } 00555 const Vec4<T> operator/( T rhs ) const { return Vec4<T>( x / rhs, y / rhs, z / rhs, w / rhs ); } 00556 Vec4<T>& operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; w += rhs; return *this; } 00557 Vec4<T>& operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; w -= rhs; return * this; } 00558 Vec4<T>& operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; w *= rhs; return * this; } 00559 Vec4<T>& operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; w /= rhs; return * this; } 00560 00561 Vec4<T> operator-() const { return Vec4<T>( -x, -y, -z, -w ); } // unary negation 00562 00563 bool operator==( const Vec4<T>& rhs ) const 00564 { 00565 return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ) && ( w == rhs.w ); 00566 } 00567 00568 bool operator!=( const Vec4<T>& rhs ) const { return ! (*this == rhs); } 00569 00570 T length() const 00571 { 00572 return (T)std::sqrt(x * x + y * y + z * z + w * w); 00573 } 00574 00575 void normalize() 00576 { 00577 T invS = ((T)1) / length(); 00578 x *= invS; 00579 y *= invS; 00580 z *= invS; 00581 w *= invS; 00582 } 00583 00584 // tests for zero-length 00585 void safeNormalize() 00586 { 00587 T s = lengthSquared(); 00588 if( s > 0 ) { 00589 T invS = ((T)1) / math<T>::sqrt( s ); 00590 x *= invS; 00591 y *= invS; 00592 z *= invS; 00593 w *= invS; 00594 } 00595 } 00596 00597 T lengthSquared() const 00598 { 00599 return x * x + y * y + z * z + w * w; 00600 } 00601 00602 Vec4<T> lerp( T fact, const Vec4<T>& r ) const 00603 { 00604 return (*this) + ( r - (*this) ) * fact; 00605 } 00606 00607 static Vec4<T> max() 00608 { 00609 return Vec4<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00610 } 00611 00612 static Vec4<T> zero() 00613 { 00614 return Vec4<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00615 } 00616 00617 static Vec4<T> one() 00618 { 00619 return Vec4<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00620 } 00621 00622 operator T*(){ return (T*) this; } 00623 operator const T*() const { return (const T*) this; } 00624 00625 friend std::ostream& operator<<( std::ostream& lhs, const Vec4<T>& rhs ) 00626 { 00627 lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "," << rhs.w << "]"; 00628 return lhs; 00629 } 00630 00631 static Vec4<T> xAxis() { return Vec4<T>( 1, 0, 0, 0 ); } 00632 static Vec4<T> yAxis() { return Vec4<T>( 0, 1, 0, 0 ); } 00633 static Vec4<T> zAxis() { return Vec4<T>( 0, 0, 1, 0 ); } 00634 static Vec4<T> wAxis() { return Vec4<T>( 0, 0, 0, 1 ); } 00635 }; 00636 00637 template<typename T,typename Y> inline Vec2<T> operator *( Y s, const Vec2<T> &v ) { return Vec2<T>( v.x * s, v.y * s ); } 00638 template<typename T,typename Y> inline Vec2<T> operator *( const Vec2<T> &v, Y s ) { return Vec2<T>( v.x * s, v.y * s ); } 00639 template<typename T,typename Y> inline Vec3<T> operator *( Y s, const Vec3<T> &v ) { return Vec3<T>( v.x * s, v.y * s, v.z * s ); } 00640 template<typename T,typename Y> inline Vec3<T> operator *( const Vec3<T> &v, Y s ) { return Vec3<T>( v.x * s, v.y * s, v.z * s ); } 00641 template<typename T,typename Y> inline Vec4<T> operator *( Y s, const Vec4<T> &v ) { return Vec4<T>( v.x * s, v.y * s, v.z * s, v.w * s ); } 00642 template<typename T,typename Y> inline Vec4<T> operator *( const Vec4<T> &v, Y s ) { return Vec4<T>( v.x * s, v.y * s, v.z * s, v.w * s ); } 00643 00644 00645 typedef Vec2<float> Vec2f; 00646 typedef Vec2<double> Vec2d; 00647 typedef Vec3<float> Vec3f; 00648 typedef Vec3<double> Vec3d; 00649 typedef Vec4<float> Vec4f; 00650 typedef Vec4<double> Vec4d; 00651 typedef Vec2<int> Vec2i; 00652 00653 } // namespace cinder