Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

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-2005 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #ifndef __Vector3_H__
00026 #define __Vector3_H__
00027 
00028 #include "OgrePrerequisites.h"
00029 #include "OgreMath.h"
00030 #include "OgreQuaternion.h"
00031 
00032 namespace Ogre
00033 {
00034 
00042     class _OgreExport Vector3
00043     {
00044     public:
00045         union {
00046             struct {
00047                 Real x, y, z;
00048             };
00049             Real val[3];
00050         };
00051 
00052     public:
00053         inline Vector3()
00054         {
00055         }
00056 
00057         inline Vector3( const Real fX, const Real fY, const Real fZ )
00058             : x( fX ), y( fY ), z( fZ )
00059         {
00060         }
00061 
00062         inline explicit Vector3( const Real afCoordinate[3] )
00063             : x( afCoordinate[0] ),
00064               y( afCoordinate[1] ),
00065               z( afCoordinate[2] )
00066         {
00067         }
00068 
00069         inline explicit Vector3( const int afCoordinate[3] )
00070         {
00071             x = (Real)afCoordinate[0];
00072             y = (Real)afCoordinate[1];
00073             z = (Real)afCoordinate[2];
00074         }
00075 
00076         inline explicit Vector3( Real* const r )
00077             : x( r[0] ), y( r[1] ), z( r[2] )
00078         {
00079         }
00080 
00081         inline explicit Vector3( const Real scaler )
00082             : x( scaler )
00083             , y( scaler )
00084             , z( scaler )
00085         {
00086         }
00087 
00088 
00089         inline Vector3( const Vector3& rkVector )
00090             : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
00091         {
00092         }
00093 
00094         inline Real operator [] ( const size_t i ) const
00095         {
00096             assert( i < 3 );
00097 
00098             return *(&x+i);
00099         }
00100 
00101         inline Real& operator [] ( const size_t i )
00102         {
00103             assert( i < 3 );
00104 
00105             return *(&x+i);
00106         }
00107 
00112         inline Vector3& operator = ( const Vector3& rkVector )
00113         {
00114             x = rkVector.x;
00115             y = rkVector.y;
00116             z = rkVector.z;
00117 
00118             return *this;
00119         }
00120 
00121         inline Vector3& operator = ( const Real fScaler )
00122         {
00123             x = fScaler;
00124             y = fScaler;
00125             z = fScaler;
00126 
00127             return *this;
00128         }
00129 
00130         inline bool operator == ( const Vector3& rkVector ) const
00131         {
00132             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00133         }
00134 
00135         inline bool operator != ( const Vector3& rkVector ) const
00136         {
00137             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00138         }
00139 
00140         // arithmetic operations
00141         inline Vector3 operator + ( const Vector3& rkVector ) const
00142         {
00143             Vector3 kSum;
00144 
00145             kSum.x = x + rkVector.x;
00146             kSum.y = y + rkVector.y;
00147             kSum.z = z + rkVector.z;
00148 
00149             return kSum;
00150         }
00151 
00152         inline Vector3 operator - ( const Vector3& rkVector ) const
00153         {
00154             Vector3 kDiff;
00155 
00156             kDiff.x = x - rkVector.x;
00157             kDiff.y = y - rkVector.y;
00158             kDiff.z = z - rkVector.z;
00159 
00160             return kDiff;
00161         }
00162 
00163         inline Vector3 operator * ( const Real fScalar ) const
00164         {
00165             Vector3 kProd;
00166 
00167             kProd.x = fScalar*x;
00168             kProd.y = fScalar*y;
00169             kProd.z = fScalar*z;
00170 
00171             return kProd;
00172         }
00173 
00174         inline Vector3 operator * ( const Vector3& rhs) const
00175         {
00176             Vector3 kProd;
00177 
00178             kProd.x = rhs.x * x;
00179             kProd.y = rhs.y * y;
00180             kProd.z = rhs.z * z;
00181 
00182             return kProd;
00183         }
00184 
00185         inline Vector3 operator / ( const Real fScalar ) const
00186         {
00187             assert( fScalar != 0.0 );
00188 
00189             Vector3 kDiv;
00190 
00191             Real fInv = 1.0 / fScalar;
00192             kDiv.x = x * fInv;
00193             kDiv.y = y * fInv;
00194             kDiv.z = z * fInv;
00195 
00196             return kDiv;
00197         }
00198 
00199         inline Vector3 operator / ( const Vector3& rhs) const
00200         {
00201             Vector3 kDiv;
00202 
00203             kDiv.x = x / rhs.x;
00204             kDiv.y = y / rhs.y;
00205             kDiv.z = z / rhs.z;
00206 
00207             return kDiv;
00208         }
00209 
00210 
00211         inline Vector3 operator - () const
00212         {
00213             Vector3 kNeg;
00214 
00215             kNeg.x = -x;
00216             kNeg.y = -y;
00217             kNeg.z = -z;
00218 
00219             return kNeg;
00220         }
00221 
00222         // overloaded operators to help Vector3
00223         inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
00224         {
00225             Vector3 kProd;
00226 
00227             kProd.x = fScalar * rkVector.x;
00228             kProd.y = fScalar * rkVector.y;
00229             kProd.z = fScalar * rkVector.z;
00230 
00231             return kProd;
00232         }
00233 
00234         inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
00235         {
00236             Vector3 ret(rhs);
00237             return ret += lhs;
00238         }
00239 
00240         inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
00241         {
00242             Vector3 ret(lhs);
00243             return ret += rhs;
00244         }
00245 
00246         inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
00247         {
00248             return lhs - Vector3(rhs);
00249         }
00250 
00251         inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
00252         {
00253             Vector3 ret(lhs);
00254             return ret -= rhs;
00255         }
00256 
00257         // arithmetic updates
00258         inline Vector3& operator += ( const Vector3& rkVector )
00259         {
00260             x += rkVector.x;
00261             y += rkVector.y;
00262             z += rkVector.z;
00263 
00264             return *this;
00265         }
00266 
00267         inline Vector3& operator += ( const Real fScalar )
00268         {
00269             x += fScalar;
00270             y += fScalar;
00271             z += fScalar;
00272             return *this;
00273         }
00274 
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 Real fScalar )
00293         {
00294             x *= fScalar;
00295             y *= fScalar;
00296             z *= fScalar;
00297             return *this;
00298         }
00299 
00300         inline Vector3& operator *= ( const Vector3& rkVector )
00301         {
00302             x *= rkVector.x;
00303             y *= rkVector.y;
00304             z *= rkVector.z;
00305 
00306             return *this;
00307         }
00308 
00309         inline Vector3& operator /= ( const Real fScalar )
00310         {
00311             assert( fScalar != 0.0 );
00312 
00313             Real fInv = 1.0 / fScalar;
00314 
00315             x *= fInv;
00316             y *= fInv;
00317             z *= fInv;
00318 
00319             return *this;
00320         }
00321 
00322         inline Vector3& operator /= ( const Vector3& rkVector )
00323         {
00324             x /= rkVector.x;
00325             y /= rkVector.y;
00326             z /= rkVector.z;
00327 
00328             return *this;
00329         }
00330 
00331 
00339         inline Real length () const
00340         {
00341             return Math::Sqrt( x * x + y * y + z * z );
00342         }
00343 
00354         inline Real squaredLength () const
00355         {
00356             return x * x + y * y + z * z;
00357         }
00358 
00373         inline Real dotProduct(const Vector3& vec) const
00374         {
00375             return x * vec.x + y * vec.y + z * vec.z;
00376         }
00377 
00387         inline Real normalise()
00388         {
00389             Real fLength = Math::Sqrt( x * x + y * y + z * z );
00390 
00391             // Will also work for zero-sized vectors, but will change nothing
00392             if ( fLength > 1e-08 )
00393             {
00394                 Real fInvLength = 1.0 / fLength;
00395                 x *= fInvLength;
00396                 y *= fInvLength;
00397                 z *= fInvLength;
00398             }
00399 
00400             return fLength;
00401         }
00402 
00431         inline Vector3 crossProduct( const Vector3& rkVector ) const
00432         {
00433             Vector3 kCross;
00434 
00435             kCross.x = y * rkVector.z - z * rkVector.y;
00436             kCross.y = z * rkVector.x - x * rkVector.z;
00437             kCross.z = x * rkVector.y - y * rkVector.x;
00438 
00439             return kCross;
00440         }
00441 
00445         inline Vector3 midPoint( const Vector3& vec ) const
00446         {
00447             return Vector3(
00448                 ( x + vec.x ) * 0.5,
00449                 ( y + vec.y ) * 0.5,
00450                 ( z + vec.z ) * 0.5 );
00451         }
00452 
00456         inline bool operator < ( const Vector3& rhs ) const
00457         {
00458             if( x < rhs.x && y < rhs.y && z < rhs.z )
00459                 return true;
00460             return false;
00461         }
00462 
00466         inline bool operator > ( const Vector3& rhs ) const
00467         {
00468             if( x > rhs.x && y > rhs.y && z > rhs.z )
00469                 return true;
00470             return false;
00471         }
00472 
00480         inline void makeFloor( const Vector3& cmp )
00481         {
00482             if( cmp.x < x ) x = cmp.x;
00483             if( cmp.y < y ) y = cmp.y;
00484             if( cmp.z < z ) z = cmp.z;
00485         }
00486 
00494         inline void makeCeil( const Vector3& cmp )
00495         {
00496             if( cmp.x > x ) x = cmp.x;
00497             if( cmp.y > y ) y = cmp.y;
00498             if( cmp.z > z ) z = cmp.z;
00499         }
00500 
00508         inline Vector3 perpendicular(void) const
00509         {
00510             static const Real fSquareZero = 1e-06 * 1e-06;
00511 
00512             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00513 
00514             // Check length
00515             if( perp.squaredLength() < fSquareZero )
00516             {
00517                 /* This vector is the Y axis multiplied by a scalar, so we have
00518                    to use another axis.
00519                 */
00520                 perp = this->crossProduct( Vector3::UNIT_Y );
00521             }
00522 
00523             return perp;
00524         }
00544         inline Vector3 randomDeviant(
00545             const Radian& angle,
00546             const Vector3& up = Vector3::ZERO ) const
00547         {
00548             Vector3 newUp;
00549 
00550             if (up == Vector3::ZERO)
00551             {
00552                 // Generate an up vector
00553                 newUp = this->perpendicular();
00554             }
00555             else
00556             {
00557                 newUp = up;
00558             }
00559 
00560             // Rotate up vector by random amount around this
00561             Quaternion q;
00562             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
00563             newUp = q * newUp;
00564 
00565             // Finally rotate this by given angle around randomised up
00566             q.FromAngleAxis( angle, newUp );
00567             return q * (*this);
00568         }
00569 #ifndef OGRE_FORCE_ANGLE_TYPES
00570         inline Vector3 randomDeviant(
00571             Real angle,
00572             const Vector3& up = Vector3::ZERO ) const
00573         {
00574             return randomDeviant ( Radian(angle), up );
00575         }
00576 #endif//OGRE_FORCE_ANGLE_TYPES
00577 
00586         Quaternion getRotationTo(const Vector3& dest,
00587             const Vector3& fallbackAxis = Vector3::ZERO) const
00588         {
00589             // Based on Stan Melax's article in Game Programming Gems
00590             Quaternion q;
00591             // Copy, since cannot modify local
00592             Vector3 v0 = *this;
00593             Vector3 v1 = dest;
00594             v0.normalise();
00595             v1.normalise();
00596 
00597             Vector3 c = v0.crossProduct(v1);
00598 
00599             Real d = v0.dotProduct(v1);
00600             // If dot == 1, vectors are the same
00601             if (d >= 1.0f)
00602             {
00603                 return Quaternion::IDENTITY;
00604             }
00605             Real s = Math::Sqrt( (1+d)*2 );
00606             if (s < 1e-6f)
00607             {
00608                 if (fallbackAxis != Vector3::ZERO)
00609                 {
00610                     // rotate 180 degrees about the fallback axis
00611                     q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
00612                 }
00613                 else
00614                 {
00615                     // Generate an axis
00616                     Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
00617                     if (axis.isZeroLength()) // pick another if colinear
00618                         axis = Vector3::UNIT_Y.crossProduct(*this);
00619                     axis.normalise();
00620                     q.FromAngleAxis(Radian(Math::PI), axis);
00621                 }
00622             }
00623             else
00624             {
00625                 Real invs = 1 / s;
00626 
00627                 q.x = c.x * invs;
00628                 q.y = c.y * invs;
00629                 q.z = c.z * invs;
00630                 q.w = s * 0.5;
00631             }
00632             return q;
00633         }
00634 
00636         inline bool isZeroLength(void) const
00637         {
00638             Real sqlen = (x * x) + (y * y) + (z * z);
00639             return (sqlen < (1e-06 * 1e-06));
00640 
00641         }
00642 
00645         inline Vector3 normalisedCopy(void) const
00646         {
00647             Vector3 ret = *this;
00648             ret.normalise();
00649             return ret;
00650         }
00651 
00655         inline Vector3 reflect(const Vector3& normal) const
00656         {
00657             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00658         }
00659 
00666         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
00667         {
00668             return Math::RealEqual(x, rhs.x, tolerance) &&
00669                 Math::RealEqual(y, rhs.y, tolerance) &&
00670                 Math::RealEqual(z, rhs.z, tolerance);
00671 
00672         }
00679         inline bool directionEquals(const Vector3& rhs,
00680             const Radian& tolerance) const
00681         {
00682             Real dot = dotProduct(rhs);
00683             Radian angle = Math::ACos(dot);
00684 
00685             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
00686 
00687         }
00688 
00689         // special points
00690         static const Vector3 ZERO;
00691         static const Vector3 UNIT_X;
00692         static const Vector3 UNIT_Y;
00693         static const Vector3 UNIT_Z;
00694         static const Vector3 NEGATIVE_UNIT_X;
00695         static const Vector3 NEGATIVE_UNIT_Y;
00696         static const Vector3 NEGATIVE_UNIT_Z;
00697         static const Vector3 UNIT_SCALE;
00698 
00701         inline _OgreExport friend std::ostream& operator <<
00702             ( std::ostream& o, const Vector3& v )
00703         {
00704             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00705             return o;
00706         }
00707     };
00708 
00709 }
00710 #endif

Copyright © 2000-2005 by The OGRE Team
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:51 2006