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-2013 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: 00061 inline Vector3() 00062 { 00063 } 00064 00065 inline Vector3( const Real fX, const Real fY, const Real fZ ) 00066 : x( fX ), y( fY ), z( fZ ) 00067 { 00068 } 00069 00070 inline explicit Vector3( const Real afCoordinate[3] ) 00071 : x( afCoordinate[0] ), 00072 y( afCoordinate[1] ), 00073 z( afCoordinate[2] ) 00074 { 00075 } 00076 00077 inline explicit Vector3( const int afCoordinate[3] ) 00078 { 00079 x = (Real)afCoordinate[0]; 00080 y = (Real)afCoordinate[1]; 00081 z = (Real)afCoordinate[2]; 00082 } 00083 00084 inline explicit Vector3( Real* const r ) 00085 : x( r[0] ), y( r[1] ), z( r[2] ) 00086 { 00087 } 00088 00089 inline explicit Vector3( const Real scaler ) 00090 : x( scaler ) 00091 , y( scaler ) 00092 , z( scaler ) 00093 { 00094 } 00095 00096 00099 inline void swap(Vector3& other) 00100 { 00101 std::swap(x, other.x); 00102 std::swap(y, other.y); 00103 std::swap(z, other.z); 00104 } 00105 00106 inline Real operator [] ( const size_t i ) const 00107 { 00108 assert( i < 3 ); 00109 00110 return *(&x+i); 00111 } 00112 00113 inline Real& operator [] ( const size_t i ) 00114 { 00115 assert( i < 3 ); 00116 00117 return *(&x+i); 00118 } 00120 inline Real* ptr() 00121 { 00122 return &x; 00123 } 00125 inline const Real* ptr() const 00126 { 00127 return &x; 00128 } 00129 00134 inline Vector3& operator = ( const Vector3& rkVector ) 00135 { 00136 x = rkVector.x; 00137 y = rkVector.y; 00138 z = rkVector.z; 00139 00140 return *this; 00141 } 00142 00143 inline Vector3& operator = ( const Real fScaler ) 00144 { 00145 x = fScaler; 00146 y = fScaler; 00147 z = fScaler; 00148 00149 return *this; 00150 } 00151 00152 inline bool operator == ( const Vector3& rkVector ) const 00153 { 00154 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00155 } 00156 00157 inline bool operator != ( const Vector3& rkVector ) const 00158 { 00159 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00160 } 00161 00162 // arithmetic operations 00163 inline Vector3 operator + ( const Vector3& rkVector ) const 00164 { 00165 return Vector3( 00166 x + rkVector.x, 00167 y + rkVector.y, 00168 z + rkVector.z); 00169 } 00170 00171 inline Vector3 operator - ( const Vector3& rkVector ) const 00172 { 00173 return Vector3( 00174 x - rkVector.x, 00175 y - rkVector.y, 00176 z - rkVector.z); 00177 } 00178 00179 inline Vector3 operator * ( const Real fScalar ) const 00180 { 00181 return Vector3( 00182 x * fScalar, 00183 y * fScalar, 00184 z * fScalar); 00185 } 00186 00187 inline Vector3 operator * ( const Vector3& rhs) const 00188 { 00189 return Vector3( 00190 x * rhs.x, 00191 y * rhs.y, 00192 z * rhs.z); 00193 } 00194 00195 inline Vector3 operator / ( const Real fScalar ) const 00196 { 00197 assert( fScalar != 0.0 ); 00198 00199 Real fInv = 1.0f / fScalar; 00200 00201 return Vector3( 00202 x * fInv, 00203 y * fInv, 00204 z * fInv); 00205 } 00206 00207 inline Vector3 operator / ( const Vector3& rhs) const 00208 { 00209 return Vector3( 00210 x / rhs.x, 00211 y / rhs.y, 00212 z / rhs.z); 00213 } 00214 00215 inline const Vector3& operator + () const 00216 { 00217 return *this; 00218 } 00219 00220 inline Vector3 operator - () const 00221 { 00222 return Vector3(-x, -y, -z); 00223 } 00224 00225 // overloaded operators to help Vector3 00226 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00227 { 00228 return Vector3( 00229 fScalar * rkVector.x, 00230 fScalar * rkVector.y, 00231 fScalar * rkVector.z); 00232 } 00233 00234 inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector ) 00235 { 00236 return Vector3( 00237 fScalar / rkVector.x, 00238 fScalar / rkVector.y, 00239 fScalar / rkVector.z); 00240 } 00241 00242 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00243 { 00244 return Vector3( 00245 lhs.x + rhs, 00246 lhs.y + rhs, 00247 lhs.z + rhs); 00248 } 00249 00250 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00251 { 00252 return Vector3( 00253 lhs + rhs.x, 00254 lhs + rhs.y, 00255 lhs + rhs.z); 00256 } 00257 00258 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00259 { 00260 return Vector3( 00261 lhs.x - rhs, 00262 lhs.y - rhs, 00263 lhs.z - rhs); 00264 } 00265 00266 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00267 { 00268 return Vector3( 00269 lhs - rhs.x, 00270 lhs - rhs.y, 00271 lhs - rhs.z); 00272 } 00273 00274 // arithmetic updates 00275 inline Vector3& operator += ( const Vector3& rkVector ) 00276 { 00277 x += rkVector.x; 00278 y += rkVector.y; 00279 z += rkVector.z; 00280 00281 return *this; 00282 } 00283 00284 inline Vector3& operator += ( const Real fScalar ) 00285 { 00286 x += fScalar; 00287 y += fScalar; 00288 z += fScalar; 00289 return *this; 00290 } 00291 00292 inline Vector3& operator -= ( const Vector3& rkVector ) 00293 { 00294 x -= rkVector.x; 00295 y -= rkVector.y; 00296 z -= rkVector.z; 00297 00298 return *this; 00299 } 00300 00301 inline Vector3& operator -= ( const Real fScalar ) 00302 { 00303 x -= fScalar; 00304 y -= fScalar; 00305 z -= fScalar; 00306 return *this; 00307 } 00308 00309 inline Vector3& operator *= ( const Real fScalar ) 00310 { 00311 x *= fScalar; 00312 y *= fScalar; 00313 z *= fScalar; 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 inline Vector3& operator /= ( const Real fScalar ) 00327 { 00328 assert( fScalar != 0.0 ); 00329 00330 Real fInv = 1.0f / fScalar; 00331 00332 x *= fInv; 00333 y *= fInv; 00334 z *= fInv; 00335 00336 return *this; 00337 } 00338 00339 inline Vector3& operator /= ( const Vector3& rkVector ) 00340 { 00341 x /= rkVector.x; 00342 y /= rkVector.y; 00343 z /= rkVector.z; 00344 00345 return *this; 00346 } 00347 00348 00356 inline Real length () const 00357 { 00358 return Math::Sqrt( x * x + y * y + z * z ); 00359 } 00360 00371 inline Real squaredLength () const 00372 { 00373 return x * x + y * y + z * z; 00374 } 00375 00383 inline Real distance(const Vector3& rhs) const 00384 { 00385 return (*this - rhs).length(); 00386 } 00387 00398 inline Real squaredDistance(const Vector3& rhs) const 00399 { 00400 return (*this - rhs).squaredLength(); 00401 } 00402 00417 inline Real dotProduct(const Vector3& vec) const 00418 { 00419 return x * vec.x + y * vec.y + z * vec.z; 00420 } 00421 00432 inline Real absDotProduct(const Vector3& vec) const 00433 { 00434 return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z); 00435 } 00436 00446 inline Real normalise() 00447 { 00448 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00449 00450 // Will also work for zero-sized vectors, but will change nothing 00451 // We're not using epsilons because we don't need to. 00452 // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259 00453 if ( fLength > Real(0.0f) ) 00454 { 00455 Real fInvLength = 1.0f / fLength; 00456 x *= fInvLength; 00457 y *= fInvLength; 00458 z *= fInvLength; 00459 } 00460 00461 return fLength; 00462 } 00463 00492 inline Vector3 crossProduct( const Vector3& rkVector ) const 00493 { 00494 return Vector3( 00495 y * rkVector.z - z * rkVector.y, 00496 z * rkVector.x - x * rkVector.z, 00497 x * rkVector.y - y * rkVector.x); 00498 } 00499 00503 inline Vector3 midPoint( const Vector3& vec ) const 00504 { 00505 return Vector3( 00506 ( x + vec.x ) * 0.5f, 00507 ( y + vec.y ) * 0.5f, 00508 ( z + vec.z ) * 0.5f ); 00509 } 00510 00514 inline bool operator < ( const Vector3& rhs ) const 00515 { 00516 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00517 return true; 00518 return false; 00519 } 00520 00524 inline bool operator > ( const Vector3& rhs ) const 00525 { 00526 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00527 return true; 00528 return false; 00529 } 00530 00538 inline void makeFloor( const Vector3& cmp ) 00539 { 00540 if( cmp.x < x ) x = cmp.x; 00541 if( cmp.y < y ) y = cmp.y; 00542 if( cmp.z < z ) z = cmp.z; 00543 } 00544 00552 inline void makeCeil( const Vector3& cmp ) 00553 { 00554 if( cmp.x > x ) x = cmp.x; 00555 if( cmp.y > y ) y = cmp.y; 00556 if( cmp.z > z ) z = cmp.z; 00557 } 00558 00566 inline Vector3 perpendicular(void) const 00567 { 00568 static const Real fSquareZero = (Real)(1e-06 * 1e-06); 00569 00570 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00571 00572 // Check length 00573 if( perp.squaredLength() < fSquareZero ) 00574 { 00575 /* This vector is the Y axis multiplied by a scalar, so we have 00576 to use another axis. 00577 */ 00578 perp = this->crossProduct( Vector3::UNIT_Y ); 00579 } 00580 perp.normalise(); 00581 00582 return perp; 00583 } 00603 inline Vector3 randomDeviant( 00604 const Radian& angle, 00605 const Vector3& up = Vector3::ZERO ) const 00606 { 00607 Vector3 newUp; 00608 00609 if (up == Vector3::ZERO) 00610 { 00611 // Generate an up vector 00612 newUp = this->perpendicular(); 00613 } 00614 else 00615 { 00616 newUp = up; 00617 } 00618 00619 // Rotate up vector by random amount around this 00620 Quaternion q; 00621 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00622 newUp = q * newUp; 00623 00624 // Finally rotate this by given angle around randomised up 00625 q.FromAngleAxis( angle, newUp ); 00626 return q * (*this); 00627 } 00628 00633 inline Radian angleBetween(const Vector3& dest) const 00634 { 00635 Real lenProduct = length() * dest.length(); 00636 00637 // Divide by zero check 00638 if(lenProduct < 1e-6f) 00639 lenProduct = 1e-6f; 00640 00641 Real f = dotProduct(dest) / lenProduct; 00642 00643 f = Math::Clamp(f, (Real)-1.0, (Real)1.0); 00644 return Math::ACos(f); 00645 00646 } 00655 Quaternion getRotationTo(const Vector3& dest, 00656 const Vector3& fallbackAxis = Vector3::ZERO) const 00657 { 00658 // Based on Stan Melax's article in Game Programming Gems 00659 Quaternion q; 00660 // Copy, since cannot modify local 00661 Vector3 v0 = *this; 00662 Vector3 v1 = dest; 00663 v0.normalise(); 00664 v1.normalise(); 00665 00666 Real d = v0.dotProduct(v1); 00667 // If dot == 1, vectors are the same 00668 if (d >= 1.0f) 00669 { 00670 return Quaternion::IDENTITY; 00671 } 00672 if (d < (1e-6f - 1.0f)) 00673 { 00674 if (fallbackAxis != Vector3::ZERO) 00675 { 00676 // rotate 180 degrees about the fallback axis 00677 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00678 } 00679 else 00680 { 00681 // Generate an axis 00682 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00683 if (axis.isZeroLength()) // pick another if colinear 00684 axis = Vector3::UNIT_Y.crossProduct(*this); 00685 axis.normalise(); 00686 q.FromAngleAxis(Radian(Math::PI), axis); 00687 } 00688 } 00689 else 00690 { 00691 Real s = Math::Sqrt( (1+d)*2 ); 00692 Real invs = 1 / s; 00693 00694 Vector3 c = v0.crossProduct(v1); 00695 00696 q.x = c.x * invs; 00697 q.y = c.y * invs; 00698 q.z = c.z * invs; 00699 q.w = s * 0.5f; 00700 q.normalise(); 00701 } 00702 return q; 00703 } 00704 00706 inline bool isZeroLength(void) const 00707 { 00708 Real sqlen = (x * x) + (y * y) + (z * z); 00709 return (sqlen < (1e-06 * 1e-06)); 00710 00711 } 00712 00715 inline Vector3 normalisedCopy(void) const 00716 { 00717 Vector3 ret = *this; 00718 ret.normalise(); 00719 return ret; 00720 } 00721 00725 inline Vector3 reflect(const Vector3& normal) const 00726 { 00727 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00728 } 00729 00736 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00737 { 00738 return Math::RealEqual(x, rhs.x, tolerance) && 00739 Math::RealEqual(y, rhs.y, tolerance) && 00740 Math::RealEqual(z, rhs.z, tolerance); 00741 00742 } 00743 00750 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00751 { 00752 return squaredDistance(rhs) <= 00753 (squaredLength() + rhs.squaredLength()) * tolerance; 00754 } 00755 00763 inline bool directionEquals(const Vector3& rhs, 00764 const Radian& tolerance) const 00765 { 00766 Real dot = dotProduct(rhs); 00767 Radian angle = Math::ACos(dot); 00768 00769 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00770 00771 } 00772 00774 inline bool isNaN() const 00775 { 00776 return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z); 00777 } 00778 00780 inline Vector3 primaryAxis() const 00781 { 00782 Real absx = Math::Abs(x); 00783 Real absy = Math::Abs(y); 00784 Real absz = Math::Abs(z); 00785 if (absx > absy) 00786 if (absx > absz) 00787 return x > 0 ? Vector3::UNIT_X : Vector3::NEGATIVE_UNIT_X; 00788 else 00789 return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z; 00790 else // absx <= absy 00791 if (absy > absz) 00792 return y > 0 ? Vector3::UNIT_Y : Vector3::NEGATIVE_UNIT_Y; 00793 else 00794 return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z; 00795 00796 00797 } 00798 00799 // special points 00800 static const Vector3 ZERO; 00801 static const Vector3 UNIT_X; 00802 static const Vector3 UNIT_Y; 00803 static const Vector3 UNIT_Z; 00804 static const Vector3 NEGATIVE_UNIT_X; 00805 static const Vector3 NEGATIVE_UNIT_Y; 00806 static const Vector3 NEGATIVE_UNIT_Z; 00807 static const Vector3 UNIT_SCALE; 00808 00811 inline _OgreExport friend std::ostream& operator << 00812 ( std::ostream& o, const Vector3& v ) 00813 { 00814 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00815 return o; 00816 } 00817 }; 00821 } 00822 #endif
Copyright © 2012 Torus Knot Software Ltd

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Mon Jul 27 2020 13:40:48