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 (c) 2000-2006 Torus Knot Software Ltd
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 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef __Vector3_H__
00030 #define __Vector3_H__
00031 
00032 #include "OgrePrerequisites.h"
00033 #include "OgreMath.h"
00034 #include "OgreQuaternion.h"
00035 
00036 namespace Ogre
00037 {
00038 
00046     class _OgreExport Vector3
00047     {
00048     public:
00049         Real x, y, z;
00050 
00051     public:
00052         inline Vector3()
00053         {
00054         }
00055 
00056         inline Vector3( const Real fX, const Real fY, const Real fZ )
00057             : x( fX ), y( fY ), z( fZ )
00058         {
00059         }
00060 
00061         inline explicit Vector3( const Real afCoordinate[3] )
00062             : x( afCoordinate[0] ),
00063               y( afCoordinate[1] ),
00064               z( afCoordinate[2] )
00065         {
00066         }
00067 
00068         inline explicit Vector3( const int afCoordinate[3] )
00069         {
00070             x = (Real)afCoordinate[0];
00071             y = (Real)afCoordinate[1];
00072             z = (Real)afCoordinate[2];
00073         }
00074 
00075         inline explicit Vector3( Real* const r )
00076             : x( r[0] ), y( r[1] ), z( r[2] )
00077         {
00078         }
00079 
00080         inline explicit Vector3( const Real scaler )
00081             : x( scaler )
00082             , y( scaler )
00083             , z( scaler )
00084         {
00085         }
00086 
00087 
00088         inline Real operator [] ( const size_t i ) const
00089         {
00090             assert( i < 3 );
00091 
00092             return *(&x+i);
00093         }
00094 
00095         inline Real& operator [] ( const size_t i )
00096         {
00097             assert( i < 3 );
00098 
00099             return *(&x+i);
00100         }
00102         inline Real* ptr()
00103         {
00104             return &x;
00105         }
00107         inline const Real* ptr() const
00108         {
00109             return &x;
00110         }
00111 
00116         inline Vector3& operator = ( const Vector3& rkVector )
00117         {
00118             x = rkVector.x;
00119             y = rkVector.y;
00120             z = rkVector.z;
00121 
00122             return *this;
00123         }
00124 
00125         inline Vector3& operator = ( const Real fScaler )
00126         {
00127             x = fScaler;
00128             y = fScaler;
00129             z = fScaler;
00130 
00131             return *this;
00132         }
00133 
00134         inline bool operator == ( const Vector3& rkVector ) const
00135         {
00136             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00137         }
00138 
00139         inline bool operator != ( const Vector3& rkVector ) const
00140         {
00141             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00142         }
00143 
00144         // arithmetic operations
00145         inline Vector3 operator + ( const Vector3& rkVector ) const
00146         {
00147             return Vector3(
00148                 x + rkVector.x,
00149                 y + rkVector.y,
00150                 z + rkVector.z);
00151         }
00152 
00153         inline Vector3 operator - ( const Vector3& rkVector ) const
00154         {
00155             return Vector3(
00156                 x - rkVector.x,
00157                 y - rkVector.y,
00158                 z - rkVector.z);
00159         }
00160 
00161         inline Vector3 operator * ( const Real fScalar ) const
00162         {
00163             return Vector3(
00164                 x * fScalar,
00165                 y * fScalar,
00166                 z * fScalar);
00167         }
00168 
00169         inline Vector3 operator * ( const Vector3& rhs) const
00170         {
00171             return Vector3(
00172                 x * rhs.x,
00173                 y * rhs.y,
00174                 z * rhs.z);
00175         }
00176 
00177         inline Vector3 operator / ( const Real fScalar ) const
00178         {
00179             assert( fScalar != 0.0 );
00180 
00181             Real fInv = 1.0 / fScalar;
00182 
00183             return Vector3(
00184                 x * fInv,
00185                 y * fInv,
00186                 z * fInv);
00187         }
00188 
00189         inline Vector3 operator / ( const Vector3& rhs) const
00190         {
00191             return Vector3(
00192                 x / rhs.x,
00193                 y / rhs.y,
00194                 z / rhs.z);
00195         }
00196 
00197         inline const Vector3& operator + () const
00198         {
00199             return *this;
00200         }
00201 
00202         inline Vector3 operator - () const
00203         {
00204             return Vector3(-x, -y, -z);
00205         }
00206 
00207         // overloaded operators to help Vector3
00208         inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
00209         {
00210             return Vector3(
00211                 fScalar * rkVector.x,
00212                 fScalar * rkVector.y,
00213                 fScalar * rkVector.z);
00214         }
00215 
00216         inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
00217         {
00218             return Vector3(
00219                 fScalar / rkVector.x,
00220                 fScalar / rkVector.y,
00221                 fScalar / rkVector.z);
00222         }
00223 
00224         inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
00225         {
00226             return Vector3(
00227                 lhs.x + rhs,
00228                 lhs.y + rhs,
00229                 lhs.z + rhs);
00230         }
00231 
00232         inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
00233         {
00234             return Vector3(
00235                 lhs + rhs.x,
00236                 lhs + rhs.y,
00237                 lhs + rhs.z);
00238         }
00239 
00240         inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
00241         {
00242             return Vector3(
00243                 lhs.x - rhs,
00244                 lhs.y - rhs,
00245                 lhs.z - rhs);
00246         }
00247 
00248         inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
00249         {
00250             return Vector3(
00251                 lhs - rhs.x,
00252                 lhs - rhs.y,
00253                 lhs - rhs.z);
00254         }
00255 
00256         // arithmetic updates
00257         inline Vector3& operator += ( const Vector3& rkVector )
00258         {
00259             x += rkVector.x;
00260             y += rkVector.y;
00261             z += rkVector.z;
00262 
00263             return *this;
00264         }
00265 
00266         inline Vector3& operator += ( const Real fScalar )
00267         {
00268             x += fScalar;
00269             y += fScalar;
00270             z += fScalar;
00271             return *this;
00272         }
00273 
00274         inline Vector3& operator -= ( const Vector3& rkVector )
00275         {
00276             x -= rkVector.x;
00277             y -= rkVector.y;
00278             z -= rkVector.z;
00279 
00280             return *this;
00281         }
00282 
00283         inline Vector3& operator -= ( const Real fScalar )
00284         {
00285             x -= fScalar;
00286             y -= fScalar;
00287             z -= fScalar;
00288             return *this;
00289         }
00290 
00291         inline Vector3& operator *= ( const Real fScalar )
00292         {
00293             x *= fScalar;
00294             y *= fScalar;
00295             z *= fScalar;
00296             return *this;
00297         }
00298 
00299         inline Vector3& operator *= ( const Vector3& rkVector )
00300         {
00301             x *= rkVector.x;
00302             y *= rkVector.y;
00303             z *= rkVector.z;
00304 
00305             return *this;
00306         }
00307 
00308         inline Vector3& operator /= ( const Real fScalar )
00309         {
00310             assert( fScalar != 0.0 );
00311 
00312             Real fInv = 1.0 / fScalar;
00313 
00314             x *= fInv;
00315             y *= fInv;
00316             z *= fInv;
00317 
00318             return *this;
00319         }
00320 
00321         inline Vector3& operator /= ( const Vector3& rkVector )
00322         {
00323             x /= rkVector.x;
00324             y /= rkVector.y;
00325             z /= rkVector.z;
00326 
00327             return *this;
00328         }
00329 
00330 
00338         inline Real length () const
00339         {
00340             return Math::Sqrt( x * x + y * y + z * z );
00341         }
00342 
00353         inline Real squaredLength () const
00354         {
00355             return x * x + y * y + z * z;
00356         }
00357 
00365         inline Real distance(const Vector3& rhs) const
00366         {
00367             return (*this - rhs).length();
00368         }
00369 
00380         inline Real squaredDistance(const Vector3& rhs) const
00381         {
00382             return (*this - rhs).squaredLength();
00383         }
00384 
00399         inline Real dotProduct(const Vector3& vec) const
00400         {
00401             return x * vec.x + y * vec.y + z * vec.z;
00402         }
00403 
00414         inline Real absDotProduct(const Vector3& vec) const
00415         {
00416             return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
00417         }
00418 
00428         inline Real normalise()
00429         {
00430             Real fLength = Math::Sqrt( x * x + y * y + z * z );
00431 
00432             // Will also work for zero-sized vectors, but will change nothing
00433             if ( fLength > 1e-08 )
00434             {
00435                 Real fInvLength = 1.0 / fLength;
00436                 x *= fInvLength;
00437                 y *= fInvLength;
00438                 z *= fInvLength;
00439             }
00440 
00441             return fLength;
00442         }
00443 
00472         inline Vector3 crossProduct( const Vector3& rkVector ) const
00473         {
00474             return Vector3(
00475                 y * rkVector.z - z * rkVector.y,
00476                 z * rkVector.x - x * rkVector.z,
00477                 x * rkVector.y - y * rkVector.x);
00478         }
00479 
00483         inline Vector3 midPoint( const Vector3& vec ) const
00484         {
00485             return Vector3(
00486                 ( x + vec.x ) * 0.5,
00487                 ( y + vec.y ) * 0.5,
00488                 ( z + vec.z ) * 0.5 );
00489         }
00490 
00494         inline bool operator < ( const Vector3& rhs ) const
00495         {
00496             if( x < rhs.x && y < rhs.y && z < rhs.z )
00497                 return true;
00498             return false;
00499         }
00500 
00504         inline bool operator > ( const Vector3& rhs ) const
00505         {
00506             if( x > rhs.x && y > rhs.y && z > rhs.z )
00507                 return true;
00508             return false;
00509         }
00510 
00518         inline void makeFloor( const Vector3& cmp )
00519         {
00520             if( cmp.x < x ) x = cmp.x;
00521             if( cmp.y < y ) y = cmp.y;
00522             if( cmp.z < z ) z = cmp.z;
00523         }
00524 
00532         inline void makeCeil( const Vector3& cmp )
00533         {
00534             if( cmp.x > x ) x = cmp.x;
00535             if( cmp.y > y ) y = cmp.y;
00536             if( cmp.z > z ) z = cmp.z;
00537         }
00538 
00546         inline Vector3 perpendicular(void) const
00547         {
00548             static const Real fSquareZero = 1e-06 * 1e-06;
00549 
00550             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00551 
00552             // Check length
00553             if( perp.squaredLength() < fSquareZero )
00554             {
00555                 /* This vector is the Y axis multiplied by a scalar, so we have
00556                    to use another axis.
00557                 */
00558                 perp = this->crossProduct( Vector3::UNIT_Y );
00559             }
00560             perp.normalise();
00561 
00562             return perp;
00563         }
00583         inline Vector3 randomDeviant(
00584             const Radian& angle,
00585             const Vector3& up = Vector3::ZERO ) const
00586         {
00587             Vector3 newUp;
00588 
00589             if (up == Vector3::ZERO)
00590             {
00591                 // Generate an up vector
00592                 newUp = this->perpendicular();
00593             }
00594             else
00595             {
00596                 newUp = up;
00597             }
00598 
00599             // Rotate up vector by random amount around this
00600             Quaternion q;
00601             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
00602             newUp = q * newUp;
00603 
00604             // Finally rotate this by given angle around randomised up
00605             q.FromAngleAxis( angle, newUp );
00606             return q * (*this);
00607         }
00608 
00613         inline Radian angleBetween(const Vector3& dest)
00614         {
00615             Real lenProduct = length() * dest.length();
00616 
00617             // Divide by zero check
00618             if(lenProduct < 1e-6f)
00619                 lenProduct = 1e-6f;
00620 
00621             Real f = dotProduct(dest) / lenProduct;
00622 
00623             f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
00624             return Math::ACos(f);
00625 
00626         }
00635         Quaternion getRotationTo(const Vector3& dest,
00636             const Vector3& fallbackAxis = Vector3::ZERO) const
00637         {
00638             // Based on Stan Melax's article in Game Programming Gems
00639             Quaternion q;
00640             // Copy, since cannot modify local
00641             Vector3 v0 = *this;
00642             Vector3 v1 = dest;
00643             v0.normalise();
00644             v1.normalise();
00645 
00646             Real d = v0.dotProduct(v1);
00647             // If dot == 1, vectors are the same
00648             if (d >= 1.0f)
00649             {
00650                 return Quaternion::IDENTITY;
00651             }
00652             if (d < (1e-6f - 1.0f))
00653             {
00654                 if (fallbackAxis != Vector3::ZERO)
00655                 {
00656                     // rotate 180 degrees about the fallback axis
00657                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
00658                 }
00659                 else
00660                 {
00661                     // Generate an axis
00662                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
00663                     if (axis.isZeroLength()) // pick another if colinear
00664                         axis = Vector3::UNIT_Y.crossProduct(*this);
00665                     axis.normalise();
00666                     q.FromAngleAxis(Radian(Math::PI), axis);
00667                 }
00668             }
00669             else
00670             {
00671                 Real s = Math::Sqrt( (1+d)*2 );
00672                 Real invs = 1 / s;
00673 
00674                 Vector3 c = v0.crossProduct(v1);
00675 
00676                 q.x = c.x * invs;
00677                 q.y = c.y * invs;
00678                 q.z = c.z * invs;
00679                 q.w = s * 0.5;
00680                 q.normalise();
00681             }
00682             return q;
00683         }
00684 
00686         inline bool isZeroLength(void) const
00687         {
00688             Real sqlen = (x * x) + (y * y) + (z * z);
00689             return (sqlen < (1e-06 * 1e-06));
00690 
00691         }
00692 
00695         inline Vector3 normalisedCopy(void) const
00696         {
00697             Vector3 ret = *this;
00698             ret.normalise();
00699             return ret;
00700         }
00701 
00705         inline Vector3 reflect(const Vector3& normal) const
00706         {
00707             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00708         }
00709 
00716         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
00717         {
00718             return Math::RealEqual(x, rhs.x, tolerance) &&
00719                 Math::RealEqual(y, rhs.y, tolerance) &&
00720                 Math::RealEqual(z, rhs.z, tolerance);
00721 
00722         }
00723 
00730         inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
00731         {
00732             return squaredDistance(rhs) <=
00733                 (squaredLength() + rhs.squaredLength()) * tolerance;
00734         }
00735 
00743         inline bool directionEquals(const Vector3& rhs,
00744             const Radian& tolerance) const
00745         {
00746             Real dot = dotProduct(rhs);
00747             Radian angle = Math::ACos(dot);
00748 
00749             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
00750 
00751         }
00752 
00753         // special points
00754         static const Vector3 ZERO;
00755         static const Vector3 UNIT_X;
00756         static const Vector3 UNIT_Y;
00757         static const Vector3 UNIT_Z;
00758         static const Vector3 NEGATIVE_UNIT_X;
00759         static const Vector3 NEGATIVE_UNIT_Y;
00760         static const Vector3 NEGATIVE_UNIT_Z;
00761         static const Vector3 UNIT_SCALE;
00762 
00765         inline _OgreExport friend std::ostream& operator <<
00766             ( std::ostream& o, const Vector3& v )
00767         {
00768             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00769             return o;
00770         }
00771     };
00772 
00773 }
00774 #endif

Copyright © 2008 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:26 2009