# 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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Feb 12 12:59:54 2006