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-2006 Torus Knot Software Ltd 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 You may alternatively use this source under the terms of a specific version of 00025 the OGRE Unrestricted License provided you have obtained such a license from 00026 Torus Knot Software Ltd. 00027 ----------------------------------------------------------------------------- 00028 */ 00029 #ifndef __Vector3_H__ 00030 #define __Vector3_H__ 00031 00032 #include "OgrePrerequisites.h" 00033 #include "OgreMath.h" 00034 #include "OgreQuaternion.h" 00035 00036 namespace Ogre 00037 { 00038 00046 class _OgreExport Vector3 00047 { 00048 public: 00049 Real x, y, z; 00050 00051 public: 00052 inline Vector3() 00053 { 00054 } 00055 00056 inline Vector3( const Real fX, const Real fY, const Real fZ ) 00057 : x( fX ), y( fY ), z( fZ ) 00058 { 00059 } 00060 00061 inline explicit Vector3( const Real afCoordinate[3] ) 00062 : x( afCoordinate[0] ), 00063 y( afCoordinate[1] ), 00064 z( afCoordinate[2] ) 00065 { 00066 } 00067 00068 inline explicit Vector3( const int afCoordinate[3] ) 00069 { 00070 x = (Real)afCoordinate[0]; 00071 y = (Real)afCoordinate[1]; 00072 z = (Real)afCoordinate[2]; 00073 } 00074 00075 inline explicit Vector3( Real* const r ) 00076 : x( r[0] ), y( r[1] ), z( r[2] ) 00077 { 00078 } 00079 00080 inline explicit Vector3( const Real scaler ) 00081 : x( scaler ) 00082 , y( scaler ) 00083 , z( scaler ) 00084 { 00085 } 00086 00087 00088 inline Real operator [] ( const size_t i ) const 00089 { 00090 assert( i < 3 ); 00091 00092 return *(&x+i); 00093 } 00094 00095 inline Real& operator [] ( const size_t i ) 00096 { 00097 assert( i < 3 ); 00098 00099 return *(&x+i); 00100 } 00102 inline Real* ptr() 00103 { 00104 return &x; 00105 } 00107 inline const Real* ptr() const 00108 { 00109 return &x; 00110 } 00111 00116 inline Vector3& operator = ( const Vector3& rkVector ) 00117 { 00118 x = rkVector.x; 00119 y = rkVector.y; 00120 z = rkVector.z; 00121 00122 return *this; 00123 } 00124 00125 inline Vector3& operator = ( const Real fScaler ) 00126 { 00127 x = fScaler; 00128 y = fScaler; 00129 z = fScaler; 00130 00131 return *this; 00132 } 00133 00134 inline bool operator == ( const Vector3& rkVector ) const 00135 { 00136 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00137 } 00138 00139 inline bool operator != ( const Vector3& rkVector ) const 00140 { 00141 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00142 } 00143 00144 // arithmetic operations 00145 inline Vector3 operator + ( const Vector3& rkVector ) const 00146 { 00147 return Vector3( 00148 x + rkVector.x, 00149 y + rkVector.y, 00150 z + rkVector.z); 00151 } 00152 00153 inline Vector3 operator - ( const Vector3& rkVector ) const 00154 { 00155 return Vector3( 00156 x - rkVector.x, 00157 y - rkVector.y, 00158 z - rkVector.z); 00159 } 00160 00161 inline Vector3 operator * ( const Real fScalar ) const 00162 { 00163 return Vector3( 00164 x * fScalar, 00165 y * fScalar, 00166 z * fScalar); 00167 } 00168 00169 inline Vector3 operator * ( const Vector3& rhs) const 00170 { 00171 return Vector3( 00172 x * rhs.x, 00173 y * rhs.y, 00174 z * rhs.z); 00175 } 00176 00177 inline Vector3 operator / ( const Real fScalar ) const 00178 { 00179 assert( fScalar != 0.0 ); 00180 00181 Real fInv = 1.0 / fScalar; 00182 00183 return Vector3( 00184 x * fInv, 00185 y * fInv, 00186 z * fInv); 00187 } 00188 00189 inline Vector3 operator / ( const Vector3& rhs) const 00190 { 00191 return Vector3( 00192 x / rhs.x, 00193 y / rhs.y, 00194 z / rhs.z); 00195 } 00196 00197 inline const Vector3& operator + () const 00198 { 00199 return *this; 00200 } 00201 00202 inline Vector3 operator - () const 00203 { 00204 return Vector3(-x, -y, -z); 00205 } 00206 00207 // overloaded operators to help Vector3 00208 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00209 { 00210 return Vector3( 00211 fScalar * rkVector.x, 00212 fScalar * rkVector.y, 00213 fScalar * rkVector.z); 00214 } 00215 00216 inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector ) 00217 { 00218 return Vector3( 00219 fScalar / rkVector.x, 00220 fScalar / rkVector.y, 00221 fScalar / rkVector.z); 00222 } 00223 00224 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00225 { 00226 return Vector3( 00227 lhs.x + rhs, 00228 lhs.y + rhs, 00229 lhs.z + rhs); 00230 } 00231 00232 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00233 { 00234 return Vector3( 00235 lhs + rhs.x, 00236 lhs + rhs.y, 00237 lhs + rhs.z); 00238 } 00239 00240 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00241 { 00242 return Vector3( 00243 lhs.x - rhs, 00244 lhs.y - rhs, 00245 lhs.z - rhs); 00246 } 00247 00248 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00249 { 00250 return Vector3( 00251 lhs - rhs.x, 00252 lhs - rhs.y, 00253 lhs - rhs.z); 00254 } 00255 00256 // arithmetic updates 00257 inline Vector3& operator += ( const Vector3& rkVector ) 00258 { 00259 x += rkVector.x; 00260 y += rkVector.y; 00261 z += rkVector.z; 00262 00263 return *this; 00264 } 00265 00266 inline Vector3& operator += ( const Real fScalar ) 00267 { 00268 x += fScalar; 00269 y += fScalar; 00270 z += fScalar; 00271 return *this; 00272 } 00273 00274 inline Vector3& operator -= ( const Vector3& rkVector ) 00275 { 00276 x -= rkVector.x; 00277 y -= rkVector.y; 00278 z -= rkVector.z; 00279 00280 return *this; 00281 } 00282 00283 inline Vector3& operator -= ( const Real fScalar ) 00284 { 00285 x -= fScalar; 00286 y -= fScalar; 00287 z -= fScalar; 00288 return *this; 00289 } 00290 00291 inline Vector3& operator *= ( const Real fScalar ) 00292 { 00293 x *= fScalar; 00294 y *= fScalar; 00295 z *= fScalar; 00296 return *this; 00297 } 00298 00299 inline Vector3& operator *= ( const Vector3& rkVector ) 00300 { 00301 x *= rkVector.x; 00302 y *= rkVector.y; 00303 z *= rkVector.z; 00304 00305 return *this; 00306 } 00307 00308 inline Vector3& operator /= ( const Real fScalar ) 00309 { 00310 assert( fScalar != 0.0 ); 00311 00312 Real fInv = 1.0 / fScalar; 00313 00314 x *= fInv; 00315 y *= fInv; 00316 z *= fInv; 00317 00318 return *this; 00319 } 00320 00321 inline Vector3& operator /= ( const Vector3& rkVector ) 00322 { 00323 x /= rkVector.x; 00324 y /= rkVector.y; 00325 z /= rkVector.z; 00326 00327 return *this; 00328 } 00329 00330 00338 inline Real length () const 00339 { 00340 return Math::Sqrt( x * x + y * y + z * z ); 00341 } 00342 00353 inline Real squaredLength () const 00354 { 00355 return x * x + y * y + z * z; 00356 } 00357 00365 inline Real distance(const Vector3& rhs) const 00366 { 00367 return (*this - rhs).length(); 00368 } 00369 00380 inline Real squaredDistance(const Vector3& rhs) const 00381 { 00382 return (*this - rhs).squaredLength(); 00383 } 00384 00399 inline Real dotProduct(const Vector3& vec) const 00400 { 00401 return x * vec.x + y * vec.y + z * vec.z; 00402 } 00403 00414 inline Real absDotProduct(const Vector3& vec) const 00415 { 00416 return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z); 00417 } 00418 00428 inline Real normalise() 00429 { 00430 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00431 00432 // Will also work for zero-sized vectors, but will change nothing 00433 if ( fLength > 1e-08 ) 00434 { 00435 Real fInvLength = 1.0 / fLength; 00436 x *= fInvLength; 00437 y *= fInvLength; 00438 z *= fInvLength; 00439 } 00440 00441 return fLength; 00442 } 00443 00472 inline Vector3 crossProduct( const Vector3& rkVector ) const 00473 { 00474 return Vector3( 00475 y * rkVector.z - z * rkVector.y, 00476 z * rkVector.x - x * rkVector.z, 00477 x * rkVector.y - y * rkVector.x); 00478 } 00479 00483 inline Vector3 midPoint( const Vector3& vec ) const 00484 { 00485 return Vector3( 00486 ( x + vec.x ) * 0.5, 00487 ( y + vec.y ) * 0.5, 00488 ( z + vec.z ) * 0.5 ); 00489 } 00490 00494 inline bool operator < ( const Vector3& rhs ) const 00495 { 00496 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00497 return true; 00498 return false; 00499 } 00500 00504 inline bool operator > ( const Vector3& rhs ) const 00505 { 00506 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00507 return true; 00508 return false; 00509 } 00510 00518 inline void makeFloor( const Vector3& cmp ) 00519 { 00520 if( cmp.x < x ) x = cmp.x; 00521 if( cmp.y < y ) y = cmp.y; 00522 if( cmp.z < z ) z = cmp.z; 00523 } 00524 00532 inline void makeCeil( const Vector3& cmp ) 00533 { 00534 if( cmp.x > x ) x = cmp.x; 00535 if( cmp.y > y ) y = cmp.y; 00536 if( cmp.z > z ) z = cmp.z; 00537 } 00538 00546 inline Vector3 perpendicular(void) const 00547 { 00548 static const Real fSquareZero = 1e-06 * 1e-06; 00549 00550 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00551 00552 // Check length 00553 if( perp.squaredLength() < fSquareZero ) 00554 { 00555 /* This vector is the Y axis multiplied by a scalar, so we have 00556 to use another axis. 00557 */ 00558 perp = this->crossProduct( Vector3::UNIT_Y ); 00559 } 00560 perp.normalise(); 00561 00562 return perp; 00563 } 00583 inline Vector3 randomDeviant( 00584 const Radian& angle, 00585 const Vector3& up = Vector3::ZERO ) const 00586 { 00587 Vector3 newUp; 00588 00589 if (up == Vector3::ZERO) 00590 { 00591 // Generate an up vector 00592 newUp = this->perpendicular(); 00593 } 00594 else 00595 { 00596 newUp = up; 00597 } 00598 00599 // Rotate up vector by random amount around this 00600 Quaternion q; 00601 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00602 newUp = q * newUp; 00603 00604 // Finally rotate this by given angle around randomised up 00605 q.FromAngleAxis( angle, newUp ); 00606 return q * (*this); 00607 } 00608 00613 inline Radian angleBetween(const Vector3& dest) 00614 { 00615 Real lenProduct = length() * dest.length(); 00616 00617 // Divide by zero check 00618 if(lenProduct < 1e-6f) 00619 lenProduct = 1e-6f; 00620 00621 Real f = dotProduct(dest) / lenProduct; 00622 00623 f = Math::Clamp(f, (Real)-1.0, (Real)1.0); 00624 return Math::ACos(f); 00625 00626 } 00635 Quaternion getRotationTo(const Vector3& dest, 00636 const Vector3& fallbackAxis = Vector3::ZERO) const 00637 { 00638 // Based on Stan Melax's article in Game Programming Gems 00639 Quaternion q; 00640 // Copy, since cannot modify local 00641 Vector3 v0 = *this; 00642 Vector3 v1 = dest; 00643 v0.normalise(); 00644 v1.normalise(); 00645 00646 Real d = v0.dotProduct(v1); 00647 // If dot == 1, vectors are the same 00648 if (d >= 1.0f) 00649 { 00650 return Quaternion::IDENTITY; 00651 } 00652 if (d < (1e-6f - 1.0f)) 00653 { 00654 if (fallbackAxis != Vector3::ZERO) 00655 { 00656 // rotate 180 degrees about the fallback axis 00657 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00658 } 00659 else 00660 { 00661 // Generate an axis 00662 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00663 if (axis.isZeroLength()) // pick another if colinear 00664 axis = Vector3::UNIT_Y.crossProduct(*this); 00665 axis.normalise(); 00666 q.FromAngleAxis(Radian(Math::PI), axis); 00667 } 00668 } 00669 else 00670 { 00671 Real s = Math::Sqrt( (1+d)*2 ); 00672 Real invs = 1 / s; 00673 00674 Vector3 c = v0.crossProduct(v1); 00675 00676 q.x = c.x * invs; 00677 q.y = c.y * invs; 00678 q.z = c.z * invs; 00679 q.w = s * 0.5; 00680 q.normalise(); 00681 } 00682 return q; 00683 } 00684 00686 inline bool isZeroLength(void) const 00687 { 00688 Real sqlen = (x * x) + (y * y) + (z * z); 00689 return (sqlen < (1e-06 * 1e-06)); 00690 00691 } 00692 00695 inline Vector3 normalisedCopy(void) const 00696 { 00697 Vector3 ret = *this; 00698 ret.normalise(); 00699 return ret; 00700 } 00701 00705 inline Vector3 reflect(const Vector3& normal) const 00706 { 00707 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00708 } 00709 00716 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00717 { 00718 return Math::RealEqual(x, rhs.x, tolerance) && 00719 Math::RealEqual(y, rhs.y, tolerance) && 00720 Math::RealEqual(z, rhs.z, tolerance); 00721 00722 } 00723 00730 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00731 { 00732 return squaredDistance(rhs) <= 00733 (squaredLength() + rhs.squaredLength()) * tolerance; 00734 } 00735 00743 inline bool directionEquals(const Vector3& rhs, 00744 const Radian& tolerance) const 00745 { 00746 Real dot = dotProduct(rhs); 00747 Radian angle = Math::ACos(dot); 00748 00749 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00750 00751 } 00752 00753 // special points 00754 static const Vector3 ZERO; 00755 static const Vector3 UNIT_X; 00756 static const Vector3 UNIT_Y; 00757 static const Vector3 UNIT_Z; 00758 static const Vector3 NEGATIVE_UNIT_X; 00759 static const Vector3 NEGATIVE_UNIT_Y; 00760 static const Vector3 NEGATIVE_UNIT_Z; 00761 static const Vector3 UNIT_SCALE; 00762 00765 inline _OgreExport friend std::ostream& operator << 00766 ( std::ostream& o, const Vector3& v ) 00767 { 00768 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00769 return o; 00770 } 00771 }; 00772 00773 } 00774 #endif
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:26 2009