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 © 2000-2002 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 [] ( unsigned i ) const 00087 { 00088 assert( i < 3 ); 00089 00090 return *(&x+i); 00091 } 00092 00093 inline Real& operator [] ( unsigned 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 00183 { 00184 Vector3 kNeg; 00185 00186 kNeg.x = -x; 00187 kNeg.y = -y; 00188 kNeg.z = -z; 00189 00190 return kNeg; 00191 } 00192 00193 inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector ) 00194 { 00195 Vector3 kProd; 00196 00197 kProd.x = fScalar * rkVector.x; 00198 kProd.y = fScalar * rkVector.y; 00199 kProd.z = fScalar * rkVector.z; 00200 00201 return kProd; 00202 } 00203 00204 // arithmetic updates 00205 inline Vector3& operator += ( const Vector3& rkVector ) 00206 { 00207 x += rkVector.x; 00208 y += rkVector.y; 00209 z += rkVector.z; 00210 00211 return *this; 00212 } 00213 00214 inline Vector3& operator -= ( const Vector3& rkVector ) 00215 { 00216 x -= rkVector.x; 00217 y -= rkVector.y; 00218 z -= rkVector.z; 00219 00220 return *this; 00221 } 00222 00223 inline Vector3& operator *= ( Real fScalar ) 00224 { 00225 x *= fScalar; 00226 y *= fScalar; 00227 z *= fScalar; 00228 return *this; 00229 } 00230 00231 inline Vector3& operator /= ( Real fScalar ) 00232 { 00233 assert( fScalar != 0.0 ); 00234 00235 Real fInv = 1.0 / fScalar; 00236 00237 x *= fInv; 00238 y *= fInv; 00239 z *= fInv; 00240 00241 return *this; 00242 } 00243 00251 inline Real length () const 00252 { 00253 return Math::Sqrt( x * x + y * y + z * z ); 00254 } 00255 00266 inline Real squaredLength () const 00267 { 00268 return x * x + y * y + z * z; 00269 } 00270 00285 inline Real dotProduct(const Vector3& vec) const 00286 { 00287 return x * vec.x + y * vec.y + z * vec.z; 00288 } 00289 00299 inline Real normalise() 00300 { 00301 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00302 00303 // Will also work for zero-sized vectors, but will change nothing 00304 if ( fLength > 1e-06 ) 00305 { 00306 Real fInvLength = 1.0 / fLength; 00307 x *= fInvLength; 00308 y *= fInvLength; 00309 z *= fInvLength; 00310 } 00311 00312 return fLength; 00313 } 00314 00342 inline Vector3 crossProduct( const Vector3& rkVector ) const 00343 { 00344 Vector3 kCross; 00345 00346 kCross.x = y * rkVector.z - z * rkVector.y; 00347 kCross.y = z * rkVector.x - x * rkVector.z; 00348 kCross.z = x * rkVector.y - y * rkVector.x; 00349 00350 return kCross; 00351 } 00352 00356 inline Vector3 midPoint( const Vector3& vec ) const 00357 { 00358 return Vector3( 00359 ( x + vec.x ) * 0.5, 00360 ( y + vec.y ) * 0.5, 00361 ( z + vec.z ) * 0.5 ); 00362 } 00363 00367 inline bool operator < ( const Vector3& rhs ) const 00368 { 00369 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00370 return true; 00371 return false; 00372 } 00373 00377 inline bool operator > ( const Vector3& rhs ) const 00378 { 00379 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00380 return true; 00381 return false; 00382 } 00383 00391 inline void makeFloor( const Vector3& cmp ) 00392 { 00393 if( cmp.x < x ) x = cmp.x; 00394 if( cmp.y < y ) y = cmp.y; 00395 if( cmp.z < z ) z = cmp.z; 00396 } 00397 00405 inline void makeCeil( const Vector3& cmp ) 00406 { 00407 if( cmp.x > x ) x = cmp.x; 00408 if( cmp.y > y ) y = cmp.y; 00409 if( cmp.z > z ) z = cmp.z; 00410 } 00411 00419 inline Vector3 perpendicular(void) const 00420 { 00421 static const Real fSquareZero = 1e-06 * 1e-06; 00422 00423 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00424 00425 // Check length 00426 if( perp.squaredLength() < fSquareZero ) 00427 { 00428 /* This vector is the Y axis multiplied by a scalar, so we have 00429 to use another axis. 00430 */ 00431 perp = this->crossProduct( Vector3::UNIT_Y ); 00432 } 00433 00434 return perp; 00435 } 00455 inline Vector3 randomDeviant( 00456 Real angle, 00457 const Vector3& up = Vector3::ZERO ) const 00458 { 00459 Vector3 newUp; 00460 00461 if (up == Vector3::ZERO) 00462 { 00463 // Generate an up vector 00464 newUp = this->perpendicular(); 00465 } 00466 else 00467 { 00468 newUp = up; 00469 } 00470 00471 // Rotate up vector by random amount around this 00472 Quaternion q; 00473 q.FromAngleAxis( Math::UnitRandom() * Math::TWO_PI, *this ); 00474 newUp = q * newUp; 00475 00476 // Finally rotate this by given angle around randomised up 00477 q.FromAngleAxis( angle, newUp ); 00478 return q * (*this); 00479 } 00480 00487 Quaternion getRotationTo(const Vector3& dest) const 00488 { 00489 // Based on Stan Melax's article in Game Programming Gems 00490 Quaternion q; 00491 // Copy, since cannot modify local 00492 Vector3 v0 = *this; 00493 Vector3 v1 = dest; 00494 v0.normalise(); 00495 v1.normalise(); 00496 00497 Vector3 c = v0.crossProduct(v1); 00498 00499 // NB if the crossProduct approaches zero, we get unstable because ANY axis will do 00500 // when v0 == -v1 00501 Real d = v0.dotProduct(v1); 00502 // If dot == 1, vectors are the same 00503 if (d >= 1.0f) 00504 { 00505 return Quaternion::IDENTITY; 00506 } 00507 Real s = Math::Sqrt( (1+d)*2 ); 00508 Real invs = 1 / s; 00509 00510 00511 q.x = c.x * invs; 00512 q.y = c.y * invs; 00513 q.z = c.z * invs; 00514 q.w = s * 0.5; 00515 return q; 00516 } 00517 00519 inline bool isZeroLength(void) const 00520 { 00521 Real sqlen = (x * x) + (y * y) + (z * z); 00522 return (sqlen < (1e-06 * 1e-06)); 00523 00524 } 00525 00528 inline Vector3 normalisedCopy(void) const 00529 { 00530 Vector3 ret = *this; 00531 ret.normalise(); 00532 return ret; 00533 } 00534 00538 inline Vector3 reflect(const Vector3& normal) 00539 { 00540 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00541 } 00542 00543 // special points 00544 static const Vector3 ZERO; 00545 static const Vector3 UNIT_X; 00546 static const Vector3 UNIT_Y; 00547 static const Vector3 UNIT_Z; 00548 static const Vector3 UNIT_SCALE; 00549 00552 inline _OgreExport friend std::ostream& operator << 00553 ( std::ostream& o, const Vector3& v ) 00554 { 00555 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00556 return o; 00557 } 00558 }; 00559 00560 } 00561 #endif
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:31 2004