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-2013 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:
00061         inline Vector3()
00062         {
00063         }
00064 
00065         inline Vector3( const Real fX, const Real fY, const Real fZ )
00066             : x( fX ), y( fY ), z( fZ )
00067         {
00068         }
00069 
00070         inline explicit Vector3( const Real afCoordinate[3] )
00071             : x( afCoordinate[0] ),
00072               y( afCoordinate[1] ),
00073               z( afCoordinate[2] )
00074         {
00075         }
00076 
00077         inline explicit Vector3( const int afCoordinate[3] )
00078         {
00079             x = (Real)afCoordinate[0];
00080             y = (Real)afCoordinate[1];
00081             z = (Real)afCoordinate[2];
00082         }
00083 
00084         inline explicit Vector3( Real* const r )
00085             : x( r[0] ), y( r[1] ), z( r[2] )
00086         {
00087         }
00088 
00089         inline explicit Vector3( const Real scaler )
00090             : x( scaler )
00091             , y( scaler )
00092             , z( scaler )
00093         {
00094         }
00095 
00096 
00099         inline void swap(Vector3& other)
00100         {
00101             std::swap(x, other.x);
00102             std::swap(y, other.y);
00103             std::swap(z, other.z);
00104         }
00105 
00106         inline Real operator [] ( const size_t i ) const
00107         {
00108             assert( i < 3 );
00109 
00110             return *(&x+i);
00111         }
00112 
00113         inline Real& operator [] ( const size_t i )
00114         {
00115             assert( i < 3 );
00116 
00117             return *(&x+i);
00118         }
00120         inline Real* ptr()
00121         {
00122             return &x;
00123         }
00125         inline const Real* ptr() const
00126         {
00127             return &x;
00128         }
00129 
00134         inline Vector3& operator = ( const Vector3& rkVector )
00135         {
00136             x = rkVector.x;
00137             y = rkVector.y;
00138             z = rkVector.z;
00139 
00140             return *this;
00141         }
00142 
00143         inline Vector3& operator = ( const Real fScaler )
00144         {
00145             x = fScaler;
00146             y = fScaler;
00147             z = fScaler;
00148 
00149             return *this;
00150         }
00151 
00152         inline bool operator == ( const Vector3& rkVector ) const
00153         {
00154             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00155         }
00156 
00157         inline bool operator != ( const Vector3& rkVector ) const
00158         {
00159             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00160         }
00161 
00162         // arithmetic operations
00163         inline Vector3 operator + ( const Vector3& rkVector ) const
00164         {
00165             return Vector3(
00166                 x + rkVector.x,
00167                 y + rkVector.y,
00168                 z + rkVector.z);
00169         }
00170 
00171         inline Vector3 operator - ( const Vector3& rkVector ) const
00172         {
00173             return Vector3(
00174                 x - rkVector.x,
00175                 y - rkVector.y,
00176                 z - rkVector.z);
00177         }
00178 
00179         inline Vector3 operator * ( const Real fScalar ) const
00180         {
00181             return Vector3(
00182                 x * fScalar,
00183                 y * fScalar,
00184                 z * fScalar);
00185         }
00186 
00187         inline Vector3 operator * ( const Vector3& rhs) const
00188         {
00189             return Vector3(
00190                 x * rhs.x,
00191                 y * rhs.y,
00192                 z * rhs.z);
00193         }
00194 
00195         inline Vector3 operator / ( const Real fScalar ) const
00196         {
00197             assert( fScalar != 0.0 );
00198 
00199             Real fInv = 1.0f / fScalar;
00200 
00201             return Vector3(
00202                 x * fInv,
00203                 y * fInv,
00204                 z * fInv);
00205         }
00206 
00207         inline Vector3 operator / ( const Vector3& rhs) const
00208         {
00209             return Vector3(
00210                 x / rhs.x,
00211                 y / rhs.y,
00212                 z / rhs.z);
00213         }
00214 
00215         inline const Vector3& operator + () const
00216         {
00217             return *this;
00218         }
00219 
00220         inline Vector3 operator - () const
00221         {
00222             return Vector3(-x, -y, -z);
00223         }
00224 
00225         // overloaded operators to help Vector3
00226         inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
00227         {
00228             return Vector3(
00229                 fScalar * rkVector.x,
00230                 fScalar * rkVector.y,
00231                 fScalar * rkVector.z);
00232         }
00233 
00234         inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
00235         {
00236             return Vector3(
00237                 fScalar / rkVector.x,
00238                 fScalar / rkVector.y,
00239                 fScalar / rkVector.z);
00240         }
00241 
00242         inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
00243         {
00244             return Vector3(
00245                 lhs.x + rhs,
00246                 lhs.y + rhs,
00247                 lhs.z + rhs);
00248         }
00249 
00250         inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
00251         {
00252             return Vector3(
00253                 lhs + rhs.x,
00254                 lhs + rhs.y,
00255                 lhs + rhs.z);
00256         }
00257 
00258         inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
00259         {
00260             return Vector3(
00261                 lhs.x - rhs,
00262                 lhs.y - rhs,
00263                 lhs.z - rhs);
00264         }
00265 
00266         inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
00267         {
00268             return Vector3(
00269                 lhs - rhs.x,
00270                 lhs - rhs.y,
00271                 lhs - rhs.z);
00272         }
00273 
00274         // arithmetic updates
00275         inline Vector3& operator += ( const Vector3& rkVector )
00276         {
00277             x += rkVector.x;
00278             y += rkVector.y;
00279             z += rkVector.z;
00280 
00281             return *this;
00282         }
00283 
00284         inline Vector3& operator += ( const Real fScalar )
00285         {
00286             x += fScalar;
00287             y += fScalar;
00288             z += fScalar;
00289             return *this;
00290         }
00291 
00292         inline Vector3& operator -= ( const Vector3& rkVector )
00293         {
00294             x -= rkVector.x;
00295             y -= rkVector.y;
00296             z -= rkVector.z;
00297 
00298             return *this;
00299         }
00300 
00301         inline Vector3& operator -= ( const Real fScalar )
00302         {
00303             x -= fScalar;
00304             y -= fScalar;
00305             z -= fScalar;
00306             return *this;
00307         }
00308 
00309         inline Vector3& operator *= ( const Real fScalar )
00310         {
00311             x *= fScalar;
00312             y *= fScalar;
00313             z *= fScalar;
00314             return *this;
00315         }
00316 
00317         inline Vector3& operator *= ( const Vector3& rkVector )
00318         {
00319             x *= rkVector.x;
00320             y *= rkVector.y;
00321             z *= rkVector.z;
00322 
00323             return *this;
00324         }
00325 
00326         inline Vector3& operator /= ( const Real fScalar )
00327         {
00328             assert( fScalar != 0.0 );
00329 
00330             Real fInv = 1.0f / fScalar;
00331 
00332             x *= fInv;
00333             y *= fInv;
00334             z *= fInv;
00335 
00336             return *this;
00337         }
00338 
00339         inline Vector3& operator /= ( const Vector3& rkVector )
00340         {
00341             x /= rkVector.x;
00342             y /= rkVector.y;
00343             z /= rkVector.z;
00344 
00345             return *this;
00346         }
00347 
00348 
00356         inline Real length () const
00357         {
00358             return Math::Sqrt( x * x + y * y + z * z );
00359         }
00360 
00371         inline Real squaredLength () const
00372         {
00373             return x * x + y * y + z * z;
00374         }
00375 
00383         inline Real distance(const Vector3& rhs) const
00384         {
00385             return (*this - rhs).length();
00386         }
00387 
00398         inline Real squaredDistance(const Vector3& rhs) const
00399         {
00400             return (*this - rhs).squaredLength();
00401         }
00402 
00417         inline Real dotProduct(const Vector3& vec) const
00418         {
00419             return x * vec.x + y * vec.y + z * vec.z;
00420         }
00421 
00432         inline Real absDotProduct(const Vector3& vec) const
00433         {
00434             return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
00435         }
00436 
00446         inline Real normalise()
00447         {
00448             Real fLength = Math::Sqrt( x * x + y * y + z * z );
00449 
00450             // Will also work for zero-sized vectors, but will change nothing
00451             // We're not using epsilons because we don't need to.
00452             // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259
00453             if ( fLength > Real(0.0f) )
00454             {
00455                 Real fInvLength = 1.0f / fLength;
00456                 x *= fInvLength;
00457                 y *= fInvLength;
00458                 z *= fInvLength;
00459             }
00460 
00461             return fLength;
00462         }
00463 
00492         inline Vector3 crossProduct( const Vector3& rkVector ) const
00493         {
00494             return Vector3(
00495                 y * rkVector.z - z * rkVector.y,
00496                 z * rkVector.x - x * rkVector.z,
00497                 x * rkVector.y - y * rkVector.x);
00498         }
00499 
00503         inline Vector3 midPoint( const Vector3& vec ) const
00504         {
00505             return Vector3(
00506                 ( x + vec.x ) * 0.5f,
00507                 ( y + vec.y ) * 0.5f,
00508                 ( z + vec.z ) * 0.5f );
00509         }
00510 
00514         inline bool operator < ( const Vector3& rhs ) const
00515         {
00516             if( x < rhs.x && y < rhs.y && z < rhs.z )
00517                 return true;
00518             return false;
00519         }
00520 
00524         inline bool operator > ( const Vector3& rhs ) const
00525         {
00526             if( x > rhs.x && y > rhs.y && z > rhs.z )
00527                 return true;
00528             return false;
00529         }
00530 
00538         inline void makeFloor( const Vector3& cmp )
00539         {
00540             if( cmp.x < x ) x = cmp.x;
00541             if( cmp.y < y ) y = cmp.y;
00542             if( cmp.z < z ) z = cmp.z;
00543         }
00544 
00552         inline void makeCeil( const Vector3& cmp )
00553         {
00554             if( cmp.x > x ) x = cmp.x;
00555             if( cmp.y > y ) y = cmp.y;
00556             if( cmp.z > z ) z = cmp.z;
00557         }
00558 
00566         inline Vector3 perpendicular(void) const
00567         {
00568             static const Real fSquareZero = (Real)(1e-06 * 1e-06);
00569 
00570             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00571 
00572             // Check length
00573             if( perp.squaredLength() < fSquareZero )
00574             {
00575                 /* This vector is the Y axis multiplied by a scalar, so we have
00576                    to use another axis.
00577                 */
00578                 perp = this->crossProduct( Vector3::UNIT_Y );
00579             }
00580             perp.normalise();
00581 
00582             return perp;
00583         }
00603         inline Vector3 randomDeviant(
00604             const Radian& angle,
00605             const Vector3& up = Vector3::ZERO ) const
00606         {
00607             Vector3 newUp;
00608 
00609             if (up == Vector3::ZERO)
00610             {
00611                 // Generate an up vector
00612                 newUp = this->perpendicular();
00613             }
00614             else
00615             {
00616                 newUp = up;
00617             }
00618 
00619             // Rotate up vector by random amount around this
00620             Quaternion q;
00621             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
00622             newUp = q * newUp;
00623 
00624             // Finally rotate this by given angle around randomised up
00625             q.FromAngleAxis( angle, newUp );
00626             return q * (*this);
00627         }
00628 
00633         inline Radian angleBetween(const Vector3& dest) const
00634         {
00635             Real lenProduct = length() * dest.length();
00636 
00637             // Divide by zero check
00638             if(lenProduct < 1e-6f)
00639                 lenProduct = 1e-6f;
00640 
00641             Real f = dotProduct(dest) / lenProduct;
00642 
00643             f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
00644             return Math::ACos(f);
00645 
00646         }
00655         Quaternion getRotationTo(const Vector3& dest,
00656             const Vector3& fallbackAxis = Vector3::ZERO) const
00657         {
00658             // Based on Stan Melax's article in Game Programming Gems
00659             Quaternion q;
00660             // Copy, since cannot modify local
00661             Vector3 v0 = *this;
00662             Vector3 v1 = dest;
00663             v0.normalise();
00664             v1.normalise();
00665 
00666             Real d = v0.dotProduct(v1);
00667             // If dot == 1, vectors are the same
00668             if (d >= 1.0f)
00669             {
00670                 return Quaternion::IDENTITY;
00671             }
00672             if (d < (1e-6f - 1.0f))
00673             {
00674                 if (fallbackAxis != Vector3::ZERO)
00675                 {
00676                     // rotate 180 degrees about the fallback axis
00677                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
00678                 }
00679                 else
00680                 {
00681                     // Generate an axis
00682                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
00683                     if (axis.isZeroLength()) // pick another if colinear
00684                         axis = Vector3::UNIT_Y.crossProduct(*this);
00685                     axis.normalise();
00686                     q.FromAngleAxis(Radian(Math::PI), axis);
00687                 }
00688             }
00689             else
00690             {
00691                 Real s = Math::Sqrt( (1+d)*2 );
00692                 Real invs = 1 / s;
00693 
00694                 Vector3 c = v0.crossProduct(v1);
00695 
00696                 q.x = c.x * invs;
00697                 q.y = c.y * invs;
00698                 q.z = c.z * invs;
00699                 q.w = s * 0.5f;
00700                 q.normalise();
00701             }
00702             return q;
00703         }
00704 
00706         inline bool isZeroLength(void) const
00707         {
00708             Real sqlen = (x * x) + (y * y) + (z * z);
00709             return (sqlen < (1e-06 * 1e-06));
00710 
00711         }
00712 
00715         inline Vector3 normalisedCopy(void) const
00716         {
00717             Vector3 ret = *this;
00718             ret.normalise();
00719             return ret;
00720         }
00721 
00725         inline Vector3 reflect(const Vector3& normal) const
00726         {
00727             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00728         }
00729 
00736         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
00737         {
00738             return Math::RealEqual(x, rhs.x, tolerance) &&
00739                 Math::RealEqual(y, rhs.y, tolerance) &&
00740                 Math::RealEqual(z, rhs.z, tolerance);
00741 
00742         }
00743 
00750         inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
00751         {
00752             return squaredDistance(rhs) <=
00753                 (squaredLength() + rhs.squaredLength()) * tolerance;
00754         }
00755 
00763         inline bool directionEquals(const Vector3& rhs,
00764             const Radian& tolerance) const
00765         {
00766             Real dot = dotProduct(rhs);
00767             Radian angle = Math::ACos(dot);
00768 
00769             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
00770 
00771         }
00772 
00774         inline bool isNaN() const
00775         {
00776             return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
00777         }
00778 
00780         inline Vector3 primaryAxis() const
00781         {
00782             Real absx = Math::Abs(x);
00783             Real absy = Math::Abs(y);
00784             Real absz = Math::Abs(z);
00785             if (absx > absy)
00786                 if (absx > absz)
00787                     return x > 0 ? Vector3::UNIT_X : Vector3::NEGATIVE_UNIT_X;
00788                 else
00789                     return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
00790             else // absx <= absy
00791                 if (absy > absz)
00792                     return y > 0 ? Vector3::UNIT_Y : Vector3::NEGATIVE_UNIT_Y;
00793                 else
00794                     return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
00795 
00796 
00797         }
00798 
00799         // special points
00800         static const Vector3 ZERO;
00801         static const Vector3 UNIT_X;
00802         static const Vector3 UNIT_Y;
00803         static const Vector3 UNIT_Z;
00804         static const Vector3 NEGATIVE_UNIT_X;
00805         static const Vector3 NEGATIVE_UNIT_Y;
00806         static const Vector3 NEGATIVE_UNIT_Z;
00807         static const Vector3 UNIT_SCALE;
00808 
00811         inline _OgreExport friend std::ostream& operator <<
00812             ( std::ostream& o, const Vector3& v )
00813         {
00814             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00815             return o;
00816         }
00817     };
00821 }
00822 #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 Mon Jul 27 2020 13:40:48