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-2012 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 // We're not using epsilons because we don't need to. 00448 // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259 00449 if ( fLength > Real(0.0f) ) 00450 { 00451 Real fInvLength = 1.0f / fLength; 00452 x *= fInvLength; 00453 y *= fInvLength; 00454 z *= fInvLength; 00455 } 00456 00457 return fLength; 00458 } 00459 00488 inline Vector3 crossProduct( const Vector3& rkVector ) const 00489 { 00490 return Vector3( 00491 y * rkVector.z - z * rkVector.y, 00492 z * rkVector.x - x * rkVector.z, 00493 x * rkVector.y - y * rkVector.x); 00494 } 00495 00499 inline Vector3 midPoint( const Vector3& vec ) const 00500 { 00501 return Vector3( 00502 ( x + vec.x ) * 0.5f, 00503 ( y + vec.y ) * 0.5f, 00504 ( z + vec.z ) * 0.5f ); 00505 } 00506 00510 inline bool operator < ( const Vector3& rhs ) const 00511 { 00512 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00513 return true; 00514 return false; 00515 } 00516 00520 inline bool operator > ( const Vector3& rhs ) const 00521 { 00522 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00523 return true; 00524 return false; 00525 } 00526 00534 inline void makeFloor( const Vector3& cmp ) 00535 { 00536 if( cmp.x < x ) x = cmp.x; 00537 if( cmp.y < y ) y = cmp.y; 00538 if( cmp.z < z ) z = cmp.z; 00539 } 00540 00548 inline void makeCeil( const Vector3& cmp ) 00549 { 00550 if( cmp.x > x ) x = cmp.x; 00551 if( cmp.y > y ) y = cmp.y; 00552 if( cmp.z > z ) z = cmp.z; 00553 } 00554 00562 inline Vector3 perpendicular(void) const 00563 { 00564 static const Real fSquareZero = (Real)(1e-06 * 1e-06); 00565 00566 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00567 00568 // Check length 00569 if( perp.squaredLength() < fSquareZero ) 00570 { 00571 /* This vector is the Y axis multiplied by a scalar, so we have 00572 to use another axis. 00573 */ 00574 perp = this->crossProduct( Vector3::UNIT_Y ); 00575 } 00576 perp.normalise(); 00577 00578 return perp; 00579 } 00599 inline Vector3 randomDeviant( 00600 const Radian& angle, 00601 const Vector3& up = Vector3::ZERO ) const 00602 { 00603 Vector3 newUp; 00604 00605 if (up == Vector3::ZERO) 00606 { 00607 // Generate an up vector 00608 newUp = this->perpendicular(); 00609 } 00610 else 00611 { 00612 newUp = up; 00613 } 00614 00615 // Rotate up vector by random amount around this 00616 Quaternion q; 00617 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00618 newUp = q * newUp; 00619 00620 // Finally rotate this by given angle around randomised up 00621 q.FromAngleAxis( angle, newUp ); 00622 return q * (*this); 00623 } 00624 00629 inline Radian angleBetween(const Vector3& dest) const 00630 { 00631 Real lenProduct = length() * dest.length(); 00632 00633 // Divide by zero check 00634 if(lenProduct < 1e-6f) 00635 lenProduct = 1e-6f; 00636 00637 Real f = dotProduct(dest) / lenProduct; 00638 00639 f = Math::Clamp(f, (Real)-1.0, (Real)1.0); 00640 return Math::ACos(f); 00641 00642 } 00651 Quaternion getRotationTo(const Vector3& dest, 00652 const Vector3& fallbackAxis = Vector3::ZERO) const 00653 { 00654 // Based on Stan Melax's article in Game Programming Gems 00655 Quaternion q; 00656 // Copy, since cannot modify local 00657 Vector3 v0 = *this; 00658 Vector3 v1 = dest; 00659 v0.normalise(); 00660 v1.normalise(); 00661 00662 Real d = v0.dotProduct(v1); 00663 // If dot == 1, vectors are the same 00664 if (d >= 1.0f) 00665 { 00666 return Quaternion::IDENTITY; 00667 } 00668 if (d < (1e-6f - 1.0f)) 00669 { 00670 if (fallbackAxis != Vector3::ZERO) 00671 { 00672 // rotate 180 degrees about the fallback axis 00673 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00674 } 00675 else 00676 { 00677 // Generate an axis 00678 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00679 if (axis.isZeroLength()) // pick another if colinear 00680 axis = Vector3::UNIT_Y.crossProduct(*this); 00681 axis.normalise(); 00682 q.FromAngleAxis(Radian(Math::PI), axis); 00683 } 00684 } 00685 else 00686 { 00687 Real s = Math::Sqrt( (1+d)*2 ); 00688 Real invs = 1 / s; 00689 00690 Vector3 c = v0.crossProduct(v1); 00691 00692 q.x = c.x * invs; 00693 q.y = c.y * invs; 00694 q.z = c.z * invs; 00695 q.w = s * 0.5f; 00696 q.normalise(); 00697 } 00698 return q; 00699 } 00700 00702 inline bool isZeroLength(void) const 00703 { 00704 Real sqlen = (x * x) + (y * y) + (z * z); 00705 return (sqlen < (1e-06 * 1e-06)); 00706 00707 } 00708 00711 inline Vector3 normalisedCopy(void) const 00712 { 00713 Vector3 ret = *this; 00714 ret.normalise(); 00715 return ret; 00716 } 00717 00721 inline Vector3 reflect(const Vector3& normal) const 00722 { 00723 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00724 } 00725 00732 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00733 { 00734 return Math::RealEqual(x, rhs.x, tolerance) && 00735 Math::RealEqual(y, rhs.y, tolerance) && 00736 Math::RealEqual(z, rhs.z, tolerance); 00737 00738 } 00739 00746 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00747 { 00748 return squaredDistance(rhs) <= 00749 (squaredLength() + rhs.squaredLength()) * tolerance; 00750 } 00751 00759 inline bool directionEquals(const Vector3& rhs, 00760 const Radian& tolerance) const 00761 { 00762 Real dot = dotProduct(rhs); 00763 Radian angle = Math::ACos(dot); 00764 00765 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00766 00767 } 00768 00770 inline bool isNaN() const 00771 { 00772 return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z); 00773 } 00774 00776 inline Vector3 primaryAxis() const 00777 { 00778 Real absx = Math::Abs(x); 00779 Real absy = Math::Abs(y); 00780 Real absz = Math::Abs(z); 00781 if (absx > absy) 00782 if (absx > absz) 00783 return x > 0 ? Vector3::UNIT_X : Vector3::NEGATIVE_UNIT_X; 00784 else 00785 return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z; 00786 else // absx <= absy 00787 if (absy > absz) 00788 return y > 0 ? Vector3::UNIT_Y : Vector3::NEGATIVE_UNIT_Y; 00789 else 00790 return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z; 00791 00792 00793 } 00794 00795 // special points 00796 static const Vector3 ZERO; 00797 static const Vector3 UNIT_X; 00798 static const Vector3 UNIT_Y; 00799 static const Vector3 UNIT_Z; 00800 static const Vector3 NEGATIVE_UNIT_X; 00801 static const Vector3 NEGATIVE_UNIT_Y; 00802 static const Vector3 NEGATIVE_UNIT_Z; 00803 static const Vector3 UNIT_SCALE; 00804 00807 inline _OgreExport friend std::ostream& operator << 00808 ( std::ostream& o, const Vector3& v ) 00809 { 00810 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00811 return o; 00812 } 00813 }; 00817 } 00818 #endif
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:28 2012