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 00186 void limit( T maxLength ) 00187 { 00188 T lengthSquared = x * x + y * y; 00189 00190 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00191 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00192 x *= ratio; 00193 y *= ratio; 00194 } 00195 } 00196 00198 Vec2<T> limited( T maxLength ) const 00199 { 00200 T lengthSquared = x * x + y * y; 00201 00202 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00203 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00204 return Vec2<T>( x * ratio, y * ratio ); 00205 } 00206 else 00207 return *this; 00208 } 00209 00210 void invert() 00211 { 00212 x - -x; 00213 y = -y; 00214 } 00215 00216 Vec2<T> inverse() const 00217 { 00218 return Vec2<T>( -x, -y ); 00219 } 00220 00221 Vec2<T> lerp( T fact, const Vec2<T>& r ) const 00222 { 00223 return (*this) + ( r - (*this) ) * fact; 00224 } 00225 00226 static Vec2<T> max() 00227 { 00228 return Vec2<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00229 } 00230 00231 static Vec2<T> zero() 00232 { 00233 return Vec2<T>( static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00234 } 00235 00236 static Vec2<T> one() 00237 { 00238 return Vec2<T>( static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00239 } 00240 00241 operator T*(){ return (T*) this; } 00242 operator const T*() const { return (const T*) this; } 00243 00244 friend std::ostream& operator<<( std::ostream& lhs, const Vec2<T>& rhs ) 00245 { 00246 lhs << "[" << rhs.x << "," << rhs.y << "]"; 00247 return lhs; 00248 } 00249 00250 static Vec2<T> xAxis() { return Vec2<T>( 1, 0 ); } 00251 static Vec2<T> yAxis() { return Vec2<T>( 0, 1 ); } 00252 }; 00253 00254 template<typename T> 00255 class Vec3 00256 { 00257 public: 00258 T x,y,z; 00259 00260 typedef T TYPE; 00261 static const int DIM = 3; 00262 00263 Vec3() {} 00264 Vec3( T nx, T ny, T nz ) 00265 : x( nx ), y( ny ), z( nz ) 00266 {} 00267 Vec3( const Vec3<T> &src ) 00268 : x( src.x ), y( src.y ), z( src.z ) 00269 {} 00270 Vec3( const Vec2<T> &v2, T aZ ) 00271 : x( v2.x ), y ( v2.y ), z( aZ ) 00272 {} 00273 explicit Vec3( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ) {} 00274 template<typename FromT> 00275 Vec3( const Vec3<FromT> &src ) 00276 : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ) 00277 {} 00278 template<typename Y> 00279 explicit Vec3( const Y &v ) 00280 : 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 ) ) 00281 { 00282 } 00283 00284 void set( T ax, T ay, T az ) 00285 { 00286 x = ax; y = ay; z = az; 00287 } 00288 00289 void set( const Vec3<T> &rhs ) 00290 { 00291 x = rhs.x; y = rhs.y; z = rhs.z; 00292 } 00293 00294 Vec3<T>& operator=( const Vec3<T> &rhs ) 00295 { 00296 x = rhs.x; 00297 y = rhs.y; 00298 z = rhs.z; 00299 return * this; 00300 } 00301 00302 template<typename FromT> 00303 Vec3<T>& operator=( const Vec3<FromT> &rhs ) 00304 { 00305 x = static_cast<T>( rhs.x ); 00306 y = static_cast<T>( rhs.y ); 00307 z = static_cast<T>( rhs.z ); 00308 return * this; 00309 } 00310 00311 T& operator[]( int n ) 00312 { 00313 assert( n >= 0 && n <= 2 ); 00314 return (&x)[n]; 00315 } 00316 00317 const T& operator[]( int n ) const 00318 { 00319 assert( n >= 0 && n <= 2 ); 00320 return (&x)[n]; 00321 } 00322 00323 const Vec3<T> operator+( const Vec3<T>& rhs ) const { return Vec3<T>( x + rhs.x, y + rhs.y, z + rhs.z ); } 00324 const Vec3<T> operator-( const Vec3<T>& rhs ) const { return Vec3<T>( x - rhs.x, y - rhs.y, z - rhs.z ); } 00325 const Vec3<T> operator*( const Vec3<T>& rhs ) const { return Vec3<T>( x * rhs.x, y * rhs.y, z * rhs.z ); } 00326 const Vec3<T> operator/( const Vec3<T>& rhs ) const { return Vec3<T>( x / rhs.x, y / rhs.y, z / rhs.z ); } 00327 Vec3<T>& operator+=( const Vec3<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } 00328 Vec3<T>& operator-=( const Vec3<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } 00329 Vec3<T>& operator*=( const Vec3<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this; } 00330 Vec3<T>& operator/=( const Vec3<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; return *this; } 00331 const Vec3<T> operator/( T rhs ) const { T invRhs = static_cast<T>( 1.0 ) / rhs; return Vec3<T>( x * invRhs, y * invRhs, z * invRhs ); } 00332 Vec3<T>& operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; return *this; } 00333 Vec3<T>& operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; return *this; } 00334 Vec3<T>& operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; return *this; } 00335 Vec3<T>& operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; return *this; } 00336 00337 Vec3<T> operator-() const { return Vec3<T>( -x, -y, -z ); } // unary negation 00338 00339 bool operator==( const Vec3<T>& rhs ) const 00340 { 00341 return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ); 00342 } 00343 00344 bool operator!=( const Vec3<T>& rhs ) const 00345 { 00346 return !( *this == rhs ); 00347 } 00348 00349 T dot( const Vec3<T> &rhs ) const 00350 { 00351 return x*rhs.x + y*rhs.y + z*rhs.z; 00352 } 00353 00354 Vec3<T> cross( const Vec3<T> &rhs ) const 00355 { 00356 return Vec3<T>( y * rhs.z - rhs.y * z, z * rhs.x - rhs.z * x, x * rhs.y - rhs.x * y ); 00357 } 00358 00359 T distance( const Vec3<T> &rhs ) const 00360 { 00361 return ( *this - rhs ).length(); 00362 } 00363 00364 T distanceSquared( const Vec3<T> &rhs ) const 00365 { 00366 return ( *this - rhs ).lengthSquared(); 00367 } 00368 00369 T length() const 00370 { 00371 return (T)std::sqrt( x*x + y*y + z*z ); 00372 } 00373 00374 T lengthSquared() const 00375 { 00376 return x*x + y*y + z*z; 00377 } 00378 00380 void limit( T maxLength ) 00381 { 00382 T lengthSquared = x * x + y * y + z * z; 00383 00384 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00385 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00386 x *= ratio; 00387 y *= ratio; 00388 z *= ratio; 00389 } 00390 } 00391 00393 Vec3<T> limited( T maxLength ) const 00394 { 00395 T lengthSquared = x * x + y * y + z * z; 00396 00397 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00398 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00399 return Vec3<T>( x * ratio, y * ratio, z * ratio ); 00400 } 00401 else 00402 return *this; 00403 } 00404 00405 void invert() 00406 { 00407 x - -x; y = -y; z = -z; 00408 } 00409 00410 Vec3<T> inverse() const 00411 { 00412 return Vec3<T>( -x, -y, -z ); 00413 } 00414 00415 void normalize() 00416 { 00417 T invS = ((T)1) / length(); 00418 x *= invS; 00419 y *= invS; 00420 z *= invS; 00421 } 00422 00423 Vec3<T> normalized() const 00424 { 00425 T invS = ((T)1) / length(); 00426 return Vec3<T>( x * invS, y * invS, z * invS ); 00427 } 00428 00429 // tests for zero-length 00430 void safeNormalize() 00431 { 00432 T s = lengthSquared(); 00433 if( s > 0 ) { 00434 T invS = ((T)1) / math<T>::sqrt( s ); 00435 x *= invS; 00436 y *= invS; 00437 z *= invS; 00438 } 00439 } 00440 00441 Vec3<T> safeNormalized() 00442 { 00443 T s = lengthSquared(); 00444 if( s > 0 ) { 00445 float invS = ((T)1) / math<T>::sqrt( s ); 00446 return Vec3<T>( x * invS, y * invS, z * invS ); 00447 } 00448 else 00449 return *this; 00450 } 00451 00452 Vec3<T> randomOrthogonal() const 00453 { 00454 if( dot( Vec3<T>::xAxis() ) >= (T)0.01 ) { 00455 return cross( Vec3<T>::xAxis() ); 00456 } 00457 else 00458 return cross( Vec3<T>::yAxis() ); 00459 } 00460 00461 void rotate( T ax, T ay, T az ) 00462 { 00463 T a = cos( toRadians( ax ) ); 00464 T b = sin( toRadians( ax ) ); 00465 T c = cos( toRadians( ay ) ); 00466 T d = sin( toRadians( ay ) ); 00467 T e = cos( toRadians( az ) ); 00468 T f = sin( toRadians( az ) ); 00469 T nx = c*e*x - c*f*y + d*z; 00470 T ny = ( a*f + b*d*e ) * x + (a*e - b*d*f) * y - b*c*z; 00471 T nz = ( b*f - a*d*e ) * x + (a*d*f + b*e) * y + a*c*z; 00472 x = nx; 00473 y = ny; 00474 z = nz; 00475 } 00476 00477 Vec3<T> lerp( T fact, const Vec3<T> &rhs ) const 00478 { 00479 return (*this) + (rhs - (*this)) * fact; 00480 } 00481 00482 void lerpEq( T fact, const Vec3<T> &rhs ) 00483 { 00484 x = x + ( rhs.x - x ) * fact; y = y + ( rhs.y - y ) * fact; z = z + ( rhs.z - z ) * fact; 00485 } 00486 00487 static Vec3<T> max() 00488 { 00489 return Vec3<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00490 } 00491 00492 static Vec3<T> zero() 00493 { 00494 return Vec3<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00495 } 00496 00497 static Vec3<T> one() 00498 { 00499 return Vec3<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00500 } 00501 00502 Vec3<T> slerp( T fact, const Vec3<T> &r ) const 00503 { 00504 T cosAlpha, alpha, sinAlpha; 00505 T t1, t2; 00506 Vec3<T> result; 00507 00508 // get cosine of angle between vectors (-1 -> 1) 00509 cosAlpha = this->dot( r ); 00510 00511 // get angle (0 -> pi) 00512 alpha = math<T>::acos( cosAlpha ); 00513 00514 // get sine of angle between vectors (0 -> 1) 00515 sinAlpha = math<T>::sin( alpha ); 00516 00517 // this breaks down when sinAlpha = 0, i.e. alpha = 0 or pi 00518 t1 = math<T>::sin( ((T)1 - fact) * alpha) / sinAlpha; 00519 t2 = math<T>::sin( fact * alpha ) / sinAlpha; 00520 00521 // interpolate src vectors 00522 return *this * t1 + r * t2; 00523 } 00524 00525 // derived from but not equivalent to Quaternion::squad 00526 Vec3<T> squad( T t, const Vec3<T> &tangentA, const Vec3<T> &tangentB, const Vec3<T> &end ) 00527 { 00528 Vec3<T> r1 = this->slerp( t, end ); 00529 Vec3<T> r2 = tangentA.slerp( t, tangentB ); 00530 return r1.slerp( 2 * t * (1-t), r2 ); 00531 } 00532 00533 operator T*(){ return (T*) this; } 00534 operator const T*() const { return (const T*) this; } 00535 00536 friend std::ostream& operator<<( std::ostream& lhs, const Vec3<T> rhs ) 00537 { 00538 lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "]"; 00539 return lhs; 00540 } 00541 00542 static Vec3<T> xAxis() { return Vec3<T>( 1, 0, 0 ); } 00543 static Vec3<T> yAxis() { return Vec3<T>( 0, 1, 0 ); } 00544 static Vec3<T> zAxis() { return Vec3<T>( 0, 0, 1 ); } 00545 }; 00546 00547 template <class T> 00548 class Vec4{ 00549 public: 00550 T x,y,z,w; 00551 00552 typedef T TYPE; 00553 static const int DIM = 4; 00554 00555 Vec4() 00556 : x( 0 ), y( 0 ), z( 0 ), w( 0 ) 00557 {} 00558 Vec4( T nx, T ny, T nz, T nw ) 00559 : x( nx ), y( ny ), z( nz ), w( nw ) 00560 {} 00561 Vec4( const Vec3<T>& src, T aW ) 00562 : x( src.x ), y( src.y ), z( src.z ), w( aW ) 00563 {} 00564 Vec4( const Vec4<T>& src ) 00565 : x( src.x ), y( src.y ), z( src.z ), w( src.w ) 00566 {} 00567 template<typename FromT> 00568 Vec4( const Vec4<FromT>& src ) 00569 : x( static_cast<T>( src.x ) ), y( static_cast<T>( src.y ) ), z( static_cast<T>( src.z ) ),w( static_cast<T>( src.w ) ) 00570 {} 00571 explicit Vec4( const T *d ) : x( d[0] ), y( d[1] ), z( d[2] ), w( d[3] ) {} 00572 00573 Vec4<T>& operator=( const Vec4<T>& rhs ) 00574 { 00575 x = rhs.x; y = rhs.y; z = rhs.z; w = rhs.w; 00576 return *this; 00577 } 00578 00579 template<typename FromT> 00580 Vec4<T>& operator=( const Vec4<FromT>& rhs ) 00581 { 00582 x = static_cast<T>(rhs.x); y = static_cast<T>(rhs.y); z = static_cast<T>(rhs.z); w = static_cast<T>(rhs.w); 00583 return *this; 00584 } 00585 00586 T& operator[]( int n ) 00587 { 00588 assert( n >= 0 && n <= 3 ); 00589 return (&x)[n]; 00590 } 00591 00592 const T& operator[]( int n ) const 00593 { 00594 assert( n >= 0 && n <= 3 ); 00595 return (&x)[n]; 00596 } 00597 00598 const Vec4<T> operator+( const Vec4<T>& rhs ) const { return Vec4<T>( x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w ); } 00599 const Vec4<T> operator-( const Vec4<T>& rhs ) const { return Vec4<T>( x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w ); } 00600 const Vec4<T> operator*( const Vec4<T>& rhs ) const { return Vec4<T>( x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w ); } 00601 const Vec4<T> operator/( const Vec4<T>& rhs ) const { return Vec4<T>( x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w ); } 00602 Vec4<T>& operator+=( const Vec4<T>& rhs ) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; } 00603 Vec4<T>& operator-=( const Vec4<T>& rhs ) { x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; } 00604 Vec4<T>& operator*=( const Vec4<T>& rhs ) { x *= rhs.x; y *= rhs.y; z *= rhs.z; w *= rhs.w; return *this; } 00605 Vec4<T>& operator/=( const Vec4<T>& rhs ) { x /= rhs.x; y /= rhs.y; z /= rhs.z; w /= rhs.w; return *this; } 00606 const Vec4<T> operator/( T rhs ) const { return Vec4<T>( x / rhs, y / rhs, z / rhs, w / rhs ); } 00607 Vec4<T>& operator+=( T rhs ) { x += rhs; y += rhs; z += rhs; w += rhs; return *this; } 00608 Vec4<T>& operator-=( T rhs ) { x -= rhs; y -= rhs; z -= rhs; w -= rhs; return * this; } 00609 Vec4<T>& operator*=( T rhs ) { x *= rhs; y *= rhs; z *= rhs; w *= rhs; return * this; } 00610 Vec4<T>& operator/=( T rhs ) { x /= rhs; y /= rhs; z /= rhs; w /= rhs; return * this; } 00611 00612 Vec4<T> operator-() const { return Vec4<T>( -x, -y, -z, -w ); } // unary negation 00613 00614 bool operator==( const Vec4<T>& rhs ) const 00615 { 00616 return ( x == rhs.x ) && ( y == rhs.y ) && ( z == rhs.z ) && ( w == rhs.w ); 00617 } 00618 00619 bool operator!=( const Vec4<T>& rhs ) const { return ! (*this == rhs); } 00620 00621 T length() const 00622 { 00623 return (T)std::sqrt(x * x + y * y + z * z + w * w); 00624 } 00625 00626 void normalize() 00627 { 00628 T invS = ((T)1) / length(); 00629 x *= invS; 00630 y *= invS; 00631 z *= invS; 00632 w *= invS; 00633 } 00634 00635 // tests for zero-length 00636 void safeNormalize() 00637 { 00638 T s = lengthSquared(); 00639 if( s > 0 ) { 00640 T invS = ((T)1) / math<T>::sqrt( s ); 00641 x *= invS; 00642 y *= invS; 00643 z *= invS; 00644 w *= invS; 00645 } 00646 } 00647 00648 T lengthSquared() const 00649 { 00650 return x * x + y * y + z * z + w * w; 00651 } 00652 00654 void limit( T maxLength ) 00655 { 00656 T lengthSquared = x * x + y * y + z * z + w * w; 00657 00658 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00659 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00660 x *= ratio; 00661 y *= ratio; 00662 z *= ratio; 00663 w *= ratio; 00664 } 00665 } 00666 00668 Vec4<T> limited( T maxLength ) const 00669 { 00670 T lengthSquared = x * x + y * y + z * z + w * w; 00671 00672 if( ( lengthSquared > maxLength * maxLength ) && ( lengthSquared > 0 ) ) { 00673 T ratio = maxLength / math<T>::sqrt( lengthSquared ); 00674 return Vec4<T>( x * ratio, y * ratio, z * ratio, w * ratio ); 00675 } 00676 else 00677 return *this; 00678 } 00679 00680 void invert() 00681 { 00682 x - -x; y = -y; z = -z; w = -w; 00683 } 00684 00685 Vec4<T> inverse() const 00686 { 00687 return Vec3<T>( -x, -y, -z, -w ); 00688 } 00689 00690 00691 Vec4<T> lerp( T fact, const Vec4<T>& r ) const 00692 { 00693 return (*this) + ( r - (*this) ) * fact; 00694 } 00695 00696 static Vec4<T> max() 00697 { 00698 return Vec4<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00699 } 00700 00701 static Vec4<T> zero() 00702 { 00703 return Vec4<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00704 } 00705 00706 static Vec4<T> one() 00707 { 00708 return Vec4<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00709 } 00710 00711 operator T*(){ return (T*) this; } 00712 operator const T*() const { return (const T*) this; } 00713 00714 friend std::ostream& operator<<( std::ostream& lhs, const Vec4<T>& rhs ) 00715 { 00716 lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "," << rhs.w << "]"; 00717 return lhs; 00718 } 00719 00720 static Vec4<T> xAxis() { return Vec4<T>( 1, 0, 0, 0 ); } 00721 static Vec4<T> yAxis() { return Vec4<T>( 0, 1, 0, 0 ); } 00722 static Vec4<T> zAxis() { return Vec4<T>( 0, 0, 1, 0 ); } 00723 static Vec4<T> wAxis() { return Vec4<T>( 0, 0, 0, 1 ); } 00724 }; 00725 00726 template<typename T,typename Y> inline Vec2<T> operator *( Y s, const Vec2<T> &v ) { return Vec2<T>( v.x * s, v.y * s ); } 00727 template<typename T,typename Y> inline Vec2<T> operator *( const Vec2<T> &v, Y s ) { return Vec2<T>( v.x * s, v.y * s ); } 00728 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 ); } 00729 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 ); } 00730 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 ); } 00731 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 ); } 00732 00733 00734 typedef Vec2<float> Vec2f; 00735 typedef Vec2<double> Vec2d; 00736 typedef Vec3<float> Vec3f; 00737 typedef Vec3<double> Vec3d; 00738 typedef Vec4<float> Vec4f; 00739 typedef Vec4<double> Vec4d; 00740 typedef Vec2<int> Vec2i; 00741 00742 } // namespace cinder