# 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-2009 Torus Knot Software Ltd
    00008
    00009 Permission is hereby granted, free of charge, to any person obtaining a copy
    00010 of this software and associated documentation files (the "Software"), to deal
    00011 in the Software without restriction, including without limitation the rights
    00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00013 copies of the Software, and to permit persons to whom the Software is
    00014 furnished to do so, subject to the following conditions:
    00015
    00016 The above copyright notice and this permission notice shall be included in
    00017 all copies or substantial portions of the Software.
    00018
    00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00025 THE SOFTWARE.
    00026 -----------------------------------------------------------------------------
    00027 */
    00028 #ifndef __Vector3_H__
    00029 #define __Vector3_H__
    00030
    00031 #include "OgrePrerequisites.h"
    00032 #include "OgreMath.h"
    00033 #include "OgreQuaternion.h"
    00034
    00035 namespace Ogre
    00036 {
    00037
    00051     class _OgreExport Vector3
    00052     {
    00053     public:
    00054         Real x, y, z;
    00055
    00056     public:
    00057         inline Vector3()
    00058         {
    00059         }
    00060
    00061         inline Vector3( const Real fX, const Real fY, const Real fZ )
    00062             : x( fX ), y( fY ), z( fZ )
    00063         {
    00064         }
    00065
    00066         inline explicit Vector3( const Real afCoordinate[3] )
    00067             : x( afCoordinate[0] ),
    00068               y( afCoordinate[1] ),
    00069               z( afCoordinate[2] )
    00070         {
    00071         }
    00072
    00073         inline explicit Vector3( const int afCoordinate[3] )
    00074         {
    00075             x = (Real)afCoordinate[0];
    00076             y = (Real)afCoordinate[1];
    00077             z = (Real)afCoordinate[2];
    00078         }
    00079
    00080         inline explicit Vector3( Real* const r )
    00081             : x( r[0] ), y( r[1] ), z( r[2] )
    00082         {
    00083         }
    00084
    00085         inline explicit Vector3( const Real scaler )
    00086             : x( scaler )
    00087             , y( scaler )
    00088             , z( scaler )
    00089         {
    00090         }
    00091
    00092
    00095         inline void swap(Vector3& other)
    00096         {
    00097             std::swap(x, other.x);
    00098             std::swap(y, other.y);
    00099             std::swap(z, other.z);
    00100         }
    00101
    00102         inline Real operator [] ( const size_t i ) const
    00103         {
    00104             assert( i < 3 );
    00105
    00106             return *(&x+i);
    00107         }
    00108
    00109         inline Real& operator [] ( const size_t i )
    00110         {
    00111             assert( i < 3 );
    00112
    00113             return *(&x+i);
    00114         }
    00116         inline Real* ptr()
    00117         {
    00118             return &x;
    00119         }
    00121         inline const Real* ptr() const
    00122         {
    00123             return &x;
    00124         }
    00125
    00130         inline Vector3& operator = ( const Vector3& rkVector )
    00131         {
    00132             x = rkVector.x;
    00133             y = rkVector.y;
    00134             z = rkVector.z;
    00135
    00136             return *this;
    00137         }
    00138
    00139         inline Vector3& operator = ( const Real fScaler )
    00140         {
    00141             x = fScaler;
    00142             y = fScaler;
    00143             z = fScaler;
    00144
    00145             return *this;
    00146         }
    00147
    00148         inline bool operator == ( const Vector3& rkVector ) const
    00149         {
    00150             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
    00151         }
    00152
    00153         inline bool operator != ( const Vector3& rkVector ) const
    00154         {
    00155             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
    00156         }
    00157
    00158         // arithmetic operations
    00159         inline Vector3 operator + ( const Vector3& rkVector ) const
    00160         {
    00161             return Vector3(
    00162                 x + rkVector.x,
    00163                 y + rkVector.y,
    00164                 z + rkVector.z);
    00165         }
    00166
    00167         inline Vector3 operator - ( const Vector3& rkVector ) const
    00168         {
    00169             return Vector3(
    00170                 x - rkVector.x,
    00171                 y - rkVector.y,
    00172                 z - rkVector.z);
    00173         }
    00174
    00175         inline Vector3 operator * ( const Real fScalar ) const
    00176         {
    00177             return Vector3(
    00178                 x * fScalar,
    00179                 y * fScalar,
    00180                 z * fScalar);
    00181         }
    00182
    00183         inline Vector3 operator * ( const Vector3& rhs) const
    00184         {
    00185             return Vector3(
    00186                 x * rhs.x,
    00187                 y * rhs.y,
    00188                 z * rhs.z);
    00189         }
    00190
    00191         inline Vector3 operator / ( const Real fScalar ) const
    00192         {
    00193             assert( fScalar != 0.0 );
    00194
    00195             Real fInv = 1.0f / fScalar;
    00196
    00197             return Vector3(
    00198                 x * fInv,
    00199                 y * fInv,
    00200                 z * fInv);
    00201         }
    00202
    00203         inline Vector3 operator / ( const Vector3& rhs) const
    00204         {
    00205             return Vector3(
    00206                 x / rhs.x,
    00207                 y / rhs.y,
    00208                 z / rhs.z);
    00209         }
    00210
    00211         inline const Vector3& operator + () const
    00212         {
    00213             return *this;
    00214         }
    00215
    00216         inline Vector3 operator - () const
    00217         {
    00218             return Vector3(-x, -y, -z);
    00219         }
    00220
    00221         // overloaded operators to help Vector3
    00222         inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
    00223         {
    00224             return Vector3(
    00225                 fScalar * rkVector.x,
    00226                 fScalar * rkVector.y,
    00227                 fScalar * rkVector.z);
    00228         }
    00229
    00230         inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
    00231         {
    00232             return Vector3(
    00233                 fScalar / rkVector.x,
    00234                 fScalar / rkVector.y,
    00235                 fScalar / rkVector.z);
    00236         }
    00237
    00238         inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
    00239         {
    00240             return Vector3(
    00241                 lhs.x + rhs,
    00242                 lhs.y + rhs,
    00243                 lhs.z + rhs);
    00244         }
    00245
    00246         inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
    00247         {
    00248             return Vector3(
    00249                 lhs + rhs.x,
    00250                 lhs + rhs.y,
    00251                 lhs + rhs.z);
    00252         }
    00253
    00254         inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
    00255         {
    00256             return Vector3(
    00257                 lhs.x - rhs,
    00258                 lhs.y - rhs,
    00259                 lhs.z - rhs);
    00260         }
    00261
    00262         inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
    00263         {
    00264             return Vector3(
    00265                 lhs - rhs.x,
    00266                 lhs - rhs.y,
    00267                 lhs - rhs.z);
    00268         }
    00269
    00270         // arithmetic updates
    00271         inline Vector3& operator += ( const Vector3& rkVector )
    00272         {
    00273             x += rkVector.x;
    00274             y += rkVector.y;
    00275             z += rkVector.z;
    00276
    00277             return *this;
    00278         }
    00279
    00280         inline Vector3& operator += ( const Real fScalar )
    00281         {
    00282             x += fScalar;
    00283             y += fScalar;
    00284             z += fScalar;
    00285             return *this;
    00286         }
    00287
    00288         inline Vector3& operator -= ( const Vector3& rkVector )
    00289         {
    00290             x -= rkVector.x;
    00291             y -= rkVector.y;
    00292             z -= rkVector.z;
    00293
    00294             return *this;
    00295         }
    00296
    00297         inline Vector3& operator -= ( const Real fScalar )
    00298         {
    00299             x -= fScalar;
    00300             y -= fScalar;
    00301             z -= fScalar;
    00302             return *this;
    00303         }
    00304
    00305         inline Vector3& operator *= ( const Real fScalar )
    00306         {
    00307             x *= fScalar;
    00308             y *= fScalar;
    00309             z *= fScalar;
    00310             return *this;
    00311         }
    00312
    00313         inline Vector3& operator *= ( const Vector3& rkVector )
    00314         {
    00315             x *= rkVector.x;
    00316             y *= rkVector.y;
    00317             z *= rkVector.z;
    00318
    00319             return *this;
    00320         }
    00321
    00322         inline Vector3& operator /= ( const Real fScalar )
    00323         {
    00324             assert( fScalar != 0.0 );
    00325
    00326             Real fInv = 1.0f / fScalar;
    00327
    00328             x *= fInv;
    00329             y *= fInv;
    00330             z *= fInv;
    00331
    00332             return *this;
    00333         }
    00334
    00335         inline Vector3& operator /= ( const Vector3& rkVector )
    00336         {
    00337             x /= rkVector.x;
    00338             y /= rkVector.y;
    00339             z /= rkVector.z;
    00340
    00341             return *this;
    00342         }
    00343
    00344
    00352         inline Real length () const
    00353         {
    00354             return Math::Sqrt( x * x + y * y + z * z );
    00355         }
    00356
    00367         inline Real squaredLength () const
    00368         {
    00369             return x * x + y * y + z * z;
    00370         }
    00371
    00379         inline Real distance(const Vector3& rhs) const
    00380         {
    00381             return (*this - rhs).length();
    00382         }
    00383
    00394         inline Real squaredDistance(const Vector3& rhs) const
    00395         {
    00396             return (*this - rhs).squaredLength();
    00397         }
    00398
    00413         inline Real dotProduct(const Vector3& vec) const
    00414         {
    00415             return x * vec.x + y * vec.y + z * vec.z;
    00416         }
    00417
    00428         inline Real absDotProduct(const Vector3& vec) const
    00429         {
    00430             return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
    00431         }
    00432
    00442         inline Real normalise()
    00443         {
    00444             Real fLength = Math::Sqrt( x * x + y * y + z * z );
    00445
    00446             // Will also work for zero-sized vectors, but will change nothing
    00447             if ( fLength > 1e-08 )
    00448             {
    00449                 Real fInvLength = 1.0f / fLength;
    00450                 x *= fInvLength;
    00451                 y *= fInvLength;
    00452                 z *= fInvLength;
    00453             }
    00454
    00455             return fLength;
    00456         }
    00457
    00486         inline Vector3 crossProduct( const Vector3& rkVector ) const
    00487         {
    00488             return Vector3(
    00489                 y * rkVector.z - z * rkVector.y,
    00490                 z * rkVector.x - x * rkVector.z,
    00491                 x * rkVector.y - y * rkVector.x);
    00492         }
    00493
    00497         inline Vector3 midPoint( const Vector3& vec ) const
    00498         {
    00499             return Vector3(
    00500                 ( x + vec.x ) * 0.5f,
    00501                 ( y + vec.y ) * 0.5f,
    00502                 ( z + vec.z ) * 0.5f );
    00503         }
    00504
    00508         inline bool operator < ( const Vector3& rhs ) const
    00509         {
    00510             if( x < rhs.x && y < rhs.y && z < rhs.z )
    00511                 return true;
    00512             return false;
    00513         }
    00514
    00518         inline bool operator > ( const Vector3& rhs ) const
    00519         {
    00520             if( x > rhs.x && y > rhs.y && z > rhs.z )
    00521                 return true;
    00522             return false;
    00523         }
    00524
    00532         inline void makeFloor( 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 void makeCeil( const Vector3& cmp )
    00547         {
    00548             if( cmp.x > x ) x = cmp.x;
    00549             if( cmp.y > y ) y = cmp.y;
    00550             if( cmp.z > z ) z = cmp.z;
    00551         }
    00552
    00560         inline Vector3 perpendicular(void) const
    00561         {
    00562             static const Real fSquareZero = (Real)(1e-06 * 1e-06);
    00563
    00564             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
    00565
    00566             // Check length
    00567             if( perp.squaredLength() < fSquareZero )
    00568             {
    00569                 /* This vector is the Y axis multiplied by a scalar, so we have
    00570                    to use another axis.
    00571                 */
    00572                 perp = this->crossProduct( Vector3::UNIT_Y );
    00573             }
    00574             perp.normalise();
    00575
    00576             return perp;
    00577         }
    00597         inline Vector3 randomDeviant(
    00598             const Radian& angle,
    00599             const Vector3& up = Vector3::ZERO ) const
    00600         {
    00601             Vector3 newUp;
    00602
    00603             if (up == Vector3::ZERO)
    00604             {
    00605                 // Generate an up vector
    00606                 newUp = this->perpendicular();
    00607             }
    00608             else
    00609             {
    00610                 newUp = up;
    00611             }
    00612
    00613             // Rotate up vector by random amount around this
    00614             Quaternion q;
    00615             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
    00616             newUp = q * newUp;
    00617
    00618             // Finally rotate this by given angle around randomised up
    00619             q.FromAngleAxis( angle, newUp );
    00620             return q * (*this);
    00621         }
    00622
    00627         inline Radian angleBetween(const Vector3& dest)
    00628         {
    00629             Real lenProduct = length() * dest.length();
    00630
    00631             // Divide by zero check
    00632             if(lenProduct < 1e-6f)
    00633                 lenProduct = 1e-6f;
    00634
    00635             Real f = dotProduct(dest) / lenProduct;
    00636
    00637             f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
    00638             return Math::ACos(f);
    00639
    00640         }
    00649         Quaternion getRotationTo(const Vector3& dest,
    00650             const Vector3& fallbackAxis = Vector3::ZERO) const
    00651         {
    00652             // Based on Stan Melax's article in Game Programming Gems
    00653             Quaternion q;
    00654             // Copy, since cannot modify local
    00655             Vector3 v0 = *this;
    00656             Vector3 v1 = dest;
    00657             v0.normalise();
    00658             v1.normalise();
    00659
    00660             Real d = v0.dotProduct(v1);
    00661             // If dot == 1, vectors are the same
    00662             if (d >= 1.0f)
    00663             {
    00664                 return Quaternion::IDENTITY;
    00665             }
    00666             if (d < (1e-6f - 1.0f))
    00667             {
    00668                 if (fallbackAxis != Vector3::ZERO)
    00669                 {
    00670                     // rotate 180 degrees about the fallback axis
    00671                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
    00672                 }
    00673                 else
    00674                 {
    00675                     // Generate an axis
    00676                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
    00677                     if (axis.isZeroLength()) // pick another if colinear
    00678                         axis = Vector3::UNIT_Y.crossProduct(*this);
    00679                     axis.normalise();
    00680                     q.FromAngleAxis(Radian(Math::PI), axis);
    00681                 }
    00682             }
    00683             else
    00684             {
    00685                 Real s = Math::Sqrt( (1+d)*2 );
    00686                 Real invs = 1 / s;
    00687
    00688                 Vector3 c = v0.crossProduct(v1);
    00689
    00690                 q.x = c.x * invs;
    00691                 q.y = c.y * invs;
    00692                 q.z = c.z * invs;
    00693                 q.w = s * 0.5f;
    00694                 q.normalise();
    00695             }
    00696             return q;
    00697         }
    00698
    00700         inline bool isZeroLength(void) const
    00701         {
    00702             Real sqlen = (x * x) + (y * y) + (z * z);
    00703             return (sqlen < (1e-06 * 1e-06));
    00704
    00705         }
    00706
    00709         inline Vector3 normalisedCopy(void) const
    00710         {
    00711             Vector3 ret = *this;
    00712             ret.normalise();
    00713             return ret;
    00714         }
    00715
    00719         inline Vector3 reflect(const Vector3& normal) const
    00720         {
    00721             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
    00722         }
    00723
    00730         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
    00731         {
    00732             return Math::RealEqual(x, rhs.x, tolerance) &&
    00733                 Math::RealEqual(y, rhs.y, tolerance) &&
    00734                 Math::RealEqual(z, rhs.z, tolerance);
    00735
    00736         }
    00737
    00744         inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
    00745         {
    00746             return squaredDistance(rhs) <=
    00747                 (squaredLength() + rhs.squaredLength()) * tolerance;
    00748         }
    00749
    00757         inline bool directionEquals(const Vector3& rhs,
    00758             const Radian& tolerance) const
    00759         {
    00760             Real dot = dotProduct(rhs);
    00761             Radian angle = Math::ACos(dot);
    00762
    00763             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
    00764
    00765         }
    00766
    00768         inline bool isNaN() const
    00769         {
    00770             return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
    00771         }
    00772
    00773         // special points
    00774         static const Vector3 ZERO;
    00775         static const Vector3 UNIT_X;
    00776         static const Vector3 UNIT_Y;
    00777         static const Vector3 UNIT_Z;
    00778         static const Vector3 NEGATIVE_UNIT_X;
    00779         static const Vector3 NEGATIVE_UNIT_Y;
    00780         static const Vector3 NEGATIVE_UNIT_Z;
    00781         static const Vector3 UNIT_SCALE;
    00782
    00785         inline _OgreExport friend std::ostream& operator <<
    00786             ( std::ostream& o, const Vector3& v )
    00787         {
    00788             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
    00789             return o;
    00790         }
    00791     };
    00795 }
    00796 #endif

Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Wed Nov 3 2010 19:24:52