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-2011 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __Vector3_H__ 00029 #define __Vector3_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 #include "OgreMath.h" 00033 #include "OgreQuaternion.h" 00034 00035 namespace Ogre 00036 { 00037 00051 class _OgreExport Vector3 00052 { 00053 public: 00054 Real x, y, z; 00055 00056 public: 00057 inline Vector3() 00058 { 00059 } 00060 00061 inline Vector3( const Real fX, const Real fY, const Real fZ ) 00062 : x( fX ), y( fY ), z( fZ ) 00063 { 00064 } 00065 00066 inline explicit Vector3( const Real afCoordinate[3] ) 00067 : x( afCoordinate[0] ), 00068 y( afCoordinate[1] ), 00069 z( afCoordinate[2] ) 00070 { 00071 } 00072 00073 inline explicit Vector3( const int afCoordinate[3] ) 00074 { 00075 x = (Real)afCoordinate[0]; 00076 y = (Real)afCoordinate[1]; 00077 z = (Real)afCoordinate[2]; 00078 } 00079 00080 inline explicit Vector3( Real* const r ) 00081 : x( r[0] ), y( r[1] ), z( r[2] ) 00082 { 00083 } 00084 00085 inline explicit Vector3( const Real scaler ) 00086 : x( scaler ) 00087 , y( scaler ) 00088 , z( scaler ) 00089 { 00090 } 00091 00092 00095 inline void swap(Vector3& other) 00096 { 00097 std::swap(x, other.x); 00098 std::swap(y, other.y); 00099 std::swap(z, other.z); 00100 } 00101 00102 inline Real operator [] ( const size_t i ) const 00103 { 00104 assert( i < 3 ); 00105 00106 return *(&x+i); 00107 } 00108 00109 inline Real& operator [] ( const size_t i ) 00110 { 00111 assert( i < 3 ); 00112 00113 return *(&x+i); 00114 } 00116 inline Real* ptr() 00117 { 00118 return &x; 00119 } 00121 inline const Real* ptr() const 00122 { 00123 return &x; 00124 } 00125 00130 inline Vector3& operator = ( const Vector3& rkVector ) 00131 { 00132 x = rkVector.x; 00133 y = rkVector.y; 00134 z = rkVector.z; 00135 00136 return *this; 00137 } 00138 00139 inline Vector3& operator = ( const Real fScaler ) 00140 { 00141 x = fScaler; 00142 y = fScaler; 00143 z = fScaler; 00144 00145 return *this; 00146 } 00147 00148 inline bool operator == ( const Vector3& rkVector ) const 00149 { 00150 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00151 } 00152 00153 inline bool operator != ( const Vector3& rkVector ) const 00154 { 00155 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00156 } 00157 00158 // arithmetic operations 00159 inline Vector3 operator + ( const Vector3& rkVector ) const 00160 { 00161 return Vector3( 00162 x + rkVector.x, 00163 y + rkVector.y, 00164 z + rkVector.z); 00165 } 00166 00167 inline Vector3 operator - ( const Vector3& rkVector ) const 00168 { 00169 return Vector3( 00170 x - rkVector.x, 00171 y - rkVector.y, 00172 z - rkVector.z); 00173 } 00174 00175 inline Vector3 operator * ( const Real fScalar ) const 00176 { 00177 return Vector3( 00178 x * fScalar, 00179 y * fScalar, 00180 z * fScalar); 00181 } 00182 00183 inline Vector3 operator * ( const Vector3& rhs) const 00184 { 00185 return Vector3( 00186 x * rhs.x, 00187 y * rhs.y, 00188 z * rhs.z); 00189 } 00190 00191 inline Vector3 operator / ( const Real fScalar ) const 00192 { 00193 assert( fScalar != 0.0 ); 00194 00195 Real fInv = 1.0f / fScalar; 00196 00197 return Vector3( 00198 x * fInv, 00199 y * fInv, 00200 z * fInv); 00201 } 00202 00203 inline Vector3 operator / ( const Vector3& rhs) const 00204 { 00205 return Vector3( 00206 x / rhs.x, 00207 y / rhs.y, 00208 z / rhs.z); 00209 } 00210 00211 inline const Vector3& operator + () const 00212 { 00213 return *this; 00214 } 00215 00216 inline Vector3 operator - () const 00217 { 00218 return Vector3(-x, -y, -z); 00219 } 00220 00221 // overloaded operators to help Vector3 00222 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00223 { 00224 return Vector3( 00225 fScalar * rkVector.x, 00226 fScalar * rkVector.y, 00227 fScalar * rkVector.z); 00228 } 00229 00230 inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector ) 00231 { 00232 return Vector3( 00233 fScalar / rkVector.x, 00234 fScalar / rkVector.y, 00235 fScalar / rkVector.z); 00236 } 00237 00238 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00239 { 00240 return Vector3( 00241 lhs.x + rhs, 00242 lhs.y + rhs, 00243 lhs.z + rhs); 00244 } 00245 00246 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00247 { 00248 return Vector3( 00249 lhs + rhs.x, 00250 lhs + rhs.y, 00251 lhs + rhs.z); 00252 } 00253 00254 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00255 { 00256 return Vector3( 00257 lhs.x - rhs, 00258 lhs.y - rhs, 00259 lhs.z - rhs); 00260 } 00261 00262 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00263 { 00264 return Vector3( 00265 lhs - rhs.x, 00266 lhs - rhs.y, 00267 lhs - rhs.z); 00268 } 00269 00270 // arithmetic updates 00271 inline Vector3& operator += ( const Vector3& rkVector ) 00272 { 00273 x += rkVector.x; 00274 y += rkVector.y; 00275 z += rkVector.z; 00276 00277 return *this; 00278 } 00279 00280 inline Vector3& operator += ( const Real fScalar ) 00281 { 00282 x += fScalar; 00283 y += fScalar; 00284 z += fScalar; 00285 return *this; 00286 } 00287 00288 inline Vector3& operator -= ( const Vector3& rkVector ) 00289 { 00290 x -= rkVector.x; 00291 y -= rkVector.y; 00292 z -= rkVector.z; 00293 00294 return *this; 00295 } 00296 00297 inline Vector3& operator -= ( const Real fScalar ) 00298 { 00299 x -= fScalar; 00300 y -= fScalar; 00301 z -= fScalar; 00302 return *this; 00303 } 00304 00305 inline Vector3& operator *= ( const Real fScalar ) 00306 { 00307 x *= fScalar; 00308 y *= fScalar; 00309 z *= fScalar; 00310 return *this; 00311 } 00312 00313 inline Vector3& operator *= ( const Vector3& rkVector ) 00314 { 00315 x *= rkVector.x; 00316 y *= rkVector.y; 00317 z *= rkVector.z; 00318 00319 return *this; 00320 } 00321 00322 inline Vector3& operator /= ( const Real fScalar ) 00323 { 00324 assert( fScalar != 0.0 ); 00325 00326 Real fInv = 1.0f / fScalar; 00327 00328 x *= fInv; 00329 y *= fInv; 00330 z *= fInv; 00331 00332 return *this; 00333 } 00334 00335 inline Vector3& operator /= ( const Vector3& rkVector ) 00336 { 00337 x /= rkVector.x; 00338 y /= rkVector.y; 00339 z /= rkVector.z; 00340 00341 return *this; 00342 } 00343 00344 00352 inline Real length () const 00353 { 00354 return Math::Sqrt( x * x + y * y + z * z ); 00355 } 00356 00367 inline Real squaredLength () const 00368 { 00369 return x * x + y * y + z * z; 00370 } 00371 00379 inline Real distance(const Vector3& rhs) const 00380 { 00381 return (*this - rhs).length(); 00382 } 00383 00394 inline Real squaredDistance(const Vector3& rhs) const 00395 { 00396 return (*this - rhs).squaredLength(); 00397 } 00398 00413 inline Real dotProduct(const Vector3& vec) const 00414 { 00415 return x * vec.x + y * vec.y + z * vec.z; 00416 } 00417 00428 inline Real absDotProduct(const Vector3& vec) const 00429 { 00430 return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z); 00431 } 00432 00442 inline Real normalise() 00443 { 00444 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00445 00446 // Will also work for zero-sized vectors, but will change nothing 00447 if ( fLength > 1e-08 ) 00448 { 00449 Real fInvLength = 1.0f / fLength; 00450 x *= fInvLength; 00451 y *= fInvLength; 00452 z *= fInvLength; 00453 } 00454 00455 return fLength; 00456 } 00457 00486 inline Vector3 crossProduct( const Vector3& rkVector ) const 00487 { 00488 return Vector3( 00489 y * rkVector.z - z * rkVector.y, 00490 z * rkVector.x - x * rkVector.z, 00491 x * rkVector.y - y * rkVector.x); 00492 } 00493 00497 inline Vector3 midPoint( const Vector3& vec ) const 00498 { 00499 return Vector3( 00500 ( x + vec.x ) * 0.5f, 00501 ( y + vec.y ) * 0.5f, 00502 ( z + vec.z ) * 0.5f ); 00503 } 00504 00508 inline bool operator < ( const Vector3& rhs ) const 00509 { 00510 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00511 return true; 00512 return false; 00513 } 00514 00518 inline bool operator > ( const Vector3& rhs ) const 00519 { 00520 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00521 return true; 00522 return false; 00523 } 00524 00532 inline void makeFloor( 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 void makeCeil( const Vector3& cmp ) 00547 { 00548 if( cmp.x > x ) x = cmp.x; 00549 if( cmp.y > y ) y = cmp.y; 00550 if( cmp.z > z ) z = cmp.z; 00551 } 00552 00560 inline Vector3 perpendicular(void) const 00561 { 00562 static const Real fSquareZero = (Real)(1e-06 * 1e-06); 00563 00564 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00565 00566 // Check length 00567 if( perp.squaredLength() < fSquareZero ) 00568 { 00569 /* This vector is the Y axis multiplied by a scalar, so we have 00570 to use another axis. 00571 */ 00572 perp = this->crossProduct( Vector3::UNIT_Y ); 00573 } 00574 perp.normalise(); 00575 00576 return perp; 00577 } 00597 inline Vector3 randomDeviant( 00598 const Radian& angle, 00599 const Vector3& up = Vector3::ZERO ) const 00600 { 00601 Vector3 newUp; 00602 00603 if (up == Vector3::ZERO) 00604 { 00605 // Generate an up vector 00606 newUp = this->perpendicular(); 00607 } 00608 else 00609 { 00610 newUp = up; 00611 } 00612 00613 // Rotate up vector by random amount around this 00614 Quaternion q; 00615 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00616 newUp = q * newUp; 00617 00618 // Finally rotate this by given angle around randomised up 00619 q.FromAngleAxis( angle, newUp ); 00620 return q * (*this); 00621 } 00622 00627 inline Radian angleBetween(const Vector3& dest) 00628 { 00629 Real lenProduct = length() * dest.length(); 00630 00631 // Divide by zero check 00632 if(lenProduct < 1e-6f) 00633 lenProduct = 1e-6f; 00634 00635 Real f = dotProduct(dest) / lenProduct; 00636 00637 f = Math::Clamp(f, (Real)-1.0, (Real)1.0); 00638 return Math::ACos(f); 00639 00640 } 00649 Quaternion getRotationTo(const Vector3& dest, 00650 const Vector3& fallbackAxis = Vector3::ZERO) const 00651 { 00652 // Based on Stan Melax's article in Game Programming Gems 00653 Quaternion q; 00654 // Copy, since cannot modify local 00655 Vector3 v0 = *this; 00656 Vector3 v1 = dest; 00657 v0.normalise(); 00658 v1.normalise(); 00659 00660 Real d = v0.dotProduct(v1); 00661 // If dot == 1, vectors are the same 00662 if (d >= 1.0f) 00663 { 00664 return Quaternion::IDENTITY; 00665 } 00666 if (d < (1e-6f - 1.0f)) 00667 { 00668 if (fallbackAxis != Vector3::ZERO) 00669 { 00670 // rotate 180 degrees about the fallback axis 00671 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00672 } 00673 else 00674 { 00675 // Generate an axis 00676 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00677 if (axis.isZeroLength()) // pick another if colinear 00678 axis = Vector3::UNIT_Y.crossProduct(*this); 00679 axis.normalise(); 00680 q.FromAngleAxis(Radian(Math::PI), axis); 00681 } 00682 } 00683 else 00684 { 00685 Real s = Math::Sqrt( (1+d)*2 ); 00686 Real invs = 1 / s; 00687 00688 Vector3 c = v0.crossProduct(v1); 00689 00690 q.x = c.x * invs; 00691 q.y = c.y * invs; 00692 q.z = c.z * invs; 00693 q.w = s * 0.5f; 00694 q.normalise(); 00695 } 00696 return q; 00697 } 00698 00700 inline bool isZeroLength(void) const 00701 { 00702 Real sqlen = (x * x) + (y * y) + (z * z); 00703 return (sqlen < (1e-06 * 1e-06)); 00704 00705 } 00706 00709 inline Vector3 normalisedCopy(void) const 00710 { 00711 Vector3 ret = *this; 00712 ret.normalise(); 00713 return ret; 00714 } 00715 00719 inline Vector3 reflect(const Vector3& normal) const 00720 { 00721 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00722 } 00723 00730 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00731 { 00732 return Math::RealEqual(x, rhs.x, tolerance) && 00733 Math::RealEqual(y, rhs.y, tolerance) && 00734 Math::RealEqual(z, rhs.z, tolerance); 00735 00736 } 00737 00744 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00745 { 00746 return squaredDistance(rhs) <= 00747 (squaredLength() + rhs.squaredLength()) * tolerance; 00748 } 00749 00757 inline bool directionEquals(const Vector3& rhs, 00758 const Radian& tolerance) const 00759 { 00760 Real dot = dotProduct(rhs); 00761 Radian angle = Math::ACos(dot); 00762 00763 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00764 00765 } 00766 00768 inline bool isNaN() const 00769 { 00770 return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z); 00771 } 00772 00773 // special points 00774 static const Vector3 ZERO; 00775 static const Vector3 UNIT_X; 00776 static const Vector3 UNIT_Y; 00777 static const Vector3 UNIT_Z; 00778 static const Vector3 NEGATIVE_UNIT_X; 00779 static const Vector3 NEGATIVE_UNIT_Y; 00780 static const Vector3 NEGATIVE_UNIT_Z; 00781 static const Vector3 UNIT_SCALE; 00782 00785 inline _OgreExport friend std::ostream& operator << 00786 ( std::ostream& o, const Vector3& v ) 00787 { 00788 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00789 return o; 00790 } 00791 }; 00795 } 00796 #endif
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sat Jan 14 2012 18:40:44