# 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