Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreVector3.h

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #ifndef __Vector3_H__
00026 #define __Vector3_H__
00027 
00028 #include "OgrePrerequisites.h"
00029 #include "OgreMath.h"
00030 #include "OgreQuaternion.h"
00031 
00032 namespace Ogre
00033 {
00034 
00042     class _OgreExport Vector3
00043     {
00044     public:
00045         union {
00046             struct {
00047                 Real x, y, z;        
00048             };
00049             Real val[3];
00050         };
00051 
00052     public:
00053         inline Vector3()
00054         {
00055         }
00056 
00057         inline Vector3( Real fX, Real fY, Real fZ ) 
00058             : x( fX ), y( fY ), z( fZ )
00059         {
00060         }
00061 
00062         inline Vector3( Real afCoordinate[3] )
00063             : x( afCoordinate[0] ),
00064               y( afCoordinate[1] ),
00065               z( afCoordinate[2] )
00066         {
00067         }
00068 
00069         inline Vector3( int afCoordinate[3] )
00070         {
00071             x = (Real)afCoordinate[0];
00072             y = (Real)afCoordinate[1];
00073             z = (Real)afCoordinate[2];
00074         }
00075 
00076         inline Vector3( const Real* const r )
00077             : x( r[0] ), y( r[1] ), z( r[2] )
00078         {
00079         }
00080 
00081         inline Vector3( const Vector3& rkVector )
00082             : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
00083         {
00084         }
00085 
00086         inline Real operator [] ( unsigned i ) const
00087         {
00088             assert( i < 3 );
00089 
00090             return *(&x+i);
00091         }
00092 
00093         inline Real& operator [] ( unsigned i )
00094         {
00095             assert( i < 3 );
00096 
00097             return *(&x+i);
00098         }
00099 
00104         inline Vector3& operator = ( const Vector3& rkVector )
00105         {
00106             x = rkVector.x;
00107             y = rkVector.y;
00108             z = rkVector.z;            
00109 
00110             return *this;
00111         }
00112 
00113         inline bool operator == ( const Vector3& rkVector ) const
00114         {
00115             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00116         }
00117 
00118         inline bool operator != ( const Vector3& rkVector ) const
00119         {
00120             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00121         }
00122 
00123         // arithmetic operations
00124         inline Vector3 operator + ( const Vector3& rkVector ) const
00125         {
00126             Vector3 kSum;
00127 
00128             kSum.x = x + rkVector.x;
00129             kSum.y = y + rkVector.y;
00130             kSum.z = z + rkVector.z;
00131 
00132             return kSum;
00133         }
00134 
00135         inline Vector3 operator - ( const Vector3& rkVector ) const
00136         {
00137             Vector3 kDiff;
00138 
00139             kDiff.x = x - rkVector.x;
00140             kDiff.y = y - rkVector.y;
00141             kDiff.z = z - rkVector.z;
00142 
00143             return kDiff;
00144         }
00145 
00146         inline Vector3 operator * ( Real fScalar ) const
00147         {
00148             Vector3 kProd;
00149 
00150             kProd.x = fScalar*x;
00151             kProd.y = fScalar*y;
00152             kProd.z = fScalar*z;
00153 
00154             return kProd;
00155         }
00156 
00157         inline Vector3 operator * ( const Vector3& rhs) const
00158         {
00159             Vector3 kProd;
00160 
00161             kProd.x = rhs.x * x;
00162             kProd.y = rhs.y * y;
00163             kProd.z = rhs.z * z;
00164 
00165             return kProd;
00166         }
00167 
00168         inline Vector3 operator / ( Real fScalar ) const
00169         {
00170             assert( fScalar != 0.0 );
00171 
00172             Vector3 kDiv;
00173 
00174             Real fInv = 1.0 / fScalar;
00175             kDiv.x = x * fInv;
00176             kDiv.y = y * fInv;
00177             kDiv.z = z * fInv;
00178 
00179             return kDiv;
00180         }
00181 
00182         inline Vector3 operator - () const
00183         {
00184             Vector3 kNeg;
00185 
00186             kNeg.x = -x;
00187             kNeg.y = -y;
00188             kNeg.z = -z;
00189 
00190             return kNeg;
00191         }
00192 
00193         inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
00194         {
00195             Vector3 kProd;
00196 
00197             kProd.x = fScalar * rkVector.x;
00198             kProd.y = fScalar * rkVector.y;
00199             kProd.z = fScalar * rkVector.z;
00200 
00201             return kProd;
00202         }
00203 
00204         // arithmetic updates
00205         inline Vector3& operator += ( const Vector3& rkVector )
00206         {
00207             x += rkVector.x;
00208             y += rkVector.y;
00209             z += rkVector.z;
00210 
00211             return *this;
00212         }
00213 
00214         inline Vector3& operator -= ( const Vector3& rkVector )
00215         {
00216             x -= rkVector.x;
00217             y -= rkVector.y;
00218             z -= rkVector.z;
00219 
00220             return *this;
00221         }
00222 
00223         inline Vector3& operator *= ( Real fScalar )
00224         {
00225             x *= fScalar;
00226             y *= fScalar;
00227             z *= fScalar;
00228             return *this;
00229         }
00230 
00231         inline Vector3& operator /= ( Real fScalar )
00232         {
00233             assert( fScalar != 0.0 );
00234 
00235             Real fInv = 1.0 / fScalar;
00236 
00237             x *= fInv;
00238             y *= fInv;
00239             z *= fInv;
00240 
00241             return *this;
00242         }
00243 
00251         inline Real length () const
00252         {
00253             return Math::Sqrt( x * x + y * y + z * z );
00254         }
00255 
00266         inline Real squaredLength () const
00267         {
00268             return x * x + y * y + z * z;
00269         }
00270 
00285         inline Real dotProduct(const Vector3& vec) const
00286         {
00287             return x * vec.x + y * vec.y + z * vec.z;
00288         }
00289 
00299         inline Real normalise()
00300         {
00301             Real fLength = Math::Sqrt( x * x + y * y + z * z );
00302 
00303             // Will also work for zero-sized vectors, but will change nothing
00304             if ( fLength > 1e-06 )
00305             {
00306                 Real fInvLength = 1.0 / fLength;
00307                 x *= fInvLength;
00308                 y *= fInvLength;
00309                 z *= fInvLength;
00310             }
00311 
00312             return fLength;
00313         }
00314 
00342         inline Vector3 crossProduct( const Vector3& rkVector ) const
00343         {
00344             Vector3 kCross;
00345 
00346             kCross.x = y * rkVector.z - z * rkVector.y;
00347             kCross.y = z * rkVector.x - x * rkVector.z;
00348             kCross.z = x * rkVector.y - y * rkVector.x;
00349 
00350             return kCross;
00351         }
00352 
00356         inline Vector3 midPoint( const Vector3& vec ) const
00357         {
00358             return Vector3( 
00359                 ( x + vec.x ) * 0.5, 
00360                 ( y + vec.y ) * 0.5, 
00361                 ( z + vec.z ) * 0.5 );
00362         }
00363 
00367         inline bool operator < ( const Vector3& rhs ) const
00368         {
00369             if( x < rhs.x && y < rhs.y && z < rhs.z )
00370                 return true;
00371             return false;
00372         }
00373 
00377         inline bool operator > ( const Vector3& rhs ) const
00378         {
00379             if( x > rhs.x && y > rhs.y && z > rhs.z )
00380                 return true;
00381             return false;
00382         }
00383 
00391         inline void makeFloor( const Vector3& cmp )
00392         {
00393             if( cmp.x < x ) x = cmp.x;
00394             if( cmp.y < y ) y = cmp.y;
00395             if( cmp.z < z ) z = cmp.z;
00396         }
00397 
00405         inline void makeCeil( const Vector3& cmp )
00406         {
00407             if( cmp.x > x ) x = cmp.x;
00408             if( cmp.y > y ) y = cmp.y;
00409             if( cmp.z > z ) z = cmp.z;
00410         }
00411 
00419         inline Vector3 perpendicular(void) const
00420         {
00421             static const Real fSquareZero = 1e-06 * 1e-06;
00422 
00423             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00424 
00425             // Check length
00426             if( perp.squaredLength() < fSquareZero )
00427             {
00428                 /* This vector is the Y axis multiplied by a scalar, so we have 
00429                    to use another axis.
00430                 */
00431                 perp = this->crossProduct( Vector3::UNIT_Y );
00432             }
00433 
00434             return perp;
00435         }
00455         inline Vector3 randomDeviant(
00456             Real angle, 
00457             const Vector3& up = Vector3::ZERO ) const
00458         {
00459             Vector3 newUp;
00460 
00461             if (up == Vector3::ZERO)
00462             {
00463                 // Generate an up vector
00464                 newUp = this->perpendicular();
00465             }
00466             else
00467             {
00468                 newUp = up;
00469             }
00470 
00471             // Rotate up vector by random amount around this
00472             Quaternion q;
00473             q.FromAngleAxis( Math::UnitRandom() * Math::TWO_PI, *this );
00474             newUp = q * newUp;
00475 
00476             // Finally rotate this by given angle around randomised up
00477             q.FromAngleAxis( angle, newUp );
00478             return q * (*this);
00479         }
00480 
00487         Quaternion getRotationTo(const Vector3& dest) const
00488         {
00489             // Based on Stan Melax's article in Game Programming Gems
00490             Quaternion q;
00491             // Copy, since cannot modify local
00492             Vector3 v0 = *this;
00493             Vector3 v1 = dest;
00494             v0.normalise();
00495             v1.normalise();
00496 
00497             Vector3 c = v0.crossProduct(v1);
00498 
00499             // NB if the crossProduct approaches zero, we get unstable because ANY axis will do
00500             // when v0 == -v1
00501             Real d = v0.dotProduct(v1);
00502             // If dot == 1, vectors are the same
00503             if (d >= 1.0f)
00504             {
00505                 return Quaternion::IDENTITY;
00506             }
00507             Real s = Math::Sqrt( (1+d)*2 );
00508             Real invs = 1 / s;
00509 
00510 
00511             q.x = c.x * invs;
00512             q.y = c.y * invs;
00513             q.z = c.z * invs;
00514             q.w = s * 0.5;
00515             return q;
00516         }
00517 
00519         inline bool isZeroLength(void) const
00520         {
00521             Real sqlen = (x * x) + (y * y) + (z * z);
00522             return (sqlen < (1e-06 * 1e-06));
00523 
00524         }
00525 
00528         inline Vector3 normalisedCopy(void) const
00529         {
00530             Vector3 ret = *this;
00531             ret.normalise();
00532             return ret;
00533         }
00534 
00538         inline Vector3 reflect(const Vector3& normal)
00539         {
00540             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00541         }
00542 
00543         // special points
00544         static const Vector3 ZERO;
00545         static const Vector3 UNIT_X;
00546         static const Vector3 UNIT_Y;
00547         static const Vector3 UNIT_Z;
00548         static const Vector3 UNIT_SCALE;
00549 
00552         inline _OgreExport friend std::ostream& operator <<
00553             ( std::ostream& o, const Vector3& v )
00554         {
00555             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00556             return o;
00557         }
00558     };
00559 
00560 }
00561 #endif

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:31 2004