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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:28 2012