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