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( Real fX, Real fY, Real fZ ) 
00058             : x( fX ), y( fY ), z( fZ )
00059         {
00060         }
00061 
00062         inline Vector3( Real afCoordinate[3] )
00063             : x( afCoordinate[0] ),
00064               y( afCoordinate[1] ),
00065               z( afCoordinate[2] )
00066         {
00067         }
00068 
00069         inline Vector3( int afCoordinate[3] )
00070         {
00071             x = (Real)afCoordinate[0];
00072             y = (Real)afCoordinate[1];
00073             z = (Real)afCoordinate[2];
00074         }
00075 
00076         inline Vector3( const Real* const r )
00077             : x( r[0] ), y( r[1] ), z( r[2] )
00078         {
00079         }
00080 
00081         inline Vector3( const Vector3& rkVector )
00082             : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
00083         {
00084         }
00085 
00086         inline Real operator [] ( size_t i ) const
00087         {
00088             assert( i < 3 );
00089 
00090             return *(&x+i);
00091         }
00092 
00093         inline Real& operator [] ( size_t i )
00094         {
00095             assert( i < 3 );
00096 
00097             return *(&x+i);
00098         }
00099 
00104         inline Vector3& operator = ( const Vector3& rkVector )
00105         {
00106             x = rkVector.x;
00107             y = rkVector.y;
00108             z = rkVector.z;            
00109 
00110             return *this;
00111         }
00112 
00113         inline bool operator == ( const Vector3& rkVector ) const
00114         {
00115             return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00116         }
00117 
00118         inline bool operator != ( const Vector3& rkVector ) const
00119         {
00120             return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00121         }
00122 
00123         // arithmetic operations
00124         inline Vector3 operator + ( const Vector3& rkVector ) const
00125         {
00126             Vector3 kSum;
00127 
00128             kSum.x = x + rkVector.x;
00129             kSum.y = y + rkVector.y;
00130             kSum.z = z + rkVector.z;
00131 
00132             return kSum;
00133         }
00134 
00135         inline Vector3 operator - ( const Vector3& rkVector ) const
00136         {
00137             Vector3 kDiff;
00138 
00139             kDiff.x = x - rkVector.x;
00140             kDiff.y = y - rkVector.y;
00141             kDiff.z = z - rkVector.z;
00142 
00143             return kDiff;
00144         }
00145 
00146         inline Vector3 operator * ( Real fScalar ) const
00147         {
00148             Vector3 kProd;
00149 
00150             kProd.x = fScalar*x;
00151             kProd.y = fScalar*y;
00152             kProd.z = fScalar*z;
00153 
00154             return kProd;
00155         }
00156 
00157         inline Vector3 operator * ( const Vector3& rhs) const
00158         {
00159             Vector3 kProd;
00160 
00161             kProd.x = rhs.x * x;
00162             kProd.y = rhs.y * y;
00163             kProd.z = rhs.z * z;
00164 
00165             return kProd;
00166         }
00167 
00168         inline Vector3 operator / ( Real fScalar ) const
00169         {
00170             assert( fScalar != 0.0 );
00171 
00172             Vector3 kDiv;
00173 
00174             Real fInv = 1.0 / fScalar;
00175             kDiv.x = x * fInv;
00176             kDiv.y = y * fInv;
00177             kDiv.z = z * fInv;
00178 
00179             return kDiv;
00180         }
00181 
00182         inline Vector3 operator / ( const Vector3& rhs) const
00183         {
00184             Vector3 kDiv;
00185 
00186             kDiv.x = x / rhs.x;
00187             kDiv.y = y / rhs.y;
00188             kDiv.z = z / rhs.z;
00189 
00190             return kDiv;
00191         }
00192 
00193 
00194         inline Vector3 operator - () const
00195         {
00196             Vector3 kNeg;
00197 
00198             kNeg.x = -x;
00199             kNeg.y = -y;
00200             kNeg.z = -z;
00201 
00202             return kNeg;
00203         }
00204 
00205         inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
00206         {
00207             Vector3 kProd;
00208 
00209             kProd.x = fScalar * rkVector.x;
00210             kProd.y = fScalar * rkVector.y;
00211             kProd.z = fScalar * rkVector.z;
00212 
00213             return kProd;
00214         }
00215 
00216         // arithmetic updates
00217         inline Vector3& operator += ( const Vector3& rkVector )
00218         {
00219             x += rkVector.x;
00220             y += rkVector.y;
00221             z += rkVector.z;
00222 
00223             return *this;
00224         }
00225 
00226         inline Vector3& operator -= ( const Vector3& rkVector )
00227         {
00228             x -= rkVector.x;
00229             y -= rkVector.y;
00230             z -= rkVector.z;
00231 
00232             return *this;
00233         }
00234 
00235         inline Vector3& operator *= ( Real fScalar )
00236         {
00237             x *= fScalar;
00238             y *= fScalar;
00239             z *= fScalar;
00240             return *this;
00241         }
00242 
00243         inline Vector3& operator *= ( const Vector3& rkVector )
00244         {
00245             x *= rkVector.x;
00246             y *= rkVector.y;
00247             z *= rkVector.z;
00248 
00249             return *this;
00250         }
00251 
00252         inline Vector3& operator /= ( Real fScalar )
00253         {
00254             assert( fScalar != 0.0 );
00255 
00256             Real fInv = 1.0 / fScalar;
00257 
00258             x *= fInv;
00259             y *= fInv;
00260             z *= fInv;
00261 
00262             return *this;
00263         }
00264 
00265         inline Vector3& operator /= ( const Vector3& rkVector )
00266         {
00267             x /= rkVector.x;
00268             y /= rkVector.y;
00269             z /= rkVector.z;
00270 
00271             return *this;
00272         }
00273 
00274 
00282         inline Real length () const
00283         {
00284             return Math::Sqrt( x * x + y * y + z * z );
00285         }
00286 
00297         inline Real squaredLength () const
00298         {
00299             return x * x + y * y + z * z;
00300         }
00301 
00316         inline Real dotProduct(const Vector3& vec) const
00317         {
00318             return x * vec.x + y * vec.y + z * vec.z;
00319         }
00320 
00330         inline Real normalise()
00331         {
00332             Real fLength = Math::Sqrt( x * x + y * y + z * z );
00333 
00334             // Will also work for zero-sized vectors, but will change nothing
00335             if ( fLength > 1e-08 )
00336             {
00337                 Real fInvLength = 1.0 / fLength;
00338                 x *= fInvLength;
00339                 y *= fInvLength;
00340                 z *= fInvLength;
00341             }
00342 
00343             return fLength;
00344         }
00345 
00373         inline Vector3 crossProduct( const Vector3& rkVector ) const
00374         {
00375             Vector3 kCross;
00376 
00377             kCross.x = y * rkVector.z - z * rkVector.y;
00378             kCross.y = z * rkVector.x - x * rkVector.z;
00379             kCross.z = x * rkVector.y - y * rkVector.x;
00380 
00381             return kCross;
00382         }
00383 
00387         inline Vector3 midPoint( const Vector3& vec ) const
00388         {
00389             return Vector3( 
00390                 ( x + vec.x ) * 0.5, 
00391                 ( y + vec.y ) * 0.5, 
00392                 ( z + vec.z ) * 0.5 );
00393         }
00394 
00398         inline bool operator < ( const Vector3& rhs ) const
00399         {
00400             if( x < rhs.x && y < rhs.y && z < rhs.z )
00401                 return true;
00402             return false;
00403         }
00404 
00408         inline bool operator > ( const Vector3& rhs ) const
00409         {
00410             if( x > rhs.x && y > rhs.y && z > rhs.z )
00411                 return true;
00412             return false;
00413         }
00414 
00422         inline void makeFloor( const Vector3& cmp )
00423         {
00424             if( cmp.x < x ) x = cmp.x;
00425             if( cmp.y < y ) y = cmp.y;
00426             if( cmp.z < z ) z = cmp.z;
00427         }
00428 
00436         inline void makeCeil( const Vector3& cmp )
00437         {
00438             if( cmp.x > x ) x = cmp.x;
00439             if( cmp.y > y ) y = cmp.y;
00440             if( cmp.z > z ) z = cmp.z;
00441         }
00442 
00450         inline Vector3 perpendicular(void) const
00451         {
00452             static const Real fSquareZero = 1e-06 * 1e-06;
00453 
00454             Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00455 
00456             // Check length
00457             if( perp.squaredLength() < fSquareZero )
00458             {
00459                 /* This vector is the Y axis multiplied by a scalar, so we have 
00460                    to use another axis.
00461                 */
00462                 perp = this->crossProduct( Vector3::UNIT_Y );
00463             }
00464 
00465             return perp;
00466         }
00486         inline Vector3 randomDeviant(
00487             const Radian& angle,
00488             const Vector3& up = Vector3::ZERO ) const
00489         {
00490             Vector3 newUp;
00491 
00492             if (up == Vector3::ZERO)
00493             {
00494                 // Generate an up vector
00495                 newUp = this->perpendicular();
00496             }
00497             else
00498             {
00499                 newUp = up;
00500             }
00501 
00502             // Rotate up vector by random amount around this
00503             Quaternion q;
00504             q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
00505             newUp = q * newUp;
00506 
00507             // Finally rotate this by given angle around randomised up
00508             q.FromAngleAxis( angle, newUp );
00509             return q * (*this);
00510         }
00511 #ifndef OGRE_FORCE_ANGLE_TYPES
00512         inline Vector3 randomDeviant(
00513             Real angle,
00514             const Vector3& up = Vector3::ZERO ) const
00515         {
00516             return randomDeviant ( Radian(angle), up );
00517         }
00518 #endif//OGRE_FORCE_ANGLE_TYPES
00519 
00526         Quaternion getRotationTo(const Vector3& dest) const
00527         {
00528             // Based on Stan Melax's article in Game Programming Gems
00529             Quaternion q;
00530             // Copy, since cannot modify local
00531             Vector3 v0 = *this;
00532             Vector3 v1 = dest;
00533             v0.normalise();
00534             v1.normalise();
00535 
00536             Vector3 c = v0.crossProduct(v1);
00537 
00538             Real d = v0.dotProduct(v1);
00539             // If dot == 1, vectors are the same
00540             if (d >= 1.0f)
00541             {
00542                 return Quaternion::IDENTITY;
00543             }
00544             // NB if the crossProduct approaches zero, we get unstable because ANY axis will do
00545             // when v0 == -v1
00546             if (c.isZeroLength())
00547             {
00548                 Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
00549                 if (axis.isZeroLength()) // pick another if colinear
00550                     axis = Vector3::UNIT_Y.crossProduct(*this);
00551                 axis.normalise();
00552                 Quaternion ret;
00553                 ret.FromAngleAxis(Radian(Math::PI), axis);
00554                 return ret;
00555             }
00556             Real s = Math::Sqrt( (1+d)*2 );
00557             assert (s != 0 && "Divide by zero!");
00558             Real invs = 1 / s;
00559 
00560 
00561             q.x = c.x * invs;
00562             q.y = c.y * invs;
00563             q.z = c.z * invs;
00564             q.w = s * 0.5;
00565             return q;
00566         }
00567 
00569         inline bool isZeroLength(void) const
00570         {
00571             Real sqlen = (x * x) + (y * y) + (z * z);
00572             return (sqlen < (1e-06 * 1e-06));
00573 
00574         }
00575 
00578         inline Vector3 normalisedCopy(void) const
00579         {
00580             Vector3 ret = *this;
00581             ret.normalise();
00582             return ret;
00583         }
00584 
00588         inline Vector3 reflect(const Vector3& normal) const
00589         {
00590             return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00591         }
00592 
00599         inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
00600         {
00601             return Math::RealEqual(x, rhs.x, tolerance) &&
00602                 Math::RealEqual(y, rhs.y, tolerance) &&
00603                 Math::RealEqual(z, rhs.z, tolerance);
00604             
00605         }
00612         inline bool directionEquals(const Vector3& rhs, 
00613             const Radian& tolerance) const
00614         {
00615             Real dot = dotProduct(rhs);
00616             Radian angle = Math::ACos(dot);
00617 
00618             return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
00619             
00620         }
00621 
00622         // special points
00623         static const Vector3 ZERO;
00624         static const Vector3 UNIT_X;
00625         static const Vector3 UNIT_Y;
00626         static const Vector3 UNIT_Z;
00627         static const Vector3 NEGATIVE_UNIT_X;
00628         static const Vector3 NEGATIVE_UNIT_Y;
00629         static const Vector3 NEGATIVE_UNIT_Z;
00630         static const Vector3 UNIT_SCALE;
00631 
00634         inline _OgreExport friend std::ostream& operator <<
00635             ( std::ostream& o, const Vector3& v )
00636         {
00637             o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00638             return o;
00639         }
00640     };
00641 
00642 }
00643 #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 Feb 12 12:59:54 2006