Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class 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 (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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Jun 10 10:35:50 2007