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-2011 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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sat Jan 14 2012 18:40:44