00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://ogre.sourceforge.net/ 00006 00007 Copyright © 2000-2002 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 Real x, y, z; 00046 00047 public: 00048 inline Vector3() 00049 { 00050 } 00051 00052 inline Vector3( Real fX, Real fY, Real fZ ) 00053 : x( fX ), y( fY ), z( fZ ) 00054 { 00055 } 00056 00057 inline Vector3( Real afCoordinate[3] ) 00058 : x( afCoordinate[0] ), 00059 y( afCoordinate[1] ), 00060 z( afCoordinate[2] ) 00061 { 00062 } 00063 00064 inline Vector3( int afCoordinate[3] ) 00065 { 00066 x = (Real)afCoordinate[0]; 00067 y = (Real)afCoordinate[1]; 00068 z = (Real)afCoordinate[2]; 00069 } 00070 00071 inline Vector3( const Real* const r ) 00072 : x( r[0] ), y( r[1] ), z( r[2] ) 00073 { 00074 } 00075 00076 inline Vector3( const Vector3& rkVector ) 00077 : x( rkVector.x ), y( rkVector.y ), z( rkVector.z ) 00078 { 00079 } 00080 00081 inline Real operator [] ( unsigned i ) const 00082 { 00083 assert( i < 3 ); 00084 00085 return *(&x+i); 00086 } 00087 00088 inline Real& operator [] ( unsigned i ) 00089 { 00090 assert( i < 3 ); 00091 00092 return *(&x+i); 00093 } 00094 00099 inline Vector3& operator = ( const Vector3& rkVector ) 00100 { 00101 x = rkVector.x; 00102 y = rkVector.y; 00103 z = rkVector.z; 00104 00105 return *this; 00106 } 00107 00108 inline bool operator == ( const Vector3& rkVector ) const 00109 { 00110 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00111 } 00112 00113 inline bool operator != ( const Vector3& rkVector ) const 00114 { 00115 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00116 } 00117 00118 // arithmetic operations 00119 inline Vector3 operator + ( const Vector3& rkVector ) const 00120 { 00121 Vector3 kSum; 00122 00123 kSum.x = x + rkVector.x; 00124 kSum.y = y + rkVector.y; 00125 kSum.z = z + rkVector.z; 00126 00127 return kSum; 00128 } 00129 00130 inline Vector3 operator - ( const Vector3& rkVector ) const 00131 { 00132 Vector3 kDiff; 00133 00134 kDiff.x = x - rkVector.x; 00135 kDiff.y = y - rkVector.y; 00136 kDiff.z = z - rkVector.z; 00137 00138 return kDiff; 00139 } 00140 00141 inline Vector3 operator * ( Real fScalar ) const 00142 { 00143 Vector3 kProd; 00144 00145 kProd.x = fScalar*x; 00146 kProd.y = fScalar*y; 00147 kProd.z = fScalar*z; 00148 00149 return kProd; 00150 } 00151 00152 inline Vector3 operator * ( const Vector3& rhs) const 00153 { 00154 Vector3 kProd; 00155 00156 kProd.x = rhs.x * x; 00157 kProd.y = rhs.y * y; 00158 kProd.z = rhs.z * z; 00159 00160 return kProd; 00161 } 00162 00163 inline Vector3 operator / ( Real fScalar ) const 00164 { 00165 assert( fScalar != 0.0 ); 00166 00167 Vector3 kDiv; 00168 00169 Real fInv = 1.0 / fScalar; 00170 kDiv.x = x * fInv; 00171 kDiv.y = y * fInv; 00172 kDiv.z = z * fInv; 00173 00174 return kDiv; 00175 } 00176 00177 inline Vector3 operator - () const 00178 { 00179 Vector3 kNeg; 00180 00181 kNeg.x = -x; 00182 kNeg.y = -y; 00183 kNeg.z = -z; 00184 00185 return kNeg; 00186 } 00187 00188 inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector ) 00189 { 00190 Vector3 kProd; 00191 00192 kProd.x = fScalar * rkVector.x; 00193 kProd.y = fScalar * rkVector.y; 00194 kProd.z = fScalar * rkVector.z; 00195 00196 return kProd; 00197 } 00198 00199 // arithmetic updates 00200 inline Vector3& operator += ( const Vector3& rkVector ) 00201 { 00202 x += rkVector.x; 00203 y += rkVector.y; 00204 z += rkVector.z; 00205 00206 return *this; 00207 } 00208 00209 inline Vector3& operator -= ( const Vector3& rkVector ) 00210 { 00211 x -= rkVector.x; 00212 y -= rkVector.y; 00213 z -= rkVector.z; 00214 00215 return *this; 00216 } 00217 00218 inline Vector3& operator *= ( Real fScalar ) 00219 { 00220 x *= fScalar; 00221 y *= fScalar; 00222 z *= fScalar; 00223 return *this; 00224 } 00225 00226 inline Vector3& operator /= ( Real fScalar ) 00227 { 00228 assert( fScalar != 0.0 ); 00229 00230 Real fInv = 1.0 / fScalar; 00231 00232 x *= fInv; 00233 y *= fInv; 00234 z *= fInv; 00235 00236 return *this; 00237 } 00238 00246 inline Real length () const 00247 { 00248 return Math::Sqrt( x * x + y * y + z * z ); 00249 } 00250 00261 inline Real squaredLength () const 00262 { 00263 return x * x + y * y + z * z; 00264 } 00265 00280 inline Real dotProduct(const Vector3& vec) const 00281 { 00282 return x * vec.x + y * vec.y + z * vec.z; 00283 } 00284 00293 inline Vector3 & normalise() 00294 { 00295 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00296 00297 // Will also work for zero-sized vectors, but will change nothing 00298 if ( fLength > 1e-06 ) 00299 { 00300 Real fInvLength = 1.0 / fLength; 00301 x *= fInvLength; 00302 y *= fInvLength; 00303 z *= fInvLength; 00304 } 00305 00306 return *this; 00307 } 00308 00336 inline Vector3 crossProduct( const Vector3& rkVector ) const 00337 { 00338 Vector3 kCross; 00339 00340 kCross.x = y * rkVector.z - z * rkVector.y; 00341 kCross.y = z * rkVector.x - x * rkVector.z; 00342 kCross.z = x * rkVector.y - y * rkVector.x; 00343 00344 return kCross; 00345 } 00346 00350 inline Vector3 midPoint( const Vector3& vec ) const 00351 { 00352 return Vector3( 00353 ( x + vec.x ) * 0.5, 00354 ( y + vec.y ) * 0.5, 00355 ( z + vec.z ) * 0.5 ); 00356 } 00357 00361 inline bool operator < ( const Vector3& rhs ) const 00362 { 00363 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00364 return true; 00365 return false; 00366 } 00367 00371 inline bool operator > ( const Vector3& rhs ) const 00372 { 00373 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00374 return true; 00375 return false; 00376 } 00377 00385 inline void makeFloor( const Vector3& cmp ) 00386 { 00387 if( cmp.x < x ) x = cmp.x; 00388 if( cmp.y < y ) y = cmp.y; 00389 if( cmp.z < z ) z = cmp.z; 00390 } 00391 00399 inline void makeCeil( const Vector3& cmp ) 00400 { 00401 if( cmp.x > x ) x = cmp.x; 00402 if( cmp.y > y ) y = cmp.y; 00403 if( cmp.z > z ) z = cmp.z; 00404 } 00405 00413 inline Vector3 perpendicular(void) 00414 { 00415 static Real fSquareZero = 1e-06 * 1e-06; 00416 00417 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00418 00419 // Check length 00420 if( perp.squaredLength() < fSquareZero ) 00421 { 00422 /* This vector is the Y axis multiplied by a scalar, so we have 00423 to use another axis. 00424 */ 00425 perp = this->crossProduct( Vector3::UNIT_Y ); 00426 } 00427 00428 return perp; 00429 } 00449 inline Vector3 randomDeviant( 00450 Real angle, 00451 const Vector3& up = Vector3::ZERO ) 00452 { 00453 Vector3 newUp; 00454 00455 if (up == Vector3::ZERO) 00456 { 00457 // Generate an up vector 00458 newUp = this->perpendicular(); 00459 } 00460 else 00461 { 00462 newUp = up; 00463 } 00464 00465 // Rotate up vector by random amount around this 00466 Quaternion q; 00467 q.FromAngleAxis( Math::UnitRandom() * Math::TWO_PI, *this ); 00468 newUp = q * newUp; 00469 00470 // Finally rotate this by given angle around randomised up 00471 q.FromAngleAxis( angle, newUp ); 00472 return q * (*this); 00473 } 00474 00481 Quaternion getRotationTo(const Vector3& dest) const 00482 { 00483 // Based on Stan Melax's article in Game Programming Gems 00484 Quaternion q; 00485 // Copy, since cannot modify local 00486 Vector3 v0 = *this; 00487 Vector3 v1 = dest; 00488 v0.normalise(); 00489 v1.normalise(); 00490 00491 Vector3 c = v0.crossProduct(v1); 00492 00493 // NB if the crossProduct approaches zero, we get unstable because ANY axis will do 00494 // when v0 == -v1 00495 Real d = v0.dotProduct(v1); 00496 // If dot == 1, vectors are the same 00497 if (d >= 1.0f) 00498 { 00499 return Quaternion::IDENTITY; 00500 } 00501 Real s = Math::Sqrt( (1+d)*2 ); 00502 Real invs = 1 / s; 00503 00504 00505 q.x = c.x * invs; 00506 q.y = c.y * invs; 00507 q.z = c.z * invs; 00508 q.w = s * 0.5; 00509 return q; 00510 } 00511 00512 // special points 00513 static const Vector3 ZERO; 00514 static const Vector3 UNIT_X; 00515 static const Vector3 UNIT_Y; 00516 static const Vector3 UNIT_Z; 00517 static const Vector3 UNIT_SCALE; 00518 00521 inline _OgreExport friend std::ostream& operator << 00522 ( std::ostream& o, const Vector3& v ) 00523 { 00524 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00525 return o; 00526 } 00527 }; 00528 00529 } 00530 #endif
Copyright © 2002 by The OGRE Team