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 00566 return perp; 00567 } 00587 inline Vector3 randomDeviant( 00588 const Radian& angle, 00589 const Vector3& up = Vector3::ZERO ) const 00590 { 00591 Vector3 newUp; 00592 00593 if (up == Vector3::ZERO) 00594 { 00595 // Generate an up vector 00596 newUp = this->perpendicular(); 00597 } 00598 else 00599 { 00600 newUp = up; 00601 } 00602 00603 // Rotate up vector by random amount around this 00604 Quaternion q; 00605 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00606 newUp = q * newUp; 00607 00608 // Finally rotate this by given angle around randomised up 00609 q.FromAngleAxis( angle, newUp ); 00610 return q * (*this); 00611 } 00612 #ifndef OGRE_FORCE_ANGLE_TYPES 00613 inline Vector3 randomDeviant( 00614 Real angle, 00615 const Vector3& up = Vector3::ZERO ) const 00616 { 00617 return randomDeviant ( Radian(angle), up ); 00618 } 00619 #endif//OGRE_FORCE_ANGLE_TYPES 00620 00629 Quaternion getRotationTo(const Vector3& dest, 00630 const Vector3& fallbackAxis = Vector3::ZERO) const 00631 { 00632 // Based on Stan Melax's article in Game Programming Gems 00633 Quaternion q; 00634 // Copy, since cannot modify local 00635 Vector3 v0 = *this; 00636 Vector3 v1 = dest; 00637 v0.normalise(); 00638 v1.normalise(); 00639 00640 Real d = v0.dotProduct(v1); 00641 // If dot == 1, vectors are the same 00642 if (d >= 1.0f) 00643 { 00644 return Quaternion::IDENTITY; 00645 } 00646 if (d < (1e-6f - 1.0f)) 00647 { 00648 if (fallbackAxis != Vector3::ZERO) 00649 { 00650 // rotate 180 degrees about the fallback axis 00651 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00652 } 00653 else 00654 { 00655 // Generate an axis 00656 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00657 if (axis.isZeroLength()) // pick another if colinear 00658 axis = Vector3::UNIT_Y.crossProduct(*this); 00659 axis.normalise(); 00660 q.FromAngleAxis(Radian(Math::PI), axis); 00661 } 00662 } 00663 else 00664 { 00665 Real s = Math::Sqrt( (1+d)*2 ); 00666 Real invs = 1 / s; 00667 00668 Vector3 c = v0.crossProduct(v1); 00669 00670 q.x = c.x * invs; 00671 q.y = c.y * invs; 00672 q.z = c.z * invs; 00673 q.w = s * 0.5; 00674 q.normalise(); 00675 } 00676 return q; 00677 } 00678 00680 inline bool isZeroLength(void) const 00681 { 00682 Real sqlen = (x * x) + (y * y) + (z * z); 00683 return (sqlen < (1e-06 * 1e-06)); 00684 00685 } 00686 00689 inline Vector3 normalisedCopy(void) const 00690 { 00691 Vector3 ret = *this; 00692 ret.normalise(); 00693 return ret; 00694 } 00695 00699 inline Vector3 reflect(const Vector3& normal) const 00700 { 00701 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00702 } 00703 00710 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00711 { 00712 return Math::RealEqual(x, rhs.x, tolerance) && 00713 Math::RealEqual(y, rhs.y, tolerance) && 00714 Math::RealEqual(z, rhs.z, tolerance); 00715 00716 } 00717 00724 inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const 00725 { 00726 return squaredDistance(rhs) <= 00727 (squaredLength() + rhs.squaredLength()) * tolerance; 00728 } 00729 00737 inline bool directionEquals(const Vector3& rhs, 00738 const Radian& tolerance) const 00739 { 00740 Real dot = dotProduct(rhs); 00741 Radian angle = Math::ACos(dot); 00742 00743 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00744 00745 } 00746 00747 // special points 00748 static const Vector3 ZERO; 00749 static const Vector3 UNIT_X; 00750 static const Vector3 UNIT_Y; 00751 static const Vector3 UNIT_Z; 00752 static const Vector3 NEGATIVE_UNIT_X; 00753 static const Vector3 NEGATIVE_UNIT_Y; 00754 static const Vector3 NEGATIVE_UNIT_Z; 00755 static const Vector3 UNIT_SCALE; 00756 00759 inline _OgreExport friend std::ostream& operator << 00760 ( std::ostream& o, const Vector3& v ) 00761 { 00762 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00763 return o; 00764 } 00765 }; 00766 00767 } 00768 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun May 6 10:54:24 2007