Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

include/cinder/Vector.h

Go to the documentation of this file.
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