# 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 Vector3( const Vector3& rkVector )
    00089             : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
    00090         {
    00091         }
    00092
    00093         inline Real operator [] ( const size_t i ) const
    00094         {
    00095             assert( i < 3 );
    00096
    00097             return *(&x+i);
    00098         }
    00099
    00100         inline Real& operator [] ( const size_t i )
    00101         {
    00102             assert( i < 3 );
    00103
    00104             return *(&x+i);
    00105         }
    00107         inline Real* ptr()
    00108         {
    00109             return &x;
    00110         }
    00112         inline const Real* ptr() const
    00113         {
    00114             return &x;
    00115         }
    00116
    00121         inline Vector3& operator = ( const Vector3& rkVector )
    00122         {
    00123             x = rkVector.x;
    00124             y = rkVector.y;
    00125             z = rkVector.z;
    00126
    00127             return *this;
    00128         }
    00129
    00130         inline Vector3& operator = ( const Real fScaler )
    00131         {
    00132             x = fScaler;
    00133             y = fScaler;
    00134             z = fScaler;
    00135
    00136             return *this;
    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         inline bool operator != ( const Vector3& rkVector ) const
    00145         {
    00146             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
    00147         }
    00148
    00149         // arithmetic operations
    00150         inline Vector3 operator + ( const Vector3& rkVector ) const
    00151         {
    00152             return Vector3(
    00153                 x + rkVector.x,
    00154                 y + rkVector.y,
    00155                 z + rkVector.z);
    00156         }
    00157
    00158         inline Vector3 operator - ( const Vector3& rkVector ) const
    00159         {
    00160             return Vector3(
    00161                 x - rkVector.x,
    00162                 y - rkVector.y,
    00163                 z - rkVector.z);
    00164         }
    00165
    00166         inline Vector3 operator * ( const Real fScalar ) const
    00167         {
    00168             return Vector3(
    00169                 x * fScalar,
    00170                 y * fScalar,
    00171                 z * fScalar);
    00172         }
    00173
    00174         inline Vector3 operator * ( const Vector3& rhs) const
    00175         {
    00176             return Vector3(
    00177                 x * rhs.x,
    00178                 y * rhs.y,
    00179                 z * rhs.z);
    00180         }
    00181
    00182         inline Vector3 operator / ( const Real fScalar ) const
    00183         {
    00184             assert( fScalar != 0.0 );
    00185
    00186             Real fInv = 1.0 / fScalar;
    00187
    00188             return Vector3(
    00189                 x * fInv,
    00190                 y * fInv,
    00191                 z * fInv);
    00192         }
    00193
    00194         inline Vector3 operator / ( const Vector3& rhs) const
    00195         {
    00196             return Vector3(
    00197                 x / rhs.x,
    00198                 y / rhs.y,
    00199                 z / rhs.z);
    00200         }
    00201
    00202         inline const Vector3& operator + () const
    00203         {
    00204             return *this;
    00205         }
    00206
    00207         inline Vector3 operator - () const
    00208         {
    00209             return Vector3(-x, -y, -z);
    00210         }
    00211
    00212         // overloaded operators to help Vector3
    00213         inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
    00214         {
    00215             return Vector3(
    00216                 fScalar * rkVector.x,
    00217                 fScalar * rkVector.y,
    00218                 fScalar * rkVector.z);
    00219         }
    00220
    00221         inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
    00222         {
    00223             return Vector3(
    00224                 fScalar / rkVector.x,
    00225                 fScalar / rkVector.y,
    00226                 fScalar / rkVector.z);
    00227         }
    00228
    00229         inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
    00230         {
    00231             return Vector3(
    00232                 lhs.x + rhs,
    00233                 lhs.y + rhs,
    00234                 lhs.z + rhs);
    00235         }
    00236
    00237         inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
    00238         {
    00239             return Vector3(
    00240                 lhs + rhs.x,
    00241                 lhs + rhs.y,
    00242                 lhs + rhs.z);
    00243         }
    00244
    00245         inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
    00246         {
    00247             return Vector3(
    00248                 lhs.x - rhs,
    00249                 lhs.y - rhs,
    00250                 lhs.z - rhs);
    00251         }
    00252
    00253         inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
    00254         {
    00255             return Vector3(
    00256                 lhs - rhs.x,
    00257                 lhs - rhs.y,
    00258                 lhs - rhs.z);
    00259         }
    00260
    00261         // arithmetic updates
    00262         inline Vector3& operator += ( const Vector3& rkVector )
    00263         {
    00264             x += rkVector.x;
    00265             y += rkVector.y;
    00266             z += rkVector.z;
    00267
    00268             return *this;
    00269         }
    00270
    00271         inline Vector3& operator += ( const Real fScalar )
    00272         {
    00273             x += fScalar;
    00274             y += fScalar;
    00275             z += fScalar;
    00276             return *this;
    00277         }
    00278
    00279         inline Vector3& operator -= ( const Vector3& rkVector )
    00280         {
    00281             x -= rkVector.x;
    00282             y -= rkVector.y;
    00283             z -= rkVector.z;
    00284
    00285             return *this;
    00286         }
    00287
    00288         inline Vector3& operator -= ( const Real fScalar )
    00289         {
    00290             x -= fScalar;
    00291             y -= fScalar;
    00292             z -= fScalar;
    00293             return *this;
    00294         }
    00295
    00296         inline Vector3& operator *= ( const Real fScalar )
    00297         {
    00298             x *= fScalar;
    00299             y *= fScalar;
    00300             z *= fScalar;
    00301             return *this;
    00302         }
    00303
    00304         inline Vector3& operator *= ( const Vector3& rkVector )
    00305         {
    00306             x *= rkVector.x;
    00307             y *= rkVector.y;
    00308             z *= rkVector.z;
    00309
    00310             return *this;
    00311         }
    00312
    00313         inline Vector3& operator /= ( const Real fScalar )
    00314         {
    00315             assert( fScalar != 0.0 );
    00316
    00317             Real fInv = 1.0 / fScalar;
    00318
    00319             x *= fInv;
    00320             y *= fInv;
    00321             z *= fInv;
    00322
    00323             return *this;
    00324         }
    00325
    00326         inline Vector3& operator /= ( const Vector3& rkVector )
    00327         {
    00328             x /= rkVector.x;
    00329             y /= rkVector.y;
    00330             z /= rkVector.z;
    00331
    00332             return *this;
    00333         }
    00334
    00335
    00343         inline Real length () const
    00344         {
    00345             return Math::Sqrt( x * x + y * y + z * z );
    00346         }
    00347
    00358         inline Real squaredLength () const
    00359         {
    00360             return x * x + y * y + z * z;
    00361         }
    00362
    00370         inline Real distance(const Vector3& rhs) const
    00371         {
    00372             return (*this - rhs).length();
    00373         }
    00374
    00385         inline Real squaredDistance(const Vector3& rhs) const
    00386         {
    00387             return (*this - rhs).squaredLength();
    00388         }
    00389
    00404         inline Real dotProduct(const Vector3& vec) const
    00405         {
    00406             return x * vec.x + y * vec.y + z * vec.z;
    00407         }
    00408
    00419         inline Real absDotProduct(const Vector3& vec) const
    00420         {
    00421             return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
    00422         }
    00423
    00433         inline Real normalise()
    00434         {
    00435             Real fLength = Math::Sqrt( x * x + y * y + z * z );
    00436
    00437             // Will also work for zero-sized vectors, but will change nothing
    00438             if ( fLength > 1e-08 )
    00439             {
    00440                 Real fInvLength = 1.0 / fLength;
    00441                 x *= fInvLength;
    00442                 y *= fInvLength;
    00443                 z *= fInvLength;
    00444             }
    00445
    00446             return fLength;
    00447         }
    00448
    00477         inline Vector3 crossProduct( const Vector3& rkVector ) const
    00478         {
    00479             return Vector3(
    00480                 y * rkVector.z - z * rkVector.y,
    00481                 z * rkVector.x - x * rkVector.z,
    00482                 x * rkVector.y - y * rkVector.x);
    00483         }
    00484
    00488         inline Vector3 midPoint( const Vector3& vec ) const
    00489         {
    00490             return Vector3(
    00491                 ( x + vec.x ) * 0.5,
    00492                 ( y + vec.y ) * 0.5,
    00493                 ( z + vec.z ) * 0.5 );
    00494         }
    00495
    00499         inline bool operator < ( const Vector3& rhs ) const
    00500         {
    00501             if( x < rhs.x && y < rhs.y && z < rhs.z )
    00502                 return true;
    00503             return false;
    00504         }
    00505
    00509         inline bool operator > ( const Vector3& rhs ) const
    00510         {
    00511             if( x > rhs.x && y > rhs.y && z > rhs.z )
    00512                 return true;
    00513             return false;
    00514         }
    00515
    00523         inline void makeFloor( const Vector3& cmp )
    00524         {
    00525             if( cmp.x < x ) x = cmp.x;
    00526             if( cmp.y < y ) y = cmp.y;
    00527             if( cmp.z < z ) z = cmp.z;
    00528         }
    00529
    00537         inline void makeCeil( const Vector3& cmp )
    00538         {
    00539             if( cmp.x > x ) x = cmp.x;
    00540             if( cmp.y > y ) y = cmp.y;
    00541             if( cmp.z > z ) z = cmp.z;
    00542         }
    00543
    00551         inline Vector3 perpendicular(void) const
    00552         {
    00553             static const Real fSquareZero = 1e-06 * 1e-06;
    00554
    00555             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
    00556
    00557             // Check length
    00558             if( perp.squaredLength() < fSquareZero )
    00559             {
    00560                 /* This vector is the Y axis multiplied by a scalar, so we have
    00561                    to use another axis.
    00562                 */
    00563                 perp = this->crossProduct( Vector3::UNIT_Y );
    00564             }
    00565             perp.normalise();
    00566
    00567             return perp;
    00568         }
    00588         inline Vector3 randomDeviant(
    00589             const Radian& angle,
    00590             const Vector3& up = Vector3::ZERO ) const
    00591         {
    00592             Vector3 newUp;
    00593
    00594             if (up == Vector3::ZERO)
    00595             {
    00596                 // Generate an up vector
    00597                 newUp = this->perpendicular();
    00598             }
    00599             else
    00600             {
    00601                 newUp = up;
    00602             }
    00603
    00604             // Rotate up vector by random amount around this
    00605             Quaternion q;
    00606             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
    00607             newUp = q * newUp;
    00608
    00609             // Finally rotate this by given angle around randomised up
    00610             q.FromAngleAxis( angle, newUp );
    00611             return q * (*this);
    00612         }
    00613 #ifndef OGRE_FORCE_ANGLE_TYPES
    00614         inline Vector3 randomDeviant(
    00615             Real angle,
    00616             const Vector3& up = Vector3::ZERO ) const
    00617         {
    00618             return randomDeviant ( Radian(angle), up );
    00619         }
    00620 #endif//OGRE_FORCE_ANGLE_TYPES
    00621
    00630         Quaternion getRotationTo(const Vector3& dest,
    00631             const Vector3& fallbackAxis = Vector3::ZERO) const
    00632         {
    00633             // Based on Stan Melax's article in Game Programming Gems
    00634             Quaternion q;
    00635             // Copy, since cannot modify local
    00636             Vector3 v0 = *this;
    00637             Vector3 v1 = dest;
    00638             v0.normalise();
    00639             v1.normalise();
    00640
    00641             Real d = v0.dotProduct(v1);
    00642             // If dot == 1, vectors are the same
    00643             if (d >= 1.0f)
    00644             {
    00645                 return Quaternion::IDENTITY;
    00646             }
    00647             if (d < (1e-6f - 1.0f))
    00648             {
    00649                 if (fallbackAxis != Vector3::ZERO)
    00650                 {
    00651                     // rotate 180 degrees about the fallback axis
    00652                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
    00653                 }
    00654                 else
    00655                 {
    00656                     // Generate an axis
    00657                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
    00658                     if (axis.isZeroLength()) // pick another if colinear
    00659                         axis = Vector3::UNIT_Y.crossProduct(*this);
    00660                     axis.normalise();
    00661                     q.FromAngleAxis(Radian(Math::PI), axis);
    00662                 }
    00663             }
    00664             else
    00665             {
    00666                 Real s = Math::Sqrt( (1+d)*2 );
    00667                 Real invs = 1 / s;
    00668
    00669                 Vector3 c = v0.crossProduct(v1);
    00670
    00671                 q.x = c.x * invs;
    00672                 q.y = c.y * invs;
    00673                 q.z = c.z * invs;
    00674                 q.w = s * 0.5;
    00675                 q.normalise();
    00676             }
    00677             return q;
    00678         }
    00679
    00681         inline bool isZeroLength(void) const
    00682         {
    00683             Real sqlen = (x * x) + (y * y) + (z * z);
    00684             return (sqlen < (1e-06 * 1e-06));
    00685
    00686         }
    00687
    00690         inline Vector3 normalisedCopy(void) const
    00691         {
    00692             Vector3 ret = *this;
    00693             ret.normalise();
    00694             return ret;
    00695         }
    00696
    00700         inline Vector3 reflect(const Vector3& normal) const
    00701         {
    00702             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
    00703         }
    00704
    00711         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
    00712         {
    00713             return Math::RealEqual(x, rhs.x, tolerance) &&
    00714                 Math::RealEqual(y, rhs.y, tolerance) &&
    00715                 Math::RealEqual(z, rhs.z, tolerance);
    00716
    00717         }
    00718
    00725         inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
    00726         {
    00727             return squaredDistance(rhs) <=
    00728                 (squaredLength() + rhs.squaredLength()) * tolerance;
    00729         }
    00730
    00738         inline bool directionEquals(const Vector3& rhs,
    00739             const Radian& tolerance) const
    00740         {
    00741             Real dot = dotProduct(rhs);
    00742             Radian angle = Math::ACos(dot);
    00743
    00744             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
    00745
    00746         }
    00747
    00748         // special points
    00749         static const Vector3 ZERO;
    00750         static const Vector3 UNIT_X;
    00751         static const Vector3 UNIT_Y;
    00752         static const Vector3 UNIT_Z;
    00753         static const Vector3 NEGATIVE_UNIT_X;
    00754         static const Vector3 NEGATIVE_UNIT_Y;
    00755         static const Vector3 NEGATIVE_UNIT_Z;
    00756         static const Vector3 UNIT_SCALE;
    00757
    00760         inline _OgreExport friend std::ostream& operator <<
    00761             ( std::ostream& o, const Vector3& v )
    00762         {
    00763             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
    00764             return o;
    00765         }
    00766     };
    00767
    00768 }
    00769 #endif

Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat May 10 16:25:04 2008