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 Vector3( const Vector3& rkVector ) 00089 : x( rkVector.x ), y( rkVector.y ), z( rkVector.z ) 00090 { 00091 } 00092 00093 inline Real operator [] ( const size_t i ) const 00094 { 00095 assert( i < 3 ); 00096 00097 return *(&x+i); 00098 } 00099 00100 inline Real& operator [] ( const size_t i ) 00101 { 00102 assert( i < 3 ); 00103 00104 return *(&x+i); 00105 } 00107 inline Real* ptr() 00108 { 00109 return &x; 00110 } 00112 inline const Real* ptr() const 00113 { 00114 return &x; 00115 } 00116 00121 inline Vector3& operator = ( const Vector3& rkVector ) 00122 { 00123 x = rkVector.x; 00124 y = rkVector.y; 00125 z = rkVector.z; 00126 00127 return *this; 00128 } 00129 00130 inline Vector3& operator = ( const Real fScaler ) 00131 { 00132 x = fScaler; 00133 y = fScaler; 00134 z = fScaler; 00135 00136 return *this; 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 inline bool operator != ( const Vector3& rkVector ) const 00145 { 00146 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00147 } 00148 00149 // arithmetic operations 00150 inline Vector3 operator + ( const Vector3& rkVector ) const 00151 { 00152 return Vector3( 00153 x + rkVector.x, 00154 y + rkVector.y, 00155 z + rkVector.z); 00156 } 00157 00158 inline Vector3 operator - ( const Vector3& rkVector ) const 00159 { 00160 return Vector3( 00161 x - rkVector.x, 00162 y - rkVector.y, 00163 z - rkVector.z); 00164 } 00165 00166 inline Vector3 operator * ( const Real fScalar ) const 00167 { 00168 return Vector3( 00169 x * fScalar, 00170 y * fScalar, 00171 z * fScalar); 00172 } 00173 00174 inline Vector3 operator * ( const Vector3& rhs) const 00175 { 00176 return Vector3( 00177 x * rhs.x, 00178 y * rhs.y, 00179 z * rhs.z); 00180 } 00181 00182 inline Vector3 operator / ( const Real fScalar ) const 00183 { 00184 assert( fScalar != 0.0 ); 00185 00186 Real fInv = 1.0 / fScalar; 00187 00188 return Vector3( 00189 x * fInv, 00190 y * fInv, 00191 z * fInv); 00192 } 00193 00194 inline Vector3 operator / ( const Vector3& rhs) const 00195 { 00196 return Vector3( 00197 x / rhs.x, 00198 y / rhs.y, 00199 z / rhs.z); 00200 } 00201 00202 inline const Vector3& operator + () const 00203 { 00204 return *this; 00205 } 00206 00207 inline Vector3 operator - () const 00208 { 00209 return Vector3(-x, -y, -z); 00210 } 00211 00212 // overloaded operators to help Vector3 00213 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00214 { 00215 return Vector3( 00216 fScalar * rkVector.x, 00217 fScalar * rkVector.y, 00218 fScalar * rkVector.z); 00219 } 00220 00221 inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector ) 00222 { 00223 return Vector3( 00224 fScalar / rkVector.x, 00225 fScalar / rkVector.y, 00226 fScalar / rkVector.z); 00227 } 00228 00229 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00230 { 00231 return Vector3( 00232 lhs.x + rhs, 00233 lhs.y + rhs, 00234 lhs.z + rhs); 00235 } 00236 00237 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00238 { 00239 return Vector3( 00240 lhs + rhs.x, 00241 lhs + rhs.y, 00242 lhs + rhs.z); 00243 } 00244 00245 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00246 { 00247 return Vector3( 00248 lhs.x - rhs, 00249 lhs.y - rhs, 00250 lhs.z - rhs); 00251 } 00252 00253 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00254 { 00255 return Vector3( 00256 lhs - rhs.x, 00257 lhs - rhs.y, 00258 lhs - rhs.z); 00259 } 00260 00261 // arithmetic updates 00262 inline Vector3& operator += ( const Vector3& rkVector ) 00263 { 00264 x += rkVector.x; 00265 y += rkVector.y; 00266 z += rkVector.z; 00267 00268 return *this; 00269 } 00270 00271 inline Vector3& operator += ( const Real fScalar ) 00272 { 00273 x += fScalar; 00274 y += fScalar; 00275 z += fScalar; 00276 return *this; 00277 } 00278 00279 inline Vector3& operator -= ( const Vector3& rkVector ) 00280 { 00281 x -= rkVector.x; 00282 y -= rkVector.y; 00283 z -= rkVector.z; 00284 00285 return *this; 00286 } 00287 00288 inline Vector3& operator -= ( const Real fScalar ) 00289 { 00290 x -= fScalar; 00291 y -= fScalar; 00292 z -= fScalar; 00293 return *this; 00294 } 00295 00296 inline Vector3& operator *= ( const Real fScalar ) 00297 { 00298 x *= fScalar; 00299 y *= fScalar; 00300 z *= fScalar; 00301 return *this; 00302 } 00303 00304 inline Vector3& operator *= ( const Vector3& rkVector ) 00305 { 00306 x *= rkVector.x; 00307 y *= rkVector.y; 00308 z *= rkVector.z; 00309 00310 return *this; 00311 } 00312 00313 inline Vector3& operator /= ( const Real fScalar ) 00314 { 00315 assert( fScalar != 0.0 ); 00316 00317 Real fInv = 1.0 / fScalar; 00318 00319 x *= fInv; 00320 y *= fInv; 00321 z *= fInv; 00322 00323 return *this; 00324 } 00325 00326 inline Vector3& operator /= ( const Vector3& rkVector ) 00327 { 00328 x /= rkVector.x; 00329 y /= rkVector.y; 00330 z /= rkVector.z; 00331 00332 return *this; 00333 } 00334 00335 00343 inline Real length () const 00344 { 00345 return Math::Sqrt( x * x + y * y + z * z ); 00346 } 00347 00358 inline Real squaredLength () const 00359 { 00360 return x * x + y * y + z * z; 00361 } 00362 00370 inline Real distance(const Vector3& rhs) const 00371 { 00372 return (*this - rhs).length(); 00373 } 00374 00385 inline Real squaredDistance(const Vector3& rhs) const 00386 { 00387 return (*this - rhs).squaredLength(); 00388 } 00389 00404 inline Real dotProduct(const Vector3& vec) const 00405 { 00406 return x * vec.x + y * vec.y + z * vec.z; 00407 } 00408 00419 inline Real absDotProduct(const Vector3& vec) const 00420 { 00421 return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z); 00422 } 00423 00433 inline Real normalise() 00434 { 00435 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00436 00437 // Will also work for zero-sized vectors, but will change nothing 00438 if ( fLength > 1e-08 ) 00439 { 00440 Real fInvLength = 1.0 / fLength; 00441 x *= fInvLength; 00442 y *= fInvLength; 00443 z *= fInvLength; 00444 } 00445 00446 return fLength; 00447 } 00448 00477 inline Vector3 crossProduct( const Vector3& rkVector ) const 00478 { 00479 return Vector3( 00480 y * rkVector.z - z * rkVector.y, 00481 z * rkVector.x - x * rkVector.z, 00482 x * rkVector.y - y * rkVector.x); 00483 } 00484 00488 inline Vector3 midPoint( const Vector3& vec ) const 00489 { 00490 return Vector3( 00491 ( x + vec.x ) * 0.5, 00492 ( y + vec.y ) * 0.5, 00493 ( z + vec.z ) * 0.5 ); 00494 } 00495 00499 inline bool operator < ( const Vector3& rhs ) const 00500 { 00501 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00502 return true; 00503 return false; 00504 } 00505 00509 inline bool operator > ( const Vector3& rhs ) const 00510 { 00511 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00512 return true; 00513 return false; 00514 } 00515 00523 inline void makeFloor( const Vector3& cmp ) 00524 { 00525 if( cmp.x < x ) x = cmp.x; 00526 if( cmp.y < y ) y = cmp.y; 00527 if( cmp.z < z ) z = cmp.z; 00528 } 00529 00537 inline void makeCeil( const Vector3& cmp ) 00538 { 00539 if( cmp.x > x ) x = cmp.x; 00540 if( cmp.y > y ) y = cmp.y; 00541 if( cmp.z > z ) z = cmp.z; 00542 } 00543 00551 inline Vector3 perpendicular(void) const 00552 { 00553 static const Real fSquareZero = 1e-06 * 1e-06; 00554 00555 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00556 00557 // Check length 00558 if( perp.squaredLength() < fSquareZero ) 00559 { 00560 /* This vector is the Y axis multiplied by a scalar, so we have 00561 to use another axis. 00562 */ 00563 perp = this->crossProduct( Vector3::UNIT_Y ); 00564 } 00565 perp.normalise(); 00566 00567 return perp; 00568 } 00588 inline Vector3 randomDeviant( 00589 const Radian& angle, 00590 const Vector3& up = Vector3::ZERO ) const 00591 { 00592 Vector3 newUp; 00593 00594 if (up == Vector3::ZERO) 00595 { 00596 // Generate an up vector 00597 newUp = this->perpendicular(); 00598 } 00599 else 00600 { 00601 newUp = up; 00602 } 00603 00604 // Rotate up vector by random amount around this 00605 Quaternion q; 00606 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00607 newUp = q * newUp; 00608 00609 // Finally rotate this by given angle around randomised up 00610 q.FromAngleAxis( angle, newUp ); 00611 return q * (*this); 00612 } 00613 #ifndef OGRE_FORCE_ANGLE_TYPES 00614 inline Vector3 randomDeviant( 00615 Real angle, 00616 const Vector3& up = Vector3::ZERO ) const 00617 { 00618 return randomDeviant ( Radian(angle), up ); 00619 } 00620 #endif//OGRE_FORCE_ANGLE_TYPES 00621 00630 Quaternion getRotationTo(const Vector3& dest, 00631 const Vector3& fallbackAxis = Vector3::ZERO) const 00632 { 00633 // Based on Stan Melax's article in Game Programming Gems 00634 Quaternion q; 00635 // Copy, since cannot modify local 00636 Vector3 v0 = *this; 00637 Vector3 v1 = dest; 00638 v0.normalise(); 00639 v1.normalise(); 00640 00641 Real d = v0.dotProduct(v1); 00642 // If dot == 1, vectors are the same 00643 if (d >= 1.0f) 00644 { 00645 return Quaternion::IDENTITY; 00646 } 00647 if (d < (1e-6f - 1.0f)) 00648 { 00649 if (fallbackAxis != Vector3::ZERO) 00650 { 00651 // rotate 180 degrees about the fallback axis 00652 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00653 } 00654 else 00655 { 00656 // Generate an axis 00657 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00658 if (axis.isZeroLength()) // pick another if colinear 00659 axis = Vector3::UNIT_Y.crossProduct(*this); 00660 axis.normalise(); 00661 q.FromAngleAxis(Radian(Math::PI), axis); 00662 } 00663 } 00664 else 00665 { 00666 Real s = Math::Sqrt( (1+d)*2 ); 00667 Real invs = 1 / s; 00668 00669 Vector3 c = v0.crossProduct(v1); 00670 00671 q.x = c.x * invs; 00672 q.y = c.y * invs; 00673 q.z = c.z * invs; 00674 q.w = s * 0.5; 00675 q.normalise(); 00676 } 00677 return q; 00678 } 00679 00681 inline bool isZeroLength(void) const 00682 { 00683 Real sqlen = (x * x) + (y * y) + (z * z); 00684 return (sqlen < (1e-06 * 1e-06)); 00685 00686 } 00687 00690 inline Vector3 normalisedCopy(void) const 00691 { 00692 Vector3 ret = *this; 00693 ret.normalise(); 00694 return ret; 00695 } 00696 00700 inline Vector3 reflect(const Vector3& normal) const 00701 { 00702 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00703 } 00704 00711 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00712 { 00713 return Math::RealEqual(x, rhs.x, tolerance) && 00714 Math::RealEqual(y, rhs.y, tolerance) && 00715 Math::RealEqual(z, rhs.z, tolerance); 00716 00717 } 00718 00725 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00726 { 00727 return squaredDistance(rhs) <= 00728 (squaredLength() + rhs.squaredLength()) * tolerance; 00729 } 00730 00738 inline bool directionEquals(const Vector3& rhs, 00739 const Radian& tolerance) const 00740 { 00741 Real dot = dotProduct(rhs); 00742 Radian angle = Math::ACos(dot); 00743 00744 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00745 00746 } 00747 00748 // special points 00749 static const Vector3 ZERO; 00750 static const Vector3 UNIT_X; 00751 static const Vector3 UNIT_Y; 00752 static const Vector3 UNIT_Z; 00753 static const Vector3 NEGATIVE_UNIT_X; 00754 static const Vector3 NEGATIVE_UNIT_Y; 00755 static const Vector3 NEGATIVE_UNIT_Z; 00756 static const Vector3 UNIT_SCALE; 00757 00760 inline _OgreExport friend std::ostream& operator << 00761 ( std::ostream& o, const Vector3& v ) 00762 { 00763 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00764 return o; 00765 } 00766 }; 00767 00768 } 00769 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat May 10 16:25:04 2008