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-2005 The OGRE Team 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 */ 00025 #ifndef __Vector3_H__ 00026 #define __Vector3_H__ 00027 00028 #include "OgrePrerequisites.h" 00029 #include "OgreMath.h" 00030 #include "OgreQuaternion.h" 00031 00032 namespace Ogre 00033 { 00034 00042 class _OgreExport Vector3 00043 { 00044 public: 00045 union { 00046 struct { 00047 Real x, y, z; 00048 }; 00049 Real val[3]; 00050 }; 00051 00052 public: 00053 inline Vector3() 00054 { 00055 } 00056 00057 inline Vector3( const Real fX, const Real fY, const Real fZ ) 00058 : x( fX ), y( fY ), z( fZ ) 00059 { 00060 } 00061 00062 inline explicit Vector3( const Real afCoordinate[3] ) 00063 : x( afCoordinate[0] ), 00064 y( afCoordinate[1] ), 00065 z( afCoordinate[2] ) 00066 { 00067 } 00068 00069 inline explicit Vector3( const int afCoordinate[3] ) 00070 { 00071 x = (Real)afCoordinate[0]; 00072 y = (Real)afCoordinate[1]; 00073 z = (Real)afCoordinate[2]; 00074 } 00075 00076 inline explicit Vector3( Real* const r ) 00077 : x( r[0] ), y( r[1] ), z( r[2] ) 00078 { 00079 } 00080 00081 inline explicit Vector3( const Real scaler ) 00082 : x( scaler ) 00083 , y( scaler ) 00084 , z( scaler ) 00085 { 00086 } 00087 00088 00089 inline Vector3( const Vector3& rkVector ) 00090 : x( rkVector.x ), y( rkVector.y ), z( rkVector.z ) 00091 { 00092 } 00093 00094 inline Real operator [] ( const size_t i ) const 00095 { 00096 assert( i < 3 ); 00097 00098 return *(&x+i); 00099 } 00100 00101 inline Real& operator [] ( const size_t i ) 00102 { 00103 assert( i < 3 ); 00104 00105 return *(&x+i); 00106 } 00107 00112 inline Vector3& operator = ( const Vector3& rkVector ) 00113 { 00114 x = rkVector.x; 00115 y = rkVector.y; 00116 z = rkVector.z; 00117 00118 return *this; 00119 } 00120 00121 inline Vector3& operator = ( const Real fScaler ) 00122 { 00123 x = fScaler; 00124 y = fScaler; 00125 z = fScaler; 00126 00127 return *this; 00128 } 00129 00130 inline bool operator == ( const Vector3& rkVector ) const 00131 { 00132 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00133 } 00134 00135 inline bool operator != ( const Vector3& rkVector ) const 00136 { 00137 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00138 } 00139 00140 // arithmetic operations 00141 inline Vector3 operator + ( const Vector3& rkVector ) const 00142 { 00143 Vector3 kSum; 00144 00145 kSum.x = x + rkVector.x; 00146 kSum.y = y + rkVector.y; 00147 kSum.z = z + rkVector.z; 00148 00149 return kSum; 00150 } 00151 00152 inline Vector3 operator - ( const Vector3& rkVector ) const 00153 { 00154 Vector3 kDiff; 00155 00156 kDiff.x = x - rkVector.x; 00157 kDiff.y = y - rkVector.y; 00158 kDiff.z = z - rkVector.z; 00159 00160 return kDiff; 00161 } 00162 00163 inline Vector3 operator * ( const Real fScalar ) const 00164 { 00165 Vector3 kProd; 00166 00167 kProd.x = fScalar*x; 00168 kProd.y = fScalar*y; 00169 kProd.z = fScalar*z; 00170 00171 return kProd; 00172 } 00173 00174 inline Vector3 operator * ( const Vector3& rhs) const 00175 { 00176 Vector3 kProd; 00177 00178 kProd.x = rhs.x * x; 00179 kProd.y = rhs.y * y; 00180 kProd.z = rhs.z * z; 00181 00182 return kProd; 00183 } 00184 00185 inline Vector3 operator / ( const Real fScalar ) const 00186 { 00187 assert( fScalar != 0.0 ); 00188 00189 Vector3 kDiv; 00190 00191 Real fInv = 1.0 / fScalar; 00192 kDiv.x = x * fInv; 00193 kDiv.y = y * fInv; 00194 kDiv.z = z * fInv; 00195 00196 return kDiv; 00197 } 00198 00199 inline Vector3 operator / ( const Vector3& rhs) const 00200 { 00201 Vector3 kDiv; 00202 00203 kDiv.x = x / rhs.x; 00204 kDiv.y = y / rhs.y; 00205 kDiv.z = z / rhs.z; 00206 00207 return kDiv; 00208 } 00209 00210 00211 inline Vector3 operator - () const 00212 { 00213 Vector3 kNeg; 00214 00215 kNeg.x = -x; 00216 kNeg.y = -y; 00217 kNeg.z = -z; 00218 00219 return kNeg; 00220 } 00221 00222 // overloaded operators to help Vector3 00223 inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector ) 00224 { 00225 Vector3 kProd; 00226 00227 kProd.x = fScalar * rkVector.x; 00228 kProd.y = fScalar * rkVector.y; 00229 kProd.z = fScalar * rkVector.z; 00230 00231 return kProd; 00232 } 00233 00234 inline friend Vector3 operator + (const Vector3& lhs, const Real rhs) 00235 { 00236 Vector3 ret(rhs); 00237 return ret += lhs; 00238 } 00239 00240 inline friend Vector3 operator + (const Real lhs, const Vector3& rhs) 00241 { 00242 Vector3 ret(lhs); 00243 return ret += rhs; 00244 } 00245 00246 inline friend Vector3 operator - (const Vector3& lhs, const Real rhs) 00247 { 00248 return lhs - Vector3(rhs); 00249 } 00250 00251 inline friend Vector3 operator - (const Real lhs, const Vector3& rhs) 00252 { 00253 Vector3 ret(lhs); 00254 return ret -= rhs; 00255 } 00256 00257 // arithmetic updates 00258 inline Vector3& operator += ( const Vector3& rkVector ) 00259 { 00260 x += rkVector.x; 00261 y += rkVector.y; 00262 z += rkVector.z; 00263 00264 return *this; 00265 } 00266 00267 inline Vector3& operator += ( const Real fScalar ) 00268 { 00269 x += fScalar; 00270 y += fScalar; 00271 z += fScalar; 00272 return *this; 00273 } 00274 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 Real fScalar ) 00293 { 00294 x *= fScalar; 00295 y *= fScalar; 00296 z *= fScalar; 00297 return *this; 00298 } 00299 00300 inline Vector3& operator *= ( const Vector3& rkVector ) 00301 { 00302 x *= rkVector.x; 00303 y *= rkVector.y; 00304 z *= rkVector.z; 00305 00306 return *this; 00307 } 00308 00309 inline Vector3& operator /= ( const Real fScalar ) 00310 { 00311 assert( fScalar != 0.0 ); 00312 00313 Real fInv = 1.0 / fScalar; 00314 00315 x *= fInv; 00316 y *= fInv; 00317 z *= fInv; 00318 00319 return *this; 00320 } 00321 00322 inline Vector3& operator /= ( const Vector3& rkVector ) 00323 { 00324 x /= rkVector.x; 00325 y /= rkVector.y; 00326 z /= rkVector.z; 00327 00328 return *this; 00329 } 00330 00331 00339 inline Real length () const 00340 { 00341 return Math::Sqrt( x * x + y * y + z * z ); 00342 } 00343 00354 inline Real squaredLength () const 00355 { 00356 return x * x + y * y + z * z; 00357 } 00358 00373 inline Real dotProduct(const Vector3& vec) const 00374 { 00375 return x * vec.x + y * vec.y + z * vec.z; 00376 } 00377 00387 inline Real normalise() 00388 { 00389 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00390 00391 // Will also work for zero-sized vectors, but will change nothing 00392 if ( fLength > 1e-08 ) 00393 { 00394 Real fInvLength = 1.0 / fLength; 00395 x *= fInvLength; 00396 y *= fInvLength; 00397 z *= fInvLength; 00398 } 00399 00400 return fLength; 00401 } 00402 00431 inline Vector3 crossProduct( const Vector3& rkVector ) const 00432 { 00433 Vector3 kCross; 00434 00435 kCross.x = y * rkVector.z - z * rkVector.y; 00436 kCross.y = z * rkVector.x - x * rkVector.z; 00437 kCross.z = x * rkVector.y - y * rkVector.x; 00438 00439 return kCross; 00440 } 00441 00445 inline Vector3 midPoint( const Vector3& vec ) const 00446 { 00447 return Vector3( 00448 ( x + vec.x ) * 0.5, 00449 ( y + vec.y ) * 0.5, 00450 ( z + vec.z ) * 0.5 ); 00451 } 00452 00456 inline bool operator < ( const Vector3& rhs ) const 00457 { 00458 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00459 return true; 00460 return false; 00461 } 00462 00466 inline bool operator > ( const Vector3& rhs ) const 00467 { 00468 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00469 return true; 00470 return false; 00471 } 00472 00480 inline void makeFloor( const Vector3& cmp ) 00481 { 00482 if( cmp.x < x ) x = cmp.x; 00483 if( cmp.y < y ) y = cmp.y; 00484 if( cmp.z < z ) z = cmp.z; 00485 } 00486 00494 inline void makeCeil( const Vector3& cmp ) 00495 { 00496 if( cmp.x > x ) x = cmp.x; 00497 if( cmp.y > y ) y = cmp.y; 00498 if( cmp.z > z ) z = cmp.z; 00499 } 00500 00508 inline Vector3 perpendicular(void) const 00509 { 00510 static const Real fSquareZero = 1e-06 * 1e-06; 00511 00512 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00513 00514 // Check length 00515 if( perp.squaredLength() < fSquareZero ) 00516 { 00517 /* This vector is the Y axis multiplied by a scalar, so we have 00518 to use another axis. 00519 */ 00520 perp = this->crossProduct( Vector3::UNIT_Y ); 00521 } 00522 00523 return perp; 00524 } 00544 inline Vector3 randomDeviant( 00545 const Radian& angle, 00546 const Vector3& up = Vector3::ZERO ) const 00547 { 00548 Vector3 newUp; 00549 00550 if (up == Vector3::ZERO) 00551 { 00552 // Generate an up vector 00553 newUp = this->perpendicular(); 00554 } 00555 else 00556 { 00557 newUp = up; 00558 } 00559 00560 // Rotate up vector by random amount around this 00561 Quaternion q; 00562 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00563 newUp = q * newUp; 00564 00565 // Finally rotate this by given angle around randomised up 00566 q.FromAngleAxis( angle, newUp ); 00567 return q * (*this); 00568 } 00569 #ifndef OGRE_FORCE_ANGLE_TYPES 00570 inline Vector3 randomDeviant( 00571 Real angle, 00572 const Vector3& up = Vector3::ZERO ) const 00573 { 00574 return randomDeviant ( Radian(angle), up ); 00575 } 00576 #endif//OGRE_FORCE_ANGLE_TYPES 00577 00586 Quaternion getRotationTo(const Vector3& dest, 00587 const Vector3& fallbackAxis = Vector3::ZERO) const 00588 { 00589 // Based on Stan Melax's article in Game Programming Gems 00590 Quaternion q; 00591 // Copy, since cannot modify local 00592 Vector3 v0 = *this; 00593 Vector3 v1 = dest; 00594 v0.normalise(); 00595 v1.normalise(); 00596 00597 Vector3 c = v0.crossProduct(v1); 00598 00599 Real d = v0.dotProduct(v1); 00600 // If dot == 1, vectors are the same 00601 if (d >= 1.0f) 00602 { 00603 return Quaternion::IDENTITY; 00604 } 00605 Real s = Math::Sqrt( (1+d)*2 ); 00606 if (s < 1e-6f) 00607 { 00608 if (fallbackAxis != Vector3::ZERO) 00609 { 00610 // rotate 180 degrees about the fallback axis 00611 q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00612 } 00613 else 00614 { 00615 // Generate an axis 00616 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00617 if (axis.isZeroLength()) // pick another if colinear 00618 axis = Vector3::UNIT_Y.crossProduct(*this); 00619 axis.normalise(); 00620 q.FromAngleAxis(Radian(Math::PI), axis); 00621 } 00622 } 00623 else 00624 { 00625 Real invs = 1 / s; 00626 00627 q.x = c.x * invs; 00628 q.y = c.y * invs; 00629 q.z = c.z * invs; 00630 q.w = s * 0.5; 00631 } 00632 return q; 00633 } 00634 00636 inline bool isZeroLength(void) const 00637 { 00638 Real sqlen = (x * x) + (y * y) + (z * z); 00639 return (sqlen < (1e-06 * 1e-06)); 00640 00641 } 00642 00645 inline Vector3 normalisedCopy(void) const 00646 { 00647 Vector3 ret = *this; 00648 ret.normalise(); 00649 return ret; 00650 } 00651 00655 inline Vector3 reflect(const Vector3& normal) const 00656 { 00657 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00658 } 00659 00666 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00667 { 00668 return Math::RealEqual(x, rhs.x, tolerance) && 00669 Math::RealEqual(y, rhs.y, tolerance) && 00670 Math::RealEqual(z, rhs.z, tolerance); 00671 00672 } 00679 inline bool directionEquals(const Vector3& rhs, 00680 const Radian& tolerance) const 00681 { 00682 Real dot = dotProduct(rhs); 00683 Radian angle = Math::ACos(dot); 00684 00685 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00686 00687 } 00688 00689 // special points 00690 static const Vector3 ZERO; 00691 static const Vector3 UNIT_X; 00692 static const Vector3 UNIT_Y; 00693 static const Vector3 UNIT_Z; 00694 static const Vector3 NEGATIVE_UNIT_X; 00695 static const Vector3 NEGATIVE_UNIT_Y; 00696 static const Vector3 NEGATIVE_UNIT_Z; 00697 static const Vector3 UNIT_SCALE; 00698 00701 inline _OgreExport friend std::ostream& operator << 00702 ( std::ostream& o, const Vector3& v ) 00703 { 00704 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00705 return o; 00706 } 00707 }; 00708 00709 } 00710 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:51 2006