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 return Vector3( 00144 x + rkVector.x, 00145 y + rkVector.y, 00146 z + rkVector.z); 00147 } 00148 00149 inline Vector3 operator - ( const Vector3& rkVector ) const 00150 { 00151 return Vector3( 00152 x - rkVector.x, 00153 y - rkVector.y, 00154 z - rkVector.z); 00155 } 00156 00157 inline Vector3 operator * ( const Real fScalar ) const 00158 { 00159 return Vector3( 00160 x * fScalar, 00161 y * fScalar, 00162 z * fScalar); 00163 } 00164 00165 inline Vector3 operator * ( const Vector3& rhs) const 00166 { 00167 return Vector3( 00168 x * rhs.x, 00169 y * rhs.y, 00170 z * rhs.z); 00171 } 00172 00173 inline Vector3 operator / ( const Real fScalar ) const 00174 { 00175 assert( fScalar != 0.0 ); 00176 00177 Real fInv = 1.0 / fScalar; 00178 00179 return Vector3( 00180 x * fInv, 00181 y * fInv, 00182 z * fInv); 00183 } 00184 00185 inline Vector3 operator / ( const Vector3& rhs) const 00186 { 00187 return Vector3( 00188 x / rhs.x, 00189 y / rhs.y, 00190 z / rhs.z); 00191 } 00192 00193 inline const Vector3& operator + () const 00194 { 00195 return *this; 00196 } 00197 00198 inline Vector3 operator - () const 00199 { 00200 return Vector3(-x, -y, -z); 00201 } 00202 00203 // overloaded operators to help Vector3 00204 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00205 { 00206 return Vector3( 00207 fScalar * rkVector.x, 00208 fScalar * rkVector.y, 00209 fScalar * rkVector.z); 00210 } 00211 00212 inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector ) 00213 { 00214 return Vector3( 00215 fScalar / rkVector.x, 00216 fScalar / rkVector.y, 00217 fScalar / rkVector.z); 00218 } 00219 00220 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00221 { 00222 return Vector3( 00223 lhs.x + rhs, 00224 lhs.y + rhs, 00225 lhs.z + rhs); 00226 } 00227 00228 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00229 { 00230 return Vector3( 00231 lhs + rhs.x, 00232 lhs + rhs.y, 00233 lhs + rhs.z); 00234 } 00235 00236 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00237 { 00238 return Vector3( 00239 lhs.x - rhs, 00240 lhs.y - rhs, 00241 lhs.z - rhs); 00242 } 00243 00244 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00245 { 00246 return Vector3( 00247 lhs - rhs.x, 00248 lhs - rhs.y, 00249 lhs - rhs.z); 00250 } 00251 00252 // arithmetic updates 00253 inline Vector3& operator += ( const Vector3& rkVector ) 00254 { 00255 x += rkVector.x; 00256 y += rkVector.y; 00257 z += rkVector.z; 00258 00259 return *this; 00260 } 00261 00262 inline Vector3& operator += ( const Real fScalar ) 00263 { 00264 x += fScalar; 00265 y += fScalar; 00266 z += fScalar; 00267 return *this; 00268 } 00269 00270 inline Vector3& operator -= ( const Vector3& rkVector ) 00271 { 00272 x -= rkVector.x; 00273 y -= rkVector.y; 00274 z -= rkVector.z; 00275 00276 return *this; 00277 } 00278 00279 inline Vector3& operator -= ( const Real fScalar ) 00280 { 00281 x -= fScalar; 00282 y -= fScalar; 00283 z -= fScalar; 00284 return *this; 00285 } 00286 00287 inline Vector3& operator *= ( const Real fScalar ) 00288 { 00289 x *= fScalar; 00290 y *= fScalar; 00291 z *= fScalar; 00292 return *this; 00293 } 00294 00295 inline Vector3& operator *= ( const Vector3& rkVector ) 00296 { 00297 x *= rkVector.x; 00298 y *= rkVector.y; 00299 z *= rkVector.z; 00300 00301 return *this; 00302 } 00303 00304 inline Vector3& operator /= ( const Real fScalar ) 00305 { 00306 assert( fScalar != 0.0 ); 00307 00308 Real fInv = 1.0 / fScalar; 00309 00310 x *= fInv; 00311 y *= fInv; 00312 z *= fInv; 00313 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 00334 inline Real length () const 00335 { 00336 return Math::Sqrt( x * x + y * y + z * z ); 00337 } 00338 00349 inline Real squaredLength () const 00350 { 00351 return x * x + y * y + z * z; 00352 } 00353 00368 inline Real dotProduct(const Vector3& vec) const 00369 { 00370 return x * vec.x + y * vec.y + z * vec.z; 00371 } 00372 00382 inline Real normalise() 00383 { 00384 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00385 00386 // Will also work for zero-sized vectors, but will change nothing 00387 if ( fLength > 1e-08 ) 00388 { 00389 Real fInvLength = 1.0 / fLength; 00390 x *= fInvLength; 00391 y *= fInvLength; 00392 z *= fInvLength; 00393 } 00394 00395 return fLength; 00396 } 00397 00426 inline Vector3 crossProduct( const Vector3& rkVector ) const 00427 { 00428 return Vector3( 00429 y * rkVector.z - z * rkVector.y, 00430 z * rkVector.x - x * rkVector.z, 00431 x * rkVector.y - y * rkVector.x); 00432 } 00433 00437 inline Vector3 midPoint( const Vector3& vec ) const 00438 { 00439 return Vector3( 00440 ( x + vec.x ) * 0.5, 00441 ( y + vec.y ) * 0.5, 00442 ( z + vec.z ) * 0.5 ); 00443 } 00444 00448 inline bool operator < ( const Vector3& rhs ) const 00449 { 00450 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00451 return true; 00452 return false; 00453 } 00454 00458 inline bool operator > ( const Vector3& rhs ) const 00459 { 00460 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00461 return true; 00462 return false; 00463 } 00464 00472 inline void makeFloor( const Vector3& cmp ) 00473 { 00474 if( cmp.x < x ) x = cmp.x; 00475 if( cmp.y < y ) y = cmp.y; 00476 if( cmp.z < z ) z = cmp.z; 00477 } 00478 00486 inline void makeCeil( const Vector3& cmp ) 00487 { 00488 if( cmp.x > x ) x = cmp.x; 00489 if( cmp.y > y ) y = cmp.y; 00490 if( cmp.z > z ) z = cmp.z; 00491 } 00492 00500 inline Vector3 perpendicular(void) const 00501 { 00502 static const Real fSquareZero = 1e-06 * 1e-06; 00503 00504 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00505 00506 // Check length 00507 if( perp.squaredLength() < fSquareZero ) 00508 { 00509 /* This vector is the Y axis multiplied by a scalar, so we have 00510 to use another axis. 00511 */ 00512 perp = this->crossProduct( Vector3::UNIT_Y ); 00513 } 00514 00515 return perp; 00516 } 00536 inline Vector3 randomDeviant( 00537 const Radian& angle, 00538 const Vector3& up = Vector3::ZERO ) const 00539 { 00540 Vector3 newUp; 00541 00542 if (up == Vector3::ZERO) 00543 { 00544 // Generate an up vector 00545 newUp = this->perpendicular(); 00546 } 00547 else 00548 { 00549 newUp = up; 00550 } 00551 00552 // Rotate up vector by random amount around this 00553 Quaternion q; 00554 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00555 newUp = q * newUp; 00556 00557 // Finally rotate this by given angle around randomised up 00558 q.FromAngleAxis( angle, newUp ); 00559 return q * (*this); 00560 } 00561 #ifndef OGRE_FORCE_ANGLE_TYPES 00562 inline Vector3 randomDeviant( 00563 Real angle, 00564 const Vector3& up = Vector3::ZERO ) const 00565 { 00566 return randomDeviant ( Radian(angle), up ); 00567 } 00568 #endif//OGRE_FORCE_ANGLE_TYPES 00569 00578 Quaternion getRotationTo(const Vector3& dest, 00579 const Vector3& fallbackAxis = Vector3::ZERO) const 00580 { 00581 // Based on Stan Melax's article in Game Programming Gems 00582 Quaternion q; 00583 // Copy, since cannot modify local 00584 Vector3 v0 = *this; 00585 Vector3 v1 = dest; 00586 v0.normalise(); 00587 v1.normalise(); 00588 00589 Real d = v0.dotProduct(v1); 00590 // If dot == 1, vectors are the same 00591 if (d >= 1.0f) 00592 { 00593 return Quaternion::IDENTITY; 00594 } 00595 Real s = Math::Sqrt( (1+d)*2 ); 00596 if (s < 1e-6f) 00597 { 00598 if (fallbackAxis != Vector3::ZERO) 00599 { 00600 // rotate 180 degrees about the fallback axis 00601 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00602 } 00603 else 00604 { 00605 // Generate an axis 00606 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00607 if (axis.isZeroLength()) // pick another if colinear 00608 axis = Vector3::UNIT_Y.crossProduct(*this); 00609 axis.normalise(); 00610 q.FromAngleAxis(Radian(Math::PI), axis); 00611 } 00612 } 00613 else 00614 { 00615 Real invs = 1 / s; 00616 00617 Vector3 c = v0.crossProduct(v1); 00618 00619 q.x = c.x * invs; 00620 q.y = c.y * invs; 00621 q.z = c.z * invs; 00622 q.w = s * 0.5; 00623 q.normalise(); 00624 } 00625 return q; 00626 } 00627 00629 inline bool isZeroLength(void) const 00630 { 00631 Real sqlen = (x * x) + (y * y) + (z * z); 00632 return (sqlen < (1e-06 * 1e-06)); 00633 00634 } 00635 00638 inline Vector3 normalisedCopy(void) const 00639 { 00640 Vector3 ret = *this; 00641 ret.normalise(); 00642 return ret; 00643 } 00644 00648 inline Vector3 reflect(const Vector3& normal) const 00649 { 00650 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00651 } 00652 00659 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00660 { 00661 return Math::RealEqual(x, rhs.x, tolerance) && 00662 Math::RealEqual(y, rhs.y, tolerance) && 00663 Math::RealEqual(z, rhs.z, tolerance); 00664 00665 } 00672 inline bool directionEquals(const Vector3& rhs, 00673 const Radian& tolerance) const 00674 { 00675 Real dot = dotProduct(rhs); 00676 Radian angle = Math::ACos(dot); 00677 00678 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00679 00680 } 00681 00682 // special points 00683 static const Vector3 ZERO; 00684 static const Vector3 UNIT_X; 00685 static const Vector3 UNIT_Y; 00686 static const Vector3 UNIT_Z; 00687 static const Vector3 NEGATIVE_UNIT_X; 00688 static const Vector3 NEGATIVE_UNIT_Y; 00689 static const Vector3 NEGATIVE_UNIT_Z; 00690 static const Vector3 UNIT_SCALE; 00691 00694 inline _OgreExport friend std::ostream& operator << 00695 ( std::ostream& o, const Vector3& v ) 00696 { 00697 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00698 return o; 00699 } 00700 }; 00701 00702 } 00703 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Nov 12 10:50:14 2006