# 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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat Apr 11 13:46:44 2009