libmove3d
3.13.0
|
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 <cstring> 00033 #include <iostream> 00034 #include <cassert> 00035 #include <cmath> 00036 #include "p3d_matrix.h" 00037 00038 //namespace Ogre 00039 //{ 00040 00048 class Vector3 00049 { 00050 public: 00051 double x, y, z; 00052 00053 public: 00054 inline Vector3() 00055 { 00056 } 00057 00058 inline Vector3( const double fX, const double fY, const double fZ ) 00059 : x( fX ), y( fY ), z( fZ ) 00060 { 00061 } 00062 00063 inline explicit Vector3( const double afCoordinate[3] ) 00064 : x( afCoordinate[0] ), 00065 y( afCoordinate[1] ), 00066 z( afCoordinate[2] ) 00067 { 00068 } 00069 00070 inline explicit Vector3( const int afCoordinate[3] ) 00071 { 00072 x = (double)afCoordinate[0]; 00073 y = (double)afCoordinate[1]; 00074 z = (double)afCoordinate[2]; 00075 } 00076 00077 inline explicit Vector3( const p3d_matrix4 m ) 00078 { 00079 x = m[0][3]; 00080 y = m[1][3]; 00081 z = m[2][3]; 00082 } 00083 00084 inline explicit Vector3( double* const r ) 00085 : x( r[0] ), y( r[1] ), z( r[2] ) 00086 { 00087 } 00088 00089 inline explicit Vector3( const double scaler ) 00090 : x( scaler ) 00091 , y( scaler ) 00092 , z( scaler ) 00093 { 00094 } 00095 00096 inline int size() const { return 3; } 00097 00098 00099 inline double operator [] ( const size_t i ) const 00100 { 00101 assert( i < 3 ); 00102 00103 return *(&x+i); 00104 } 00105 00106 inline double& operator [] ( const size_t i ) 00107 { 00108 assert( i < 3 ); 00109 00110 return *(&x+i); 00111 } 00113 inline double* ptr() 00114 { 00115 return &x; 00116 } 00118 inline const double* ptr() const 00119 { 00120 return &x; 00121 } 00122 00127 inline Vector3& operator = ( const Vector3& rkVector ) 00128 { 00129 x = rkVector.x; 00130 y = rkVector.y; 00131 z = rkVector.z; 00132 00133 return *this; 00134 } 00135 00136 inline Vector3& operator = ( const double fScaler ) 00137 { 00138 x = fScaler; 00139 y = fScaler; 00140 z = fScaler; 00141 00142 return *this; 00143 } 00144 00145 inline bool operator == ( const Vector3& rkVector ) const 00146 { 00147 return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); 00148 } 00149 00150 inline bool operator != ( const Vector3& rkVector ) const 00151 { 00152 return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); 00153 } 00154 00155 // arithmetic operations 00156 inline Vector3 operator + ( const Vector3& rkVector ) const 00157 { 00158 return Vector3( 00159 x + rkVector.x, 00160 y + rkVector.y, 00161 z + rkVector.z); 00162 } 00163 00164 inline Vector3 operator - ( const Vector3& rkVector ) const 00165 { 00166 return Vector3( 00167 x - rkVector.x, 00168 y - rkVector.y, 00169 z - rkVector.z); 00170 } 00171 00172 inline Vector3 operator * ( const double fScalar ) const 00173 { 00174 return Vector3( 00175 x * fScalar, 00176 y * fScalar, 00177 z * fScalar); 00178 } 00179 00180 inline Vector3 operator * ( const Vector3& rhs) const 00181 { 00182 return Vector3( 00183 x * rhs.x, 00184 y * rhs.y, 00185 z * rhs.z); 00186 } 00187 00188 inline Vector3 operator / ( const double fScalar ) const 00189 { 00190 assert( fScalar != 0.0 ); 00191 00192 double fInv = 1.0 / fScalar; 00193 00194 return Vector3( 00195 x * fInv, 00196 y * fInv, 00197 z * fInv); 00198 } 00199 00200 inline Vector3 operator / ( const Vector3& rhs) const 00201 { 00202 return Vector3( 00203 x / rhs.x, 00204 y / rhs.y, 00205 z / rhs.z); 00206 } 00207 00208 inline const Vector3& operator + () const 00209 { 00210 return *this; 00211 } 00212 00213 inline Vector3 operator - () const 00214 { 00215 return Vector3(-x, -y, -z); 00216 } 00217 00218 // overloaded operators to help Vector3 00219 inline friend Vector3 operator * ( const double fScalar, const Vector3& rkVector ) 00220 { 00221 return Vector3( 00222 fScalar * rkVector.x, 00223 fScalar * rkVector.y, 00224 fScalar * rkVector.z); 00225 } 00226 00227 inline friend Vector3 operator / ( const double fScalar, const Vector3& rkVector ) 00228 { 00229 return Vector3( 00230 fScalar / rkVector.x, 00231 fScalar / rkVector.y, 00232 fScalar / rkVector.z); 00233 } 00234 00235 inline friend Vector3 operator + (const Vector3& lhs, const double rhs) 00236 { 00237 return Vector3( 00238 lhs.x + rhs, 00239 lhs.y + rhs, 00240 lhs.z + rhs); 00241 } 00242 00243 inline friend Vector3 operator + (const double lhs, const Vector3& rhs) 00244 { 00245 return Vector3( 00246 lhs + rhs.x, 00247 lhs + rhs.y, 00248 lhs + rhs.z); 00249 } 00250 00251 inline friend Vector3 operator - (const Vector3& lhs, const double rhs) 00252 { 00253 return Vector3( 00254 lhs.x - rhs, 00255 lhs.y - rhs, 00256 lhs.z - rhs); 00257 } 00258 00259 inline friend Vector3 operator - (const double lhs, const Vector3& rhs) 00260 { 00261 return Vector3( 00262 lhs - rhs.x, 00263 lhs - rhs.y, 00264 lhs - rhs.z); 00265 } 00266 00267 // arithmetic updates 00268 inline Vector3& operator += ( const Vector3& rkVector ) 00269 { 00270 x += rkVector.x; 00271 y += rkVector.y; 00272 z += rkVector.z; 00273 00274 return *this; 00275 } 00276 00277 inline Vector3& operator += ( const double fScalar ) 00278 { 00279 x += fScalar; 00280 y += fScalar; 00281 z += fScalar; 00282 return *this; 00283 } 00284 00285 inline Vector3& operator -= ( const Vector3& rkVector ) 00286 { 00287 x -= rkVector.x; 00288 y -= rkVector.y; 00289 z -= rkVector.z; 00290 00291 return *this; 00292 } 00293 00294 inline Vector3& operator -= ( const double fScalar ) 00295 { 00296 x -= fScalar; 00297 y -= fScalar; 00298 z -= fScalar; 00299 return *this; 00300 } 00301 00302 inline Vector3& operator *= ( const double fScalar ) 00303 { 00304 x *= fScalar; 00305 y *= fScalar; 00306 z *= fScalar; 00307 return *this; 00308 } 00309 00310 inline Vector3& operator *= ( const Vector3& rkVector ) 00311 { 00312 x *= rkVector.x; 00313 y *= rkVector.y; 00314 z *= rkVector.z; 00315 00316 return *this; 00317 } 00318 00319 inline Vector3& operator /= ( const double fScalar ) 00320 { 00321 assert( fScalar != 0.0 ); 00322 00323 double fInv = 1.0 / fScalar; 00324 00325 x *= fInv; 00326 y *= fInv; 00327 z *= fInv; 00328 00329 return *this; 00330 } 00331 00332 inline Vector3& operator /= ( const Vector3& rkVector ) 00333 { 00334 x /= rkVector.x; 00335 y /= rkVector.y; 00336 z /= rkVector.z; 00337 00338 return *this; 00339 } 00340 00341 00349 inline double length () const 00350 { 00351 return sqrt( x * x + y * y + z * z ); 00352 } 00353 00364 inline double squaredLength () const 00365 { 00366 return x * x + y * y + z * z; 00367 } 00368 00376 inline double distance(const Vector3& rhs) const 00377 { 00378 return (*this - rhs).length(); 00379 } 00380 00391 inline double squaredDistance(const Vector3& rhs) const 00392 { 00393 return (*this - rhs).squaredLength(); 00394 } 00395 00410 inline double dotProduct(const Vector3& vec) const 00411 { 00412 return x * vec.x + y * vec.y + z * vec.z; 00413 } 00414 00425 inline double absDotProduct(const Vector3& vec) const 00426 { 00427 return abs(x * vec.x) + abs(y * vec.y) + abs(z * vec.z); 00428 } 00429 00439 inline double normalise() 00440 { 00441 double fLength = sqrt( x * x + y * y + z * z ); 00442 00443 // Will also work for zero-sized vectors, but will change nothing 00444 if ( fLength > 1e-08 ) 00445 { 00446 double fInvLength = 1.0 / fLength; 00447 x *= fInvLength; 00448 y *= fInvLength; 00449 z *= fInvLength; 00450 } 00451 00452 return fLength; 00453 } 00454 00483 inline Vector3 crossProduct( const Vector3& rkVector ) const 00484 { 00485 return Vector3( 00486 y * rkVector.z - z * rkVector.y, 00487 z * rkVector.x - x * rkVector.z, 00488 x * rkVector.y - y * rkVector.x); 00489 } 00490 00494 inline Vector3 midPoint( const Vector3& vec ) const 00495 { 00496 return Vector3( 00497 ( x + vec.x ) * 0.5, 00498 ( y + vec.y ) * 0.5, 00499 ( z + vec.z ) * 0.5 ); 00500 } 00501 00505 inline bool operator < ( const Vector3& rhs ) const 00506 { 00507 if( x < rhs.x && y < rhs.y && z < rhs.z ) 00508 return true; 00509 return false; 00510 } 00511 00515 inline bool operator > ( const Vector3& rhs ) const 00516 { 00517 if( x > rhs.x && y > rhs.y && z > rhs.z ) 00518 return true; 00519 return false; 00520 } 00521 00529 inline void makeFloor( const Vector3& cmp ) 00530 { 00531 if( cmp.x < x ) x = cmp.x; 00532 if( cmp.y < y ) y = cmp.y; 00533 if( cmp.z < z ) z = cmp.z; 00534 } 00535 00543 inline void makeCeil( const Vector3& cmp ) 00544 { 00545 if( cmp.x > x ) x = cmp.x; 00546 if( cmp.y > y ) y = cmp.y; 00547 if( cmp.z > z ) z = cmp.z; 00548 } 00549 00557 inline Vector3 perpendicular(void) const 00558 { 00559 static const double fSquareZero = 1e-06 * 1e-06; 00560 00561 Vector3 perp = this->crossProduct( Vector3::UNIT_X ); 00562 00563 // Check length 00564 if( perp.squaredLength() < fSquareZero ) 00565 { 00566 /* This vector is the Y axis multiplied by a scalar, so we have 00567 to use another axis. 00568 */ 00569 perp = this->crossProduct( Vector3::UNIT_Y ); 00570 } 00571 perp.normalise(); 00572 00573 return perp; 00574 } 00594 // inline Vector3 randomDeviant( 00595 // const Radian& angle, 00596 // const Vector3& up = Vector3::ZERO ) const 00597 // { 00598 // Vector3 newUp; 00599 // 00600 // if (up == Vector3::ZERO) 00601 // { 00602 // // Generate an up vector 00603 // newUp = this->perpendicular(); 00604 // } 00605 // else 00606 // { 00607 // newUp = up; 00608 // } 00609 // 00610 // // Rotate up vector by random amount around this 00611 // Quaternion q; 00612 // q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this ); 00613 // newUp = q * newUp; 00614 // 00615 // // Finally rotate this by given angle around randomised up 00616 // q.FromAngleAxis( angle, newUp ); 00617 // return q * (*this); 00618 // } 00619 00624 // inline Radian angleBetween(const Vector3& dest) 00625 // { 00626 // double lenProduct = length() * dest.length(); 00627 // 00628 // // Divide by zero check 00629 // if(lenProduct < 1e-6f) 00630 // lenProduct = 1e-6f; 00631 // 00632 // double f = dotProduct(dest) / lenProduct; 00633 // 00634 // f = Math::Clamp(f, (double)-1.0, (double)1.0); 00635 // return Math::ACos(f); 00636 // 00637 // } 00646 // Quaternion getRotationTo(const Vector3& dest, 00647 // const Vector3& fallbackAxis = Vector3::ZERO) const 00648 // { 00649 // // Based on Stan Melax's article in Game Programming Gems 00650 // Quaternion q; 00651 // // Copy, since cannot modify local 00652 // Vector3 v0 = *this; 00653 // Vector3 v1 = dest; 00654 // v0.normalise(); 00655 // v1.normalise(); 00656 // 00657 // double d = v0.dotProduct(v1); 00658 // // If dot == 1, vectors are the same 00659 // if (d >= 1.0f) 00660 // { 00661 // return Quaternion::IDENTITY; 00662 // } 00663 // if (d < (1e-6f - 1.0f)) 00664 // { 00665 // if (fallbackAxis != Vector3::ZERO) 00666 // { 00667 // // rotate 180 degrees about the fallback axis 00668 // q.FromAngleAxis(Radian(Math::PI), fallbackAxis); 00669 // } 00670 // else 00671 // { 00672 // // Generate an axis 00673 // Vector3 axis = Vector3::UNIT_X.crossProduct(*this); 00674 // if (axis.isZeroLength()) // pick another if colinear 00675 // axis = Vector3::UNIT_Y.crossProduct(*this); 00676 // axis.normalise(); 00677 // q.FromAngleAxis(Radian(Math::PI), axis); 00678 // } 00679 // } 00680 // else 00681 // { 00682 // double s = Math::Sqrt( (1+d)*2 ); 00683 // double invs = 1 / s; 00684 // 00685 // Vector3 c = v0.crossProduct(v1); 00686 // 00687 // q.x = c.x * invs; 00688 // q.y = c.y * invs; 00689 // q.z = c.z * invs; 00690 // q.w = s * 0.5; 00691 // q.normalise(); 00692 // } 00693 // return q; 00694 // } 00695 00697 inline bool isZeroLength(void) const 00698 { 00699 double sqlen = (x * x) + (y * y) + (z * z); 00700 return (sqlen < (1e-06 * 1e-06)); 00701 00702 } 00703 00706 inline Vector3 normalisedCopy(void) const 00707 { 00708 Vector3 ret = *this; 00709 ret.normalise(); 00710 return ret; 00711 } 00712 00716 inline Vector3 reflect(const Vector3& normal) const 00717 { 00718 return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) ); 00719 } 00720 00727 inline bool positionEquals(const Vector3& rhs, double tolerance = 1e-03) const 00728 { 00729 return doubleEqual(x, rhs.x, tolerance) && 00730 doubleEqual(y, rhs.y, tolerance) && 00731 doubleEqual(z, rhs.z, tolerance); 00732 00733 } 00734 00735 bool doubleEqual(const double& a, const double& b, const double& tolerance) const 00736 { 00737 if (fabs(b-a) <= tolerance) 00738 return true; 00739 else 00740 return false; 00741 } 00742 00749 inline bool positionCloses(const Vector3& rhs, double tolerance = 1e-03f) const 00750 { 00751 return squaredDistance(rhs) <= 00752 (squaredLength() + rhs.squaredLength()) * tolerance; 00753 } 00754 00762 // inline bool directionEquals(const Vector3& rhs, 00763 // const Radian& tolerance) const 00764 // { 00765 // double dot = dotProduct(rhs); 00766 // Radian angle = Math::ACos(dot); 00767 // 00768 // return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); 00769 // 00770 // } 00771 00772 // special points 00773 static const Vector3 ZERO; 00774 static const Vector3 UNIT_X; 00775 static const Vector3 UNIT_Y; 00776 static const Vector3 UNIT_Z; 00777 static const Vector3 NEGATIVE_UNIT_X; 00778 static const Vector3 NEGATIVE_UNIT_Y; 00779 static const Vector3 NEGATIVE_UNIT_Z; 00780 static const Vector3 UNIT_SCALE; 00781 00784 friend std::ostream& operator << 00785 ( std::ostream& o, const Vector3& v ) 00786 { 00787 o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")"; 00788 return o; 00789 } 00790 }; 00791 //} 00792 #endif