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( Real fX, Real fY, Real fZ ) 00058 : x( fX ), y( fY ), z( fZ ) 00059 { 00060 } 00061 00062 inline Vector3( Real afCoordinate[3] ) 00063 : x( afCoordinate[0] ), 00064 y( afCoordinate[1] ), 00065 z( afCoordinate[2] ) 00066 { 00067 } 00068 00069 inline Vector3( int afCoordinate[3] ) 00070 { 00071 x = (Real)afCoordinate[0]; 00072 y = (Real)afCoordinate[1]; 00073 z = (Real)afCoordinate[2]; 00074 } 00075 00076 inline Vector3( const Real* const r ) 00077 : x( r[0] ), y( r[1] ), z( r[2] ) 00078 { 00079 } 00080 00081 inline Vector3( const Vector3& rkVector ) 00082 : x( rkVector.x ), y( rkVector.y ), z( rkVector.z ) 00083 { 00084 } 00085 00086 inline Real operator [] ( size_t i ) const 00087 { 00088 assert( i < 3 ); 00089 00090 return *(&x+i); 00091 } 00092 00093 inline Real& operator [] ( size_t i ) 00094 { 00095 assert( i < 3 ); 00096 00097 return *(&x+i); 00098 } 00099 00104 inline Vector3& operator = ( const Vector3& rkVector ) 00105 { 00106 x = rkVector.x; 00107 y = rkVector.y; 00108 z = rkVector.z; 00109 00110 return *this; 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 inline bool operator != ( const Vector3& rkVector ) const 00119 { 00120 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00121 } 00122 00123 // arithmetic operations 00124 inline Vector3 operator + ( const Vector3& rkVector ) const 00125 { 00126 Vector3 kSum; 00127 00128 kSum.x = x + rkVector.x; 00129 kSum.y = y + rkVector.y; 00130 kSum.z = z + rkVector.z; 00131 00132 return kSum; 00133 } 00134 00135 inline Vector3 operator - ( const Vector3& rkVector ) const 00136 { 00137 Vector3 kDiff; 00138 00139 kDiff.x = x - rkVector.x; 00140 kDiff.y = y - rkVector.y; 00141 kDiff.z = z - rkVector.z; 00142 00143 return kDiff; 00144 } 00145 00146 inline Vector3 operator * ( Real fScalar ) const 00147 { 00148 Vector3 kProd; 00149 00150 kProd.x = fScalar*x; 00151 kProd.y = fScalar*y; 00152 kProd.z = fScalar*z; 00153 00154 return kProd; 00155 } 00156 00157 inline Vector3 operator * ( const Vector3& rhs) const 00158 { 00159 Vector3 kProd; 00160 00161 kProd.x = rhs.x * x; 00162 kProd.y = rhs.y * y; 00163 kProd.z = rhs.z * z; 00164 00165 return kProd; 00166 } 00167 00168 inline Vector3 operator / ( Real fScalar ) const 00169 { 00170 assert( fScalar != 0.0 ); 00171 00172 Vector3 kDiv; 00173 00174 Real fInv = 1.0 / fScalar; 00175 kDiv.x = x * fInv; 00176 kDiv.y = y * fInv; 00177 kDiv.z = z * fInv; 00178 00179 return kDiv; 00180 } 00181 00182 inline Vector3 operator / ( const Vector3& rhs) const 00183 { 00184 Vector3 kDiv; 00185 00186 kDiv.x = x / rhs.x; 00187 kDiv.y = y / rhs.y; 00188 kDiv.z = z / rhs.z; 00189 00190 return kDiv; 00191 } 00192 00193 00194 inline Vector3 operator - () const 00195 { 00196 Vector3 kNeg; 00197 00198 kNeg.x = -x; 00199 kNeg.y = -y; 00200 kNeg.z = -z; 00201 00202 return kNeg; 00203 } 00204 00205 inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector ) 00206 { 00207 Vector3 kProd; 00208 00209 kProd.x = fScalar * rkVector.x; 00210 kProd.y = fScalar * rkVector.y; 00211 kProd.z = fScalar * rkVector.z; 00212 00213 return kProd; 00214 } 00215 00216 // arithmetic updates 00217 inline Vector3& operator += ( const Vector3& rkVector ) 00218 { 00219 x += rkVector.x; 00220 y += rkVector.y; 00221 z += rkVector.z; 00222 00223 return *this; 00224 } 00225 00226 inline Vector3& operator -= ( const Vector3& rkVector ) 00227 { 00228 x -= rkVector.x; 00229 y -= rkVector.y; 00230 z -= rkVector.z; 00231 00232 return *this; 00233 } 00234 00235 inline Vector3& operator *= ( Real fScalar ) 00236 { 00237 x *= fScalar; 00238 y *= fScalar; 00239 z *= fScalar; 00240 return *this; 00241 } 00242 00243 inline Vector3& operator *= ( const Vector3& rkVector ) 00244 { 00245 x *= rkVector.x; 00246 y *= rkVector.y; 00247 z *= rkVector.z; 00248 00249 return *this; 00250 } 00251 00252 inline Vector3& operator /= ( Real fScalar ) 00253 { 00254 assert( fScalar != 0.0 ); 00255 00256 Real fInv = 1.0 / fScalar; 00257 00258 x *= fInv; 00259 y *= fInv; 00260 z *= fInv; 00261 00262 return *this; 00263 } 00264 00265 inline Vector3& operator /= ( const Vector3& rkVector ) 00266 { 00267 x /= rkVector.x; 00268 y /= rkVector.y; 00269 z /= rkVector.z; 00270 00271 return *this; 00272 } 00273 00274 00282 inline Real length () const 00283 { 00284 return Math::Sqrt( x * x + y * y + z * z ); 00285 } 00286 00297 inline Real squaredLength () const 00298 { 00299 return x * x + y * y + z * z; 00300 } 00301 00316 inline Real dotProduct(const Vector3& vec) const 00317 { 00318 return x * vec.x + y * vec.y + z * vec.z; 00319 } 00320 00330 inline Real normalise() 00331 { 00332 Real fLength = Math::Sqrt( x * x + y * y + z * z ); 00333 00334 // Will also work for zero-sized vectors, but will change nothing 00335 if ( fLength > 1e-08 ) 00336 { 00337 Real fInvLength = 1.0 / fLength; 00338 x *= fInvLength; 00339 y *= fInvLength; 00340 z *= fInvLength; 00341 } 00342 00343 return fLength; 00344 } 00345 00373 inline Vector3 crossProduct( const Vector3& rkVector ) const 00374 { 00375 Vector3 kCross; 00376 00377 kCross.x = y * rkVector.z - z * rkVector.y; 00378 kCross.y = z * rkVector.x - x * rkVector.z; 00379 kCross.z = x * rkVector.y - y * rkVector.x; 00380 00381 return kCross; 00382 } 00383 00387 inline Vector3 midPoint( const Vector3& vec ) const 00388 { 00389 return Vector3( 00390 ( x + vec.x ) * 0.5, 00391 ( y + vec.y ) * 0.5, 00392 ( z + vec.z ) * 0.5 ); 00393 } 00394 00398 inline bool operator < ( const Vector3& rhs ) const 00399 { 00400 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00401 return true; 00402 return false; 00403 } 00404 00408 inline bool operator > ( const Vector3& rhs ) const 00409 { 00410 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00411 return true; 00412 return false; 00413 } 00414 00422 inline void makeFloor( const Vector3& cmp ) 00423 { 00424 if( cmp.x < x ) x = cmp.x; 00425 if( cmp.y < y ) y = cmp.y; 00426 if( cmp.z < z ) z = cmp.z; 00427 } 00428 00436 inline void makeCeil( const Vector3& cmp ) 00437 { 00438 if( cmp.x > x ) x = cmp.x; 00439 if( cmp.y > y ) y = cmp.y; 00440 if( cmp.z > z ) z = cmp.z; 00441 } 00442 00450 inline Vector3 perpendicular(void) const 00451 { 00452 static const Real fSquareZero = 1e-06 * 1e-06; 00453 00454 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00455 00456 // Check length 00457 if( perp.squaredLength() < fSquareZero ) 00458 { 00459 /* This vector is the Y axis multiplied by a scalar, so we have 00460 to use another axis. 00461 */ 00462 perp = this->crossProduct( Vector3::UNIT_Y ); 00463 } 00464 00465 return perp; 00466 } 00486 inline Vector3 randomDeviant( 00487 const Radian& angle, 00488 const Vector3& up = Vector3::ZERO ) const 00489 { 00490 Vector3 newUp; 00491 00492 if (up == Vector3::ZERO) 00493 { 00494 // Generate an up vector 00495 newUp = this->perpendicular(); 00496 } 00497 else 00498 { 00499 newUp = up; 00500 } 00501 00502 // Rotate up vector by random amount around this 00503 Quaternion q; 00504 q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00505 newUp = q * newUp; 00506 00507 // Finally rotate this by given angle around randomised up 00508 q.FromAngleAxis( angle, newUp ); 00509 return q * (*this); 00510 } 00511 #ifndef OGRE_FORCE_ANGLE_TYPES 00512 inline Vector3 randomDeviant( 00513 Real angle, 00514 const Vector3& up = Vector3::ZERO ) const 00515 { 00516 return randomDeviant ( Radian(angle), up ); 00517 } 00518 #endif//OGRE_FORCE_ANGLE_TYPES 00519 00526 Quaternion getRotationTo(const Vector3& dest) const 00527 { 00528 // Based on Stan Melax's article in Game Programming Gems 00529 Quaternion q; 00530 // Copy, since cannot modify local 00531 Vector3 v0 = *this; 00532 Vector3 v1 = dest; 00533 v0.normalise(); 00534 v1.normalise(); 00535 00536 Vector3 c = v0.crossProduct(v1); 00537 00538 Real d = v0.dotProduct(v1); 00539 // If dot == 1, vectors are the same 00540 if (d >= 1.0f) 00541 { 00542 return Quaternion::IDENTITY; 00543 } 00544 // NB if the crossProduct approaches zero, we get unstable because ANY axis will do 00545 // when v0 == -v1 00546 if (c.isZeroLength()) 00547 { 00548 Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00549 if (axis.isZeroLength()) // pick another if colinear 00550 axis = Vector3::UNIT_Y.crossProduct(*this); 00551 axis.normalise(); 00552 Quaternion ret; 00553 ret.FromAngleAxis(Radian(Math::PI), axis); 00554 return ret; 00555 } 00556 Real s = Math::Sqrt( (1+d)*2 ); 00557 assert (s != 0 && "Divide by zero!"); 00558 Real invs = 1 / s; 00559 00560 00561 q.x = c.x * invs; 00562 q.y = c.y * invs; 00563 q.z = c.z * invs; 00564 q.w = s * 0.5; 00565 return q; 00566 } 00567 00569 inline bool isZeroLength(void) const 00570 { 00571 Real sqlen = (x * x) + (y * y) + (z * z); 00572 return (sqlen < (1e-06 * 1e-06)); 00573 00574 } 00575 00578 inline Vector3 normalisedCopy(void) const 00579 { 00580 Vector3 ret = *this; 00581 ret.normalise(); 00582 return ret; 00583 } 00584 00588 inline Vector3 reflect(const Vector3& normal) const 00589 { 00590 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00591 } 00592 00599 inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const 00600 { 00601 return Math::RealEqual(x, rhs.x, tolerance) && 00602 Math::RealEqual(y, rhs.y, tolerance) && 00603 Math::RealEqual(z, rhs.z, tolerance); 00604 00605 } 00612 inline bool directionEquals(const Vector3& rhs, 00613 const Radian& tolerance) const 00614 { 00615 Real dot = dotProduct(rhs); 00616 Radian angle = Math::ACos(dot); 00617 00618 return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00619 00620 } 00621 00622 // special points 00623 static const Vector3 ZERO; 00624 static const Vector3 UNIT_X; 00625 static const Vector3 UNIT_Y; 00626 static const Vector3 UNIT_Z; 00627 static const Vector3 NEGATIVE_UNIT_X; 00628 static const Vector3 NEGATIVE_UNIT_Y; 00629 static const Vector3 NEGATIVE_UNIT_Z; 00630 static const Vector3 UNIT_SCALE; 00631 00634 inline _OgreExport friend std::ostream& operator << 00635 ( std::ostream& o, const Vector3& v ) 00636 { 00637 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00638 return o; 00639 } 00640 }; 00641 00642 } 00643 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Feb 12 12:59:54 2006