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-2012 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             // We're not using epsilons because we don't need to.
    00448             // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259
    00449             if ( fLength > Real(0.0f) )
    00450             {
    00451                 Real fInvLength = 1.0f / fLength;
    00452                 x *= fInvLength;
    00453                 y *= fInvLength;
    00454                 z *= fInvLength;
    00455             }
    00456
    00457             return fLength;
    00458         }
    00459
    00488         inline Vector3 crossProduct( const Vector3& rkVector ) const
    00489         {
    00490             return Vector3(
    00491                 y * rkVector.z - z * rkVector.y,
    00492                 z * rkVector.x - x * rkVector.z,
    00493                 x * rkVector.y - y * rkVector.x);
    00494         }
    00495
    00499         inline Vector3 midPoint( const Vector3& vec ) const
    00500         {
    00501             return Vector3(
    00502                 ( x + vec.x ) * 0.5f,
    00503                 ( y + vec.y ) * 0.5f,
    00504                 ( z + vec.z ) * 0.5f );
    00505         }
    00506
    00510         inline bool operator < ( const Vector3& rhs ) const
    00511         {
    00512             if( x < rhs.x && y < rhs.y && z < rhs.z )
    00513                 return true;
    00514             return false;
    00515         }
    00516
    00520         inline bool operator > ( const Vector3& rhs ) const
    00521         {
    00522             if( x > rhs.x && y > rhs.y && z > rhs.z )
    00523                 return true;
    00524             return false;
    00525         }
    00526
    00534         inline void makeFloor( const Vector3& cmp )
    00535         {
    00536             if( cmp.x < x ) x = cmp.x;
    00537             if( cmp.y < y ) y = cmp.y;
    00538             if( cmp.z < z ) z = cmp.z;
    00539         }
    00540
    00548         inline void makeCeil( const Vector3& cmp )
    00549         {
    00550             if( cmp.x > x ) x = cmp.x;
    00551             if( cmp.y > y ) y = cmp.y;
    00552             if( cmp.z > z ) z = cmp.z;
    00553         }
    00554
    00562         inline Vector3 perpendicular(void) const
    00563         {
    00564             static const Real fSquareZero = (Real)(1e-06 * 1e-06);
    00565
    00566             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
    00567
    00568             // Check length
    00569             if( perp.squaredLength() < fSquareZero )
    00570             {
    00571                 /* This vector is the Y axis multiplied by a scalar, so we have
    00572                    to use another axis.
    00573                 */
    00574                 perp = this->crossProduct( Vector3::UNIT_Y );
    00575             }
    00576             perp.normalise();
    00577
    00578             return perp;
    00579         }
    00599         inline Vector3 randomDeviant(
    00600             const Radian& angle,
    00601             const Vector3& up = Vector3::ZERO ) const
    00602         {
    00603             Vector3 newUp;
    00604
    00605             if (up == Vector3::ZERO)
    00606             {
    00607                 // Generate an up vector
    00608                 newUp = this->perpendicular();
    00609             }
    00610             else
    00611             {
    00612                 newUp = up;
    00613             }
    00614
    00615             // Rotate up vector by random amount around this
    00616             Quaternion q;
    00617             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
    00618             newUp = q * newUp;
    00619
    00620             // Finally rotate this by given angle around randomised up
    00621             q.FromAngleAxis( angle, newUp );
    00622             return q * (*this);
    00623         }
    00624
    00629         inline Radian angleBetween(const Vector3& dest) const
    00630         {
    00631             Real lenProduct = length() * dest.length();
    00632
    00633             // Divide by zero check
    00634             if(lenProduct < 1e-6f)
    00635                 lenProduct = 1e-6f;
    00636
    00637             Real f = dotProduct(dest) / lenProduct;
    00638
    00639             f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
    00640             return Math::ACos(f);
    00641
    00642         }
    00651         Quaternion getRotationTo(const Vector3& dest,
    00652             const Vector3& fallbackAxis = Vector3::ZERO) const
    00653         {
    00654             // Based on Stan Melax's article in Game Programming Gems
    00655             Quaternion q;
    00656             // Copy, since cannot modify local
    00657             Vector3 v0 = *this;
    00658             Vector3 v1 = dest;
    00659             v0.normalise();
    00660             v1.normalise();
    00661
    00662             Real d = v0.dotProduct(v1);
    00663             // If dot == 1, vectors are the same
    00664             if (d >= 1.0f)
    00665             {
    00666                 return Quaternion::IDENTITY;
    00667             }
    00668             if (d < (1e-6f - 1.0f))
    00669             {
    00670                 if (fallbackAxis != Vector3::ZERO)
    00671                 {
    00672                     // rotate 180 degrees about the fallback axis
    00673                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
    00674                 }
    00675                 else
    00676                 {
    00677                     // Generate an axis
    00678                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
    00679                     if (axis.isZeroLength()) // pick another if colinear
    00680                         axis = Vector3::UNIT_Y.crossProduct(*this);
    00681                     axis.normalise();
    00682                     q.FromAngleAxis(Radian(Math::PI), axis);
    00683                 }
    00684             }
    00685             else
    00686             {
    00687                 Real s = Math::Sqrt( (1+d)*2 );
    00688                 Real invs = 1 / s;
    00689
    00690                 Vector3 c = v0.crossProduct(v1);
    00691
    00692                 q.x = c.x * invs;
    00693                 q.y = c.y * invs;
    00694                 q.z = c.z * invs;
    00695                 q.w = s * 0.5f;
    00696                 q.normalise();
    00697             }
    00698             return q;
    00699         }
    00700
    00702         inline bool isZeroLength(void) const
    00703         {
    00704             Real sqlen = (x * x) + (y * y) + (z * z);
    00705             return (sqlen < (1e-06 * 1e-06));
    00706
    00707         }
    00708
    00711         inline Vector3 normalisedCopy(void) const
    00712         {
    00713             Vector3 ret = *this;
    00714             ret.normalise();
    00715             return ret;
    00716         }
    00717
    00721         inline Vector3 reflect(const Vector3& normal) const
    00722         {
    00723             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
    00724         }
    00725
    00732         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
    00733         {
    00734             return Math::RealEqual(x, rhs.x, tolerance) &&
    00735                 Math::RealEqual(y, rhs.y, tolerance) &&
    00736                 Math::RealEqual(z, rhs.z, tolerance);
    00737
    00738         }
    00739
    00746         inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
    00747         {
    00748             return squaredDistance(rhs) <=
    00749                 (squaredLength() + rhs.squaredLength()) * tolerance;
    00750         }
    00751
    00759         inline bool directionEquals(const Vector3& rhs,
    00760             const Radian& tolerance) const
    00761         {
    00762             Real dot = dotProduct(rhs);
    00763             Radian angle = Math::ACos(dot);
    00764
    00765             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
    00766
    00767         }
    00768
    00770         inline bool isNaN() const
    00771         {
    00772             return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
    00773         }
    00774
    00776         inline Vector3 primaryAxis() const
    00777         {
    00778             Real absx = Math::Abs(x);
    00779             Real absy = Math::Abs(y);
    00780             Real absz = Math::Abs(z);
    00781             if (absx > absy)
    00782                 if (absx > absz)
    00783                     return x > 0 ? Vector3::UNIT_X : Vector3::NEGATIVE_UNIT_X;
    00784                 else
    00785                     return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
    00786             else // absx <= absy
    00787                 if (absy > absz)
    00788                     return y > 0 ? Vector3::UNIT_Y : Vector3::NEGATIVE_UNIT_Y;
    00789                 else
    00790                     return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
    00791
    00792
    00793         }
    00794
    00795         // special points
    00796         static const Vector3 ZERO;
    00797         static const Vector3 UNIT_X;
    00798         static const Vector3 UNIT_Y;
    00799         static const Vector3 UNIT_Z;
    00800         static const Vector3 NEGATIVE_UNIT_X;
    00801         static const Vector3 NEGATIVE_UNIT_Y;
    00802         static const Vector3 NEGATIVE_UNIT_Z;
    00803         static const Vector3 UNIT_SCALE;
    00804
    00807         inline _OgreExport friend std::ostream& operator <<
    00808             ( std::ostream& o, const Vector3& v )
    00809         {
    00810             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
    00811             return o;
    00812         }
    00813     };
    00817 }
    00818 #endif

Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sun Sep 2 2012 07:27:24