Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2633 lines
63 KiB

  1. //====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef VECTOR_H
  9. #define VECTOR_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include <math.h>
  14. #include <float.h>
  15. // For vec_t, put this somewhere else?
  16. #include "tier0/basetypes.h"
  17. #if defined( _PS3 )
  18. //#include <ssemath.h>
  19. #include <vectormath/c/vectormath_aos.h>
  20. #include "platform.h"
  21. #include "mathlib/math_pfns.h"
  22. #endif
  23. #ifndef PLATFORM_PPC // we want our linux with xmm support
  24. // For MMX intrinsics
  25. #include <xmmintrin.h>
  26. #endif
  27. #ifndef ALIGN16_POST
  28. #define ALIGN16_POST
  29. #endif
  30. #include "tier0/dbg.h"
  31. #include "tier0/platform.h"
  32. #include "tier0/threadtools.h"
  33. #include "mathlib/vector2d.h"
  34. #include "mathlib/math_pfns.h"
  35. #include "tier0/memalloc.h"
  36. #include "vstdlib/random.h"
  37. // Uncomment this to add extra Asserts to check for NANs, uninitialized vecs, etc.
  38. //#define VECTOR_PARANOIA 1
  39. // Uncomment this to make sure we don't do anything slow with our vectors
  40. //#define VECTOR_NO_SLOW_OPERATIONS 1
  41. // Used to make certain code easier to read.
  42. #define X_INDEX 0
  43. #define Y_INDEX 1
  44. #define Z_INDEX 2
  45. #ifdef VECTOR_PARANOIA
  46. #define CHECK_VALID( _v) Assert( (_v).IsValid() )
  47. #else
  48. #ifdef GNUC
  49. #define CHECK_VALID( _v)
  50. #else
  51. #define CHECK_VALID( _v) 0
  52. #endif
  53. #endif
  54. #define VecToString(v) (static_cast<const char *>(CFmtStr("(%f, %f, %f)", (v).x, (v).y, (v).z))) // ** Note: this generates a temporary, don't hold reference!
  55. class VectorByValue;
  56. //=========================================================
  57. // 3D Vector
  58. //=========================================================
  59. class Vector
  60. {
  61. public:
  62. // Members
  63. vec_t x, y, z;
  64. // Construction/destruction:
  65. Vector(void);
  66. Vector(vec_t X, vec_t Y, vec_t Z);
  67. // Initialization
  68. void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f);
  69. // TODO (Ilya): Should there be an init that takes a single float for consistency?
  70. // Got any nasty NAN's?
  71. bool IsValid() const;
  72. void Invalidate();
  73. // array access...
  74. vec_t operator[](int i) const;
  75. vec_t& operator[](int i);
  76. // Base address...
  77. vec_t* Base();
  78. vec_t const* Base() const;
  79. // Cast to Vector2D...
  80. Vector2D& AsVector2D();
  81. const Vector2D& AsVector2D() const;
  82. // Initialization methods
  83. void Random( vec_t minVal, vec_t maxVal );
  84. inline void Zero(); ///< zero out a vector
  85. // equality
  86. bool operator==(const Vector& v) const;
  87. bool operator!=(const Vector& v) const;
  88. // arithmetic operations
  89. FORCEINLINE Vector& operator+=(const Vector &v);
  90. FORCEINLINE Vector& operator-=(const Vector &v);
  91. FORCEINLINE Vector& operator*=(const Vector &v);
  92. FORCEINLINE Vector& operator*=(float s);
  93. FORCEINLINE Vector& operator/=(const Vector &v);
  94. FORCEINLINE Vector& operator/=(float s);
  95. FORCEINLINE Vector& operator+=(float fl) ; ///< broadcast add
  96. FORCEINLINE Vector& operator-=(float fl) ; ///< broadcast sub
  97. // negate the vector components
  98. void Negate();
  99. // Get the vector's magnitude.
  100. inline vec_t Length() const;
  101. // Get the vector's magnitude squared.
  102. FORCEINLINE vec_t LengthSqr(void) const
  103. {
  104. CHECK_VALID(*this);
  105. return (x*x + y*y + z*z);
  106. }
  107. // Get one over the vector's length
  108. // via fast hardware approximation
  109. inline vec_t LengthRecipFast(void) const
  110. {
  111. return FastRSqrtFast( LengthSqr() );
  112. }
  113. // return true if this vector is (0,0,0) within tolerance
  114. bool IsZero( float tolerance = 0.01f ) const
  115. {
  116. return (x > -tolerance && x < tolerance &&
  117. y > -tolerance && y < tolerance &&
  118. z > -tolerance && z < tolerance);
  119. }
  120. // return true if this vector is exactly (0,0,0) -- only fast if vector is coming from memory, not registers
  121. inline bool IsZeroFast( ) const RESTRICT
  122. {
  123. COMPILE_TIME_ASSERT( sizeof(vec_t) == sizeof(int) );
  124. return ( *(const int *)(&x) == 0 &&
  125. *(const int *)(&y) == 0 &&
  126. *(const int *)(&z) == 0 );
  127. }
  128. vec_t NormalizeInPlace();
  129. Vector Normalized() const;
  130. bool IsLengthGreaterThan( float val ) const;
  131. bool IsLengthLessThan( float val ) const;
  132. // check if a vector is within the box defined by two other vectors
  133. FORCEINLINE bool WithinAABox( Vector const &boxmin, Vector const &boxmax);
  134. // Get the distance from this vector to the other one.
  135. vec_t DistTo(const Vector &vOther) const;
  136. // Get the distance from this vector to the other one squared.
  137. // NJS: note, VC wasn't inlining it correctly in several deeply nested inlines due to being an 'out of line' inline.
  138. // may be able to tidy this up after switching to VC7
  139. FORCEINLINE vec_t DistToSqr(const Vector &vOther) const
  140. {
  141. Vector delta;
  142. delta.x = x - vOther.x;
  143. delta.y = y - vOther.y;
  144. delta.z = z - vOther.z;
  145. return delta.LengthSqr();
  146. }
  147. // Copy
  148. void CopyToArray(float* rgfl) const;
  149. // Multiply, add, and assign to this (ie: *this = a + b * scalar). This
  150. // is about 12% faster than the actual vector equation (because it's done per-component
  151. // rather than per-vector).
  152. void MulAdd(const Vector& a, const Vector& b, float scalar);
  153. // Dot product.
  154. vec_t Dot(const Vector& vOther) const;
  155. // assignment
  156. Vector& operator=(const Vector &vOther);
  157. // returns 0, 1, 2 corresponding to the component with the largest absolute value
  158. inline int LargestComponent() const;
  159. // 2d
  160. vec_t Length2D(void) const;
  161. vec_t Length2DSqr(void) const;
  162. /// get the component of this vector parallel to some other given vector
  163. inline Vector ProjectOnto( const Vector& onto );
  164. operator VectorByValue &() { return *((VectorByValue *)(this)); }
  165. operator const VectorByValue &() const { return *((const VectorByValue *)(this)); }
  166. #ifndef VECTOR_NO_SLOW_OPERATIONS
  167. // copy constructors
  168. // Vector(const Vector &vOther);
  169. // arithmetic operations
  170. Vector operator-(void) const;
  171. Vector operator+(const Vector& v) const;
  172. Vector operator-(const Vector& v) const;
  173. Vector operator*(const Vector& v) const;
  174. Vector operator/(const Vector& v) const;
  175. Vector operator*(float fl) const;
  176. Vector operator/(float fl) const;
  177. // Cross product between two vectors.
  178. Vector Cross(const Vector &vOther) const;
  179. // Returns a vector with the min or max in X, Y, and Z.
  180. Vector Min(const Vector &vOther) const;
  181. Vector Max(const Vector &vOther) const;
  182. #else
  183. private:
  184. // No copy constructors allowed if we're in optimal mode
  185. Vector(const Vector& vOther);
  186. #endif
  187. };
  188. #define USE_M64S defined( PLATFORM_WINDOWS_PC )
  189. //=========================================================
  190. // 4D Short Vector (aligned on 8-byte boundary)
  191. //=========================================================
  192. class ALIGN8 ShortVector
  193. {
  194. public:
  195. short x, y, z, w;
  196. // Initialization
  197. void Init(short ix = 0, short iy = 0, short iz = 0, short iw = 0 );
  198. #if USE_M64S
  199. __m64 &AsM64() { return *(__m64*)&x; }
  200. const __m64 &AsM64() const { return *(const __m64*)&x; }
  201. #endif
  202. // Setter
  203. void Set( const ShortVector& vOther );
  204. void Set( const short ix, const short iy, const short iz, const short iw );
  205. // array access...
  206. short operator[](int i) const;
  207. short& operator[](int i);
  208. // Base address...
  209. short* Base();
  210. short const* Base() const;
  211. // equality
  212. bool operator==(const ShortVector& v) const;
  213. bool operator!=(const ShortVector& v) const;
  214. // Arithmetic operations
  215. FORCEINLINE ShortVector& operator+=(const ShortVector &v);
  216. FORCEINLINE ShortVector& operator-=(const ShortVector &v);
  217. FORCEINLINE ShortVector& operator*=(const ShortVector &v);
  218. FORCEINLINE ShortVector& operator*=(float s);
  219. FORCEINLINE ShortVector& operator/=(const ShortVector &v);
  220. FORCEINLINE ShortVector& operator/=(float s);
  221. FORCEINLINE ShortVector operator*(float fl) const;
  222. private:
  223. // No copy constructors allowed if we're in optimal mode
  224. // ShortVector(ShortVector const& vOther);
  225. // No assignment operators either...
  226. // ShortVector& operator=( ShortVector const& src );
  227. } ALIGN8_POST;
  228. //=========================================================
  229. // 4D Integer Vector
  230. //=========================================================
  231. class IntVector4D
  232. {
  233. public:
  234. int x, y, z, w;
  235. // Initialization
  236. void Init(int ix = 0, int iy = 0, int iz = 0, int iw = 0 );
  237. #if USE_M64S
  238. __m64 &AsM64() { return *(__m64*)&x; }
  239. const __m64 &AsM64() const { return *(const __m64*)&x; }
  240. #endif
  241. // Setter
  242. void Set( const IntVector4D& vOther );
  243. void Set( const int ix, const int iy, const int iz, const int iw );
  244. // array access...
  245. int operator[](int i) const;
  246. int& operator[](int i);
  247. // Base address...
  248. int* Base();
  249. int const* Base() const;
  250. // equality
  251. bool operator==(const IntVector4D& v) const;
  252. bool operator!=(const IntVector4D& v) const;
  253. // Arithmetic operations
  254. FORCEINLINE IntVector4D& operator+=(const IntVector4D &v);
  255. FORCEINLINE IntVector4D& operator-=(const IntVector4D &v);
  256. FORCEINLINE IntVector4D& operator*=(const IntVector4D &v);
  257. FORCEINLINE IntVector4D& operator*=(float s);
  258. FORCEINLINE IntVector4D& operator/=(const IntVector4D &v);
  259. FORCEINLINE IntVector4D& operator/=(float s);
  260. FORCEINLINE IntVector4D operator*(float fl) const;
  261. private:
  262. // No copy constructors allowed if we're in optimal mode
  263. // IntVector4D(IntVector4D const& vOther);
  264. // No assignment operators either...
  265. // IntVector4D& operator=( IntVector4D const& src );
  266. };
  267. //-----------------------------------------------------------------------------
  268. // Allows us to specifically pass the vector by value when we need to
  269. //-----------------------------------------------------------------------------
  270. class VectorByValue : public Vector
  271. {
  272. public:
  273. // Construction/destruction:
  274. VectorByValue(void) : Vector() {}
  275. VectorByValue(vec_t X, vec_t Y, vec_t Z) : Vector( X, Y, Z ) {}
  276. VectorByValue(const VectorByValue& vOther) { *this = vOther; }
  277. };
  278. //-----------------------------------------------------------------------------
  279. // Utility to simplify table construction. No constructor means can use
  280. // traditional C-style initialization
  281. //-----------------------------------------------------------------------------
  282. class TableVector
  283. {
  284. public:
  285. vec_t x, y, z;
  286. operator Vector &() { return *((Vector *)(this)); }
  287. operator const Vector &() const { return *((const Vector *)(this)); }
  288. // array access...
  289. inline vec_t& operator[](int i)
  290. {
  291. Assert( (i >= 0) && (i < 3) );
  292. return ((vec_t*)this)[i];
  293. }
  294. inline vec_t operator[](int i) const
  295. {
  296. Assert( (i >= 0) && (i < 3) );
  297. return ((vec_t*)this)[i];
  298. }
  299. };
  300. //-----------------------------------------------------------------------------
  301. // Here's where we add all those lovely SSE optimized routines
  302. //-----------------------------------------------------------------------------
  303. class ALIGN16 VectorAligned : public Vector
  304. {
  305. public:
  306. inline VectorAligned(void) {};
  307. inline VectorAligned(vec_t X, vec_t Y, vec_t Z)
  308. {
  309. Init(X,Y,Z);
  310. }
  311. #ifdef VECTOR_NO_SLOW_OPERATIONS
  312. private:
  313. // No copy constructors allowed if we're in optimal mode
  314. VectorAligned(const VectorAligned& vOther);
  315. VectorAligned(const Vector &vOther);
  316. #else
  317. public:
  318. explicit VectorAligned(const Vector &vOther)
  319. {
  320. Init(vOther.x, vOther.y, vOther.z);
  321. }
  322. VectorAligned& operator=(const Vector &vOther)
  323. {
  324. Init(vOther.x, vOther.y, vOther.z);
  325. return *this;
  326. }
  327. VectorAligned& operator=(const VectorAligned &vOther)
  328. {
  329. // we know we're aligned, so use simd
  330. // we can't use the convenient abstract interface coz it gets declared later
  331. #ifdef _X360
  332. XMStoreVector4A(Base(), XMLoadVector4A(vOther.Base()));
  333. #elif _WIN32
  334. _mm_store_ps(Base(), _mm_load_ps( vOther.Base() ));
  335. #else
  336. Init(vOther.x, vOther.y, vOther.z);
  337. #endif
  338. return *this;
  339. }
  340. #endif
  341. float w; // this space is used anyway
  342. #if !defined(NO_MALLOC_OVERRIDE)
  343. void* operator new[] ( size_t nSize)
  344. {
  345. return MemAlloc_AllocAligned(nSize, 16);
  346. }
  347. void* operator new[] ( size_t nSize, const char *pFileName, int nLine)
  348. {
  349. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  350. }
  351. void* operator new[] ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine)
  352. {
  353. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  354. }
  355. void operator delete[] ( void* p)
  356. {
  357. MemAlloc_FreeAligned(p);
  358. }
  359. void operator delete[] ( void* p, const char *pFileName, int nLine)
  360. {
  361. MemAlloc_FreeAligned(p, pFileName, nLine);
  362. }
  363. void operator delete[] ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
  364. {
  365. MemAlloc_FreeAligned(p, pFileName, nLine);
  366. }
  367. // please don't allocate a single quaternion...
  368. void* operator new ( size_t nSize )
  369. {
  370. return MemAlloc_AllocAligned(nSize, 16);
  371. }
  372. void* operator new ( size_t nSize, const char *pFileName, int nLine )
  373. {
  374. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  375. }
  376. void* operator new ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine )
  377. {
  378. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  379. }
  380. void operator delete ( void* p)
  381. {
  382. MemAlloc_FreeAligned(p);
  383. }
  384. void operator delete ( void* p, const char *pFileName, int nLine)
  385. {
  386. MemAlloc_FreeAligned(p, pFileName, nLine);
  387. }
  388. void operator delete ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
  389. {
  390. MemAlloc_FreeAligned(p, pFileName, nLine);
  391. }
  392. #endif
  393. } ALIGN16_POST;
  394. //-----------------------------------------------------------------------------
  395. // Vector related operations
  396. //-----------------------------------------------------------------------------
  397. // Vector clear
  398. FORCEINLINE void VectorClear( Vector& a );
  399. // Copy
  400. FORCEINLINE void VectorCopy( const Vector& src, Vector& dst );
  401. // Vector arithmetic
  402. FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& result );
  403. FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& result );
  404. FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& result );
  405. FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& result );
  406. FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& result );
  407. FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& result );
  408. inline void VectorScale ( const Vector& in, vec_t scale, Vector& result );
  409. void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest );
  410. // Vector equality with tolerance
  411. bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance = 0.0f );
  412. #define VectorExpand(v) (v).x, (v).y, (v).z
  413. // Normalization
  414. // FIXME: Can't use quite yet
  415. //vec_t VectorNormalize( Vector& v );
  416. // Length
  417. inline vec_t VectorLength( const Vector& v );
  418. // Dot Product
  419. FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b);
  420. // Cross product
  421. void CrossProduct(const Vector& a, const Vector& b, Vector& result );
  422. // Store the min or max of each of x, y, and z into the result.
  423. void VectorMin( const Vector &a, const Vector &b, Vector &result );
  424. void VectorMax( const Vector &a, const Vector &b, Vector &result );
  425. // Linearly interpolate between two vectors
  426. void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest );
  427. Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t );
  428. FORCEINLINE Vector ReplicateToVector( float x )
  429. {
  430. return Vector( x, x, x );
  431. }
  432. FORCEINLINE bool PointWithinViewAngle( Vector const &vecSrcPosition,
  433. Vector const &vecTargetPosition,
  434. Vector const &vecLookDirection, float flCosHalfFOV )
  435. {
  436. Vector vecDelta = vecTargetPosition - vecSrcPosition;
  437. float cosDiff = DotProduct( vecLookDirection, vecDelta );
  438. if ( flCosHalfFOV <= 0 ) // >180
  439. {
  440. // signs are different, answer is implicit
  441. if ( cosDiff > 0 )
  442. return true;
  443. // a/sqrt(b) > c == a^2 < b * c ^2
  444. // IFF left and right sides are <= 0
  445. float flLen2 = vecDelta.LengthSqr();
  446. return ( cosDiff * cosDiff <= flLen2 * flCosHalfFOV * flCosHalfFOV );
  447. }
  448. else // flCosHalfFOV > 0
  449. {
  450. // signs are different, answer is implicit
  451. if ( cosDiff < 0 )
  452. return false;
  453. // a/sqrt(b) > c == a^2 > b * c ^2
  454. // IFF left and right sides are >= 0
  455. float flLen2 = vecDelta.LengthSqr();
  456. return ( cosDiff * cosDiff >= flLen2 * flCosHalfFOV * flCosHalfFOV );
  457. }
  458. }
  459. #ifndef VECTOR_NO_SLOW_OPERATIONS
  460. // Cross product
  461. Vector CrossProduct( const Vector& a, const Vector& b );
  462. // Random vector creation
  463. Vector RandomVector( vec_t minVal, vec_t maxVal );
  464. #endif
  465. float RandomVectorInUnitSphere( Vector *pVector );
  466. float RandomVectorInUnitCircle( Vector2D *pVector );
  467. //-----------------------------------------------------------------------------
  468. //
  469. // Inlined Vector methods
  470. //
  471. //-----------------------------------------------------------------------------
  472. //-----------------------------------------------------------------------------
  473. // constructors
  474. //-----------------------------------------------------------------------------
  475. inline Vector::Vector(void)
  476. {
  477. #ifdef _DEBUG
  478. #ifdef VECTOR_PARANOIA
  479. // Initialize to NAN to catch errors
  480. x = y = z = VEC_T_NAN;
  481. #endif
  482. #endif
  483. }
  484. inline Vector::Vector(vec_t X, vec_t Y, vec_t Z)
  485. {
  486. x = X; y = Y; z = Z;
  487. CHECK_VALID(*this);
  488. }
  489. //inline Vector::Vector(const float *pFloat)
  490. //{
  491. // Assert( pFloat );
  492. // x = pFloat[0]; y = pFloat[1]; z = pFloat[2];
  493. // CHECK_VALID(*this);
  494. //}
  495. #if 0
  496. //-----------------------------------------------------------------------------
  497. // copy constructor
  498. //-----------------------------------------------------------------------------
  499. inline Vector::Vector(const Vector &vOther)
  500. {
  501. CHECK_VALID(vOther);
  502. x = vOther.x; y = vOther.y; z = vOther.z;
  503. }
  504. #endif
  505. //-----------------------------------------------------------------------------
  506. // initialization
  507. //-----------------------------------------------------------------------------
  508. inline void Vector::Init( vec_t ix, vec_t iy, vec_t iz )
  509. {
  510. x = ix; y = iy; z = iz;
  511. CHECK_VALID(*this);
  512. }
  513. inline void Vector::Random( vec_t minVal, vec_t maxVal )
  514. {
  515. x = RandomFloat( minVal, maxVal );
  516. y = RandomFloat( minVal, maxVal );
  517. z = RandomFloat( minVal, maxVal );
  518. CHECK_VALID(*this);
  519. }
  520. // This should really be a single opcode on the PowerPC (move r0 onto the vec reg)
  521. inline void Vector::Zero()
  522. {
  523. x = y = z = 0.0f;
  524. }
  525. inline void VectorClear( Vector& a )
  526. {
  527. a.x = a.y = a.z = 0.0f;
  528. }
  529. //-----------------------------------------------------------------------------
  530. // assignment
  531. //-----------------------------------------------------------------------------
  532. inline Vector& Vector::operator=(const Vector &vOther)
  533. {
  534. CHECK_VALID(vOther);
  535. x=vOther.x; y=vOther.y; z=vOther.z;
  536. return *this;
  537. }
  538. //-----------------------------------------------------------------------------
  539. // Array access
  540. //-----------------------------------------------------------------------------
  541. inline vec_t& Vector::operator[](int i)
  542. {
  543. Assert( (i >= 0) && (i < 3) );
  544. return ((vec_t*)this)[i];
  545. }
  546. inline vec_t Vector::operator[](int i) const
  547. {
  548. Assert( (i >= 0) && (i < 3) );
  549. return ((vec_t*)this)[i];
  550. }
  551. //-----------------------------------------------------------------------------
  552. // Base address...
  553. //-----------------------------------------------------------------------------
  554. inline vec_t* Vector::Base()
  555. {
  556. return (vec_t*)this;
  557. }
  558. inline vec_t const* Vector::Base() const
  559. {
  560. return (vec_t const*)this;
  561. }
  562. //-----------------------------------------------------------------------------
  563. // Cast to Vector2D...
  564. //-----------------------------------------------------------------------------
  565. inline Vector2D& Vector::AsVector2D()
  566. {
  567. return *(Vector2D*)this;
  568. }
  569. inline const Vector2D& Vector::AsVector2D() const
  570. {
  571. return *(const Vector2D*)this;
  572. }
  573. //-----------------------------------------------------------------------------
  574. // IsValid?
  575. //-----------------------------------------------------------------------------
  576. inline bool Vector::IsValid() const
  577. {
  578. return IsFinite(x) && IsFinite(y) && IsFinite(z);
  579. }
  580. //-----------------------------------------------------------------------------
  581. // Invalidate
  582. //-----------------------------------------------------------------------------
  583. inline void Vector::Invalidate()
  584. {
  585. //#ifdef _DEBUG
  586. //#ifdef VECTOR_PARANOIA
  587. x = y = z = VEC_T_NAN;
  588. //#endif
  589. //#endif
  590. }
  591. //-----------------------------------------------------------------------------
  592. // comparison
  593. //-----------------------------------------------------------------------------
  594. inline bool Vector::operator==( const Vector& src ) const
  595. {
  596. CHECK_VALID(src);
  597. CHECK_VALID(*this);
  598. return (src.x == x) && (src.y == y) && (src.z == z);
  599. }
  600. inline bool Vector::operator!=( const Vector& src ) const
  601. {
  602. CHECK_VALID(src);
  603. CHECK_VALID(*this);
  604. return (src.x != x) || (src.y != y) || (src.z != z);
  605. }
  606. //-----------------------------------------------------------------------------
  607. // Copy
  608. //-----------------------------------------------------------------------------
  609. FORCEINLINE void VectorCopy( const Vector& src, Vector& dst )
  610. {
  611. CHECK_VALID(src);
  612. dst.x = src.x;
  613. dst.y = src.y;
  614. dst.z = src.z;
  615. }
  616. inline void Vector::CopyToArray(float* rgfl) const
  617. {
  618. Assert( rgfl );
  619. CHECK_VALID(*this);
  620. rgfl[0] = x, rgfl[1] = y, rgfl[2] = z;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // standard math operations
  624. //-----------------------------------------------------------------------------
  625. // #pragma message("TODO: these should be SSE")
  626. inline void Vector::Negate()
  627. {
  628. CHECK_VALID(*this);
  629. x = -x; y = -y; z = -z;
  630. }
  631. FORCEINLINE Vector& Vector::operator+=(const Vector& v)
  632. {
  633. CHECK_VALID(*this);
  634. CHECK_VALID(v);
  635. x+=v.x; y+=v.y; z += v.z;
  636. return *this;
  637. }
  638. FORCEINLINE Vector& Vector::operator-=(const Vector& v)
  639. {
  640. CHECK_VALID(*this);
  641. CHECK_VALID(v);
  642. x-=v.x; y-=v.y; z -= v.z;
  643. return *this;
  644. }
  645. FORCEINLINE Vector& Vector::operator*=(float fl)
  646. {
  647. x *= fl;
  648. y *= fl;
  649. z *= fl;
  650. CHECK_VALID(*this);
  651. return *this;
  652. }
  653. FORCEINLINE Vector& Vector::operator*=(const Vector& v)
  654. {
  655. CHECK_VALID(v);
  656. x *= v.x;
  657. y *= v.y;
  658. z *= v.z;
  659. CHECK_VALID(*this);
  660. return *this;
  661. }
  662. // this ought to be an opcode.
  663. FORCEINLINE Vector& Vector::operator+=(float fl)
  664. {
  665. x += fl;
  666. y += fl;
  667. z += fl;
  668. CHECK_VALID(*this);
  669. return *this;
  670. }
  671. FORCEINLINE Vector& Vector::operator-=(float fl)
  672. {
  673. x -= fl;
  674. y -= fl;
  675. z -= fl;
  676. CHECK_VALID(*this);
  677. return *this;
  678. }
  679. FORCEINLINE Vector& Vector::operator/=(float fl)
  680. {
  681. Assert( fl != 0.0f );
  682. float oofl = 1.0f / fl;
  683. x *= oofl;
  684. y *= oofl;
  685. z *= oofl;
  686. CHECK_VALID(*this);
  687. return *this;
  688. }
  689. FORCEINLINE Vector& Vector::operator/=(const Vector& v)
  690. {
  691. CHECK_VALID(v);
  692. Assert( v.x != 0.0f && v.y != 0.0f && v.z != 0.0f );
  693. x /= v.x;
  694. y /= v.y;
  695. z /= v.z;
  696. CHECK_VALID(*this);
  697. return *this;
  698. }
  699. // get the component of this vector parallel to some other given vector
  700. inline Vector Vector::ProjectOnto( const Vector& onto )
  701. {
  702. return onto * ( this->Dot(onto) / ( onto.LengthSqr() ) );
  703. }
  704. //-----------------------------------------------------------------------------
  705. //
  706. // Inlined Short Vector methods
  707. //
  708. //-----------------------------------------------------------------------------
  709. inline void ShortVector::Init( short ix, short iy, short iz, short iw )
  710. {
  711. x = ix; y = iy; z = iz; w = iw;
  712. }
  713. FORCEINLINE void ShortVector::Set( const ShortVector& vOther )
  714. {
  715. x = vOther.x;
  716. y = vOther.y;
  717. z = vOther.z;
  718. w = vOther.w;
  719. }
  720. FORCEINLINE void ShortVector::Set( const short ix, const short iy, const short iz, const short iw )
  721. {
  722. x = ix;
  723. y = iy;
  724. z = iz;
  725. w = iw;
  726. }
  727. //-----------------------------------------------------------------------------
  728. // Array access
  729. //-----------------------------------------------------------------------------
  730. inline short ShortVector::operator[](int i) const
  731. {
  732. Assert( (i >= 0) && (i < 4) );
  733. return ((short*)this)[i];
  734. }
  735. inline short& ShortVector::operator[](int i)
  736. {
  737. Assert( (i >= 0) && (i < 4) );
  738. return ((short*)this)[i];
  739. }
  740. //-----------------------------------------------------------------------------
  741. // Base address...
  742. //-----------------------------------------------------------------------------
  743. inline short* ShortVector::Base()
  744. {
  745. return (short*)this;
  746. }
  747. inline short const* ShortVector::Base() const
  748. {
  749. return (short const*)this;
  750. }
  751. //-----------------------------------------------------------------------------
  752. // comparison
  753. //-----------------------------------------------------------------------------
  754. inline bool ShortVector::operator==( const ShortVector& src ) const
  755. {
  756. return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w);
  757. }
  758. inline bool ShortVector::operator!=( const ShortVector& src ) const
  759. {
  760. return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w);
  761. }
  762. //-----------------------------------------------------------------------------
  763. // standard math operations
  764. //-----------------------------------------------------------------------------
  765. FORCEINLINE ShortVector& ShortVector::operator+=(const ShortVector& v)
  766. {
  767. x+=v.x; y+=v.y; z += v.z; w += v.w;
  768. return *this;
  769. }
  770. FORCEINLINE ShortVector& ShortVector::operator-=(const ShortVector& v)
  771. {
  772. x-=v.x; y-=v.y; z -= v.z; w -= v.w;
  773. return *this;
  774. }
  775. FORCEINLINE ShortVector& ShortVector::operator*=(float fl)
  776. {
  777. x = (short)(x * fl);
  778. y = (short)(y * fl);
  779. z = (short)(z * fl);
  780. w = (short)(w * fl);
  781. return *this;
  782. }
  783. FORCEINLINE ShortVector& ShortVector::operator*=(const ShortVector& v)
  784. {
  785. x = (short)(x * v.x);
  786. y = (short)(y * v.y);
  787. z = (short)(z * v.z);
  788. w = (short)(w * v.w);
  789. return *this;
  790. }
  791. FORCEINLINE ShortVector& ShortVector::operator/=(float fl)
  792. {
  793. Assert( fl != 0.0f );
  794. float oofl = 1.0f / fl;
  795. x = (short)(x * oofl);
  796. y = (short)(y * oofl);
  797. z = (short)(z * oofl);
  798. w = (short)(w * oofl);
  799. return *this;
  800. }
  801. FORCEINLINE ShortVector& ShortVector::operator/=(const ShortVector& v)
  802. {
  803. Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 );
  804. x = (short)(x / v.x);
  805. y = (short)(y / v.y);
  806. z = (short)(z / v.z);
  807. w = (short)(w / v.w);
  808. return *this;
  809. }
  810. FORCEINLINE void ShortVectorMultiply( const ShortVector& src, float fl, ShortVector& res )
  811. {
  812. Assert( IsFinite(fl) );
  813. res.x = (short)(src.x * fl);
  814. res.y = (short)(src.y * fl);
  815. res.z = (short)(src.z * fl);
  816. res.w = (short)(src.w * fl);
  817. }
  818. FORCEINLINE ShortVector ShortVector::operator*(float fl) const
  819. {
  820. ShortVector res;
  821. ShortVectorMultiply( *this, fl, res );
  822. return res;
  823. }
  824. //-----------------------------------------------------------------------------
  825. //
  826. // Inlined Integer Vector methods
  827. //
  828. //-----------------------------------------------------------------------------
  829. inline void IntVector4D::Init( int ix, int iy, int iz, int iw )
  830. {
  831. x = ix; y = iy; z = iz; w = iw;
  832. }
  833. FORCEINLINE void IntVector4D::Set( const IntVector4D& vOther )
  834. {
  835. x = vOther.x;
  836. y = vOther.y;
  837. z = vOther.z;
  838. w = vOther.w;
  839. }
  840. FORCEINLINE void IntVector4D::Set( const int ix, const int iy, const int iz, const int iw )
  841. {
  842. x = ix;
  843. y = iy;
  844. z = iz;
  845. w = iw;
  846. }
  847. //-----------------------------------------------------------------------------
  848. // Array access
  849. //-----------------------------------------------------------------------------
  850. inline int IntVector4D::operator[](int i) const
  851. {
  852. Assert( (i >= 0) && (i < 4) );
  853. return ((int*)this)[i];
  854. }
  855. inline int& IntVector4D::operator[](int i)
  856. {
  857. Assert( (i >= 0) && (i < 4) );
  858. return ((int*)this)[i];
  859. }
  860. //-----------------------------------------------------------------------------
  861. // Base address...
  862. //-----------------------------------------------------------------------------
  863. inline int* IntVector4D::Base()
  864. {
  865. return (int*)this;
  866. }
  867. inline int const* IntVector4D::Base() const
  868. {
  869. return (int const*)this;
  870. }
  871. //-----------------------------------------------------------------------------
  872. // comparison
  873. //-----------------------------------------------------------------------------
  874. inline bool IntVector4D::operator==( const IntVector4D& src ) const
  875. {
  876. return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w);
  877. }
  878. inline bool IntVector4D::operator!=( const IntVector4D& src ) const
  879. {
  880. return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w);
  881. }
  882. //-----------------------------------------------------------------------------
  883. // standard math operations
  884. //-----------------------------------------------------------------------------
  885. FORCEINLINE IntVector4D& IntVector4D::operator+=(const IntVector4D& v)
  886. {
  887. x+=v.x; y+=v.y; z += v.z; w += v.w;
  888. return *this;
  889. }
  890. FORCEINLINE IntVector4D& IntVector4D::operator-=(const IntVector4D& v)
  891. {
  892. x-=v.x; y-=v.y; z -= v.z; w -= v.w;
  893. return *this;
  894. }
  895. FORCEINLINE IntVector4D& IntVector4D::operator*=(float fl)
  896. {
  897. x = (int)(x * fl);
  898. y = (int)(y * fl);
  899. z = (int)(z * fl);
  900. w = (int)(w * fl);
  901. return *this;
  902. }
  903. FORCEINLINE IntVector4D& IntVector4D::operator*=(const IntVector4D& v)
  904. {
  905. x = (int)(x * v.x);
  906. y = (int)(y * v.y);
  907. z = (int)(z * v.z);
  908. w = (int)(w * v.w);
  909. return *this;
  910. }
  911. FORCEINLINE IntVector4D& IntVector4D::operator/=(float fl)
  912. {
  913. Assert( fl != 0.0f );
  914. float oofl = 1.0f / fl;
  915. x = (int)(x * oofl);
  916. y = (int)(y * oofl);
  917. z = (int)(z * oofl);
  918. w = (int)(w * oofl);
  919. return *this;
  920. }
  921. FORCEINLINE IntVector4D& IntVector4D::operator/=(const IntVector4D& v)
  922. {
  923. Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 );
  924. x = (int)(x / v.x);
  925. y = (int)(y / v.y);
  926. z = (int)(z / v.z);
  927. w = (int)(w / v.w);
  928. return *this;
  929. }
  930. FORCEINLINE void IntVector4DMultiply( const IntVector4D& src, float fl, IntVector4D& res )
  931. {
  932. Assert( IsFinite(fl) );
  933. res.x = (int)(src.x * fl);
  934. res.y = (int)(src.y * fl);
  935. res.z = (int)(src.z * fl);
  936. res.w = (int)(src.w * fl);
  937. }
  938. FORCEINLINE IntVector4D IntVector4D::operator*(float fl) const
  939. {
  940. IntVector4D res;
  941. IntVector4DMultiply( *this, fl, res );
  942. return res;
  943. }
  944. // =======================
  945. FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& c )
  946. {
  947. CHECK_VALID(a);
  948. CHECK_VALID(b);
  949. c.x = a.x + b.x;
  950. c.y = a.y + b.y;
  951. c.z = a.z + b.z;
  952. }
  953. FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& c )
  954. {
  955. CHECK_VALID(a);
  956. CHECK_VALID(b);
  957. c.x = a.x - b.x;
  958. c.y = a.y - b.y;
  959. c.z = a.z - b.z;
  960. }
  961. FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& c )
  962. {
  963. CHECK_VALID(a);
  964. Assert( IsFinite(b) );
  965. c.x = a.x * b;
  966. c.y = a.y * b;
  967. c.z = a.z * b;
  968. }
  969. FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& c )
  970. {
  971. CHECK_VALID(a);
  972. CHECK_VALID(b);
  973. c.x = a.x * b.x;
  974. c.y = a.y * b.y;
  975. c.z = a.z * b.z;
  976. }
  977. // for backwards compatability
  978. inline void VectorScale ( const Vector& in, vec_t scale, Vector& result )
  979. {
  980. VectorMultiply( in, scale, result );
  981. }
  982. FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& c )
  983. {
  984. CHECK_VALID(a);
  985. Assert( b != 0.0f );
  986. vec_t oob = 1.0f / b;
  987. c.x = a.x * oob;
  988. c.y = a.y * oob;
  989. c.z = a.z * oob;
  990. }
  991. FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& c )
  992. {
  993. CHECK_VALID(a);
  994. CHECK_VALID(b);
  995. Assert( (b.x != 0.0f) && (b.y != 0.0f) && (b.z != 0.0f) );
  996. c.x = a.x / b.x;
  997. c.y = a.y / b.y;
  998. c.z = a.z / b.z;
  999. }
  1000. // FIXME: Remove
  1001. // For backwards compatability
  1002. inline void Vector::MulAdd(const Vector& a, const Vector& b, float scalar)
  1003. {
  1004. CHECK_VALID(a);
  1005. CHECK_VALID(b);
  1006. x = a.x + b.x * scalar;
  1007. y = a.y + b.y * scalar;
  1008. z = a.z + b.z * scalar;
  1009. }
  1010. inline void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest )
  1011. {
  1012. CHECK_VALID(src1);
  1013. CHECK_VALID(src2);
  1014. dest.x = src1.x + (src2.x - src1.x) * t;
  1015. dest.y = src1.y + (src2.y - src1.y) * t;
  1016. dest.z = src1.z + (src2.z - src1.z) * t;
  1017. }
  1018. inline Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t )
  1019. {
  1020. Vector result;
  1021. VectorLerp( src1, src2, t, result );
  1022. return result;
  1023. }
  1024. //-----------------------------------------------------------------------------
  1025. // Temporary storage for vector results so const Vector& results can be returned
  1026. //-----------------------------------------------------------------------------
  1027. inline Vector &AllocTempVector()
  1028. {
  1029. static Vector s_vecTemp[128];
  1030. static CInterlockedInt s_nIndex;
  1031. int nIndex;
  1032. for (;;)
  1033. {
  1034. int nOldIndex = s_nIndex;
  1035. nIndex = ( (nOldIndex + 0x10001) & 0x7F );
  1036. if ( s_nIndex.AssignIf( nOldIndex, nIndex ) )
  1037. {
  1038. break;
  1039. }
  1040. ThreadPause();
  1041. }
  1042. return s_vecTemp[nIndex & 0xffff];
  1043. }
  1044. //-----------------------------------------------------------------------------
  1045. // dot, cross
  1046. //-----------------------------------------------------------------------------
  1047. FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b)
  1048. {
  1049. CHECK_VALID(a);
  1050. CHECK_VALID(b);
  1051. return( a.x*b.x + a.y*b.y + a.z*b.z );
  1052. }
  1053. // for backwards compatability
  1054. inline vec_t Vector::Dot( const Vector& vOther ) const
  1055. {
  1056. CHECK_VALID(vOther);
  1057. return DotProduct( *this, vOther );
  1058. }
  1059. inline int Vector::LargestComponent() const
  1060. {
  1061. float flAbsx = fabs(x);
  1062. float flAbsy = fabs(y);
  1063. float flAbsz = fabs(z);
  1064. if ( flAbsx > flAbsy )
  1065. {
  1066. if ( flAbsx > flAbsz )
  1067. return X_INDEX;
  1068. return Z_INDEX;
  1069. }
  1070. if ( flAbsy > flAbsz )
  1071. return Y_INDEX;
  1072. return Z_INDEX;
  1073. }
  1074. inline void CrossProduct(const Vector& a, const Vector& b, Vector& result )
  1075. {
  1076. CHECK_VALID(a);
  1077. CHECK_VALID(b);
  1078. Assert( &a != &result );
  1079. Assert( &b != &result );
  1080. result.x = a.y*b.z - a.z*b.y;
  1081. result.y = a.z*b.x - a.x*b.z;
  1082. result.z = a.x*b.y - a.y*b.x;
  1083. }
  1084. inline vec_t DotProductAbs( const Vector &v0, const Vector &v1 )
  1085. {
  1086. CHECK_VALID(v0);
  1087. CHECK_VALID(v1);
  1088. return FloatMakePositive(v0.x*v1.x) + FloatMakePositive(v0.y*v1.y) + FloatMakePositive(v0.z*v1.z);
  1089. }
  1090. inline vec_t DotProductAbs( const Vector &v0, const float *v1 )
  1091. {
  1092. return FloatMakePositive(v0.x * v1[0]) + FloatMakePositive(v0.y * v1[1]) + FloatMakePositive(v0.z * v1[2]);
  1093. }
  1094. //-----------------------------------------------------------------------------
  1095. // length
  1096. //-----------------------------------------------------------------------------
  1097. inline vec_t VectorLength( const Vector& v )
  1098. {
  1099. CHECK_VALID(v);
  1100. return (vec_t)FastSqrt(v.x*v.x + v.y*v.y + v.z*v.z);
  1101. }
  1102. inline vec_t Vector::Length(void) const
  1103. {
  1104. CHECK_VALID(*this);
  1105. return VectorLength( *this );
  1106. }
  1107. //-----------------------------------------------------------------------------
  1108. // Normalization
  1109. //-----------------------------------------------------------------------------
  1110. /*
  1111. // FIXME: Can't use until we're un-macroed in mathlib.h
  1112. inline vec_t VectorNormalize( Vector& v )
  1113. {
  1114. Assert( v.IsValid() );
  1115. vec_t l = v.Length();
  1116. if (l != 0.0f)
  1117. {
  1118. v /= l;
  1119. }
  1120. else
  1121. {
  1122. // FIXME:
  1123. // Just copying the existing implemenation; shouldn't res.z == 0?
  1124. v.x = v.y = 0.0f; v.z = 1.0f;
  1125. }
  1126. return l;
  1127. }
  1128. */
  1129. // check a point against a box
  1130. bool Vector::WithinAABox( Vector const &boxmin, Vector const &boxmax)
  1131. {
  1132. return (
  1133. ( x >= boxmin.x ) && ( x <= boxmax.x) &&
  1134. ( y >= boxmin.y ) && ( y <= boxmax.y) &&
  1135. ( z >= boxmin.z ) && ( z <= boxmax.z)
  1136. );
  1137. }
  1138. //-----------------------------------------------------------------------------
  1139. // Get the distance from this vector to the other one
  1140. //-----------------------------------------------------------------------------
  1141. inline vec_t Vector::DistTo(const Vector &vOther) const
  1142. {
  1143. Vector delta;
  1144. VectorSubtract( *this, vOther, delta );
  1145. return delta.Length();
  1146. }
  1147. //-----------------------------------------------------------------------------
  1148. // Vector equality with tolerance
  1149. //-----------------------------------------------------------------------------
  1150. inline bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance )
  1151. {
  1152. if (FloatMakePositive(src1.x - src2.x) > tolerance)
  1153. return false;
  1154. if (FloatMakePositive(src1.y - src2.y) > tolerance)
  1155. return false;
  1156. return (FloatMakePositive(src1.z - src2.z) <= tolerance);
  1157. }
  1158. //-----------------------------------------------------------------------------
  1159. // Computes the closest point to vecTarget no farther than flMaxDist from vecStart
  1160. //-----------------------------------------------------------------------------
  1161. inline void ComputeClosestPoint( const Vector& vecStart, float flMaxDist, const Vector& vecTarget, Vector *pResult )
  1162. {
  1163. Vector vecDelta;
  1164. VectorSubtract( vecTarget, vecStart, vecDelta );
  1165. float flDistSqr = vecDelta.LengthSqr();
  1166. if ( flDistSqr <= flMaxDist * flMaxDist )
  1167. {
  1168. *pResult = vecTarget;
  1169. }
  1170. else
  1171. {
  1172. vecDelta /= FastSqrt( flDistSqr );
  1173. VectorMA( vecStart, flMaxDist, vecDelta, *pResult );
  1174. }
  1175. }
  1176. //-----------------------------------------------------------------------------
  1177. // Takes the absolute value of a vector
  1178. //-----------------------------------------------------------------------------
  1179. inline void VectorAbs( const Vector& src, Vector& dst )
  1180. {
  1181. dst.x = FloatMakePositive(src.x);
  1182. dst.y = FloatMakePositive(src.y);
  1183. dst.z = FloatMakePositive(src.z);
  1184. }
  1185. //-----------------------------------------------------------------------------
  1186. //
  1187. // Slow methods
  1188. //
  1189. //-----------------------------------------------------------------------------
  1190. #ifndef VECTOR_NO_SLOW_OPERATIONS
  1191. //-----------------------------------------------------------------------------
  1192. // Returns a vector with the min or max in X, Y, and Z.
  1193. //-----------------------------------------------------------------------------
  1194. inline Vector Vector::Min(const Vector &vOther) const
  1195. {
  1196. return Vector(x < vOther.x ? x : vOther.x,
  1197. y < vOther.y ? y : vOther.y,
  1198. z < vOther.z ? z : vOther.z);
  1199. }
  1200. inline Vector Vector::Max(const Vector &vOther) const
  1201. {
  1202. return Vector(x > vOther.x ? x : vOther.x,
  1203. y > vOther.y ? y : vOther.y,
  1204. z > vOther.z ? z : vOther.z);
  1205. }
  1206. //-----------------------------------------------------------------------------
  1207. // arithmetic operations
  1208. //-----------------------------------------------------------------------------
  1209. inline Vector Vector::operator-(void) const
  1210. {
  1211. return Vector(-x,-y,-z);
  1212. }
  1213. inline Vector Vector::operator+(const Vector& v) const
  1214. {
  1215. Vector res;
  1216. VectorAdd( *this, v, res );
  1217. return res;
  1218. }
  1219. inline Vector Vector::operator-(const Vector& v) const
  1220. {
  1221. Vector res;
  1222. VectorSubtract( *this, v, res );
  1223. return res;
  1224. }
  1225. inline Vector Vector::operator*(float fl) const
  1226. {
  1227. Vector res;
  1228. VectorMultiply( *this, fl, res );
  1229. return res;
  1230. }
  1231. inline Vector Vector::operator*(const Vector& v) const
  1232. {
  1233. Vector res;
  1234. VectorMultiply( *this, v, res );
  1235. return res;
  1236. }
  1237. inline Vector Vector::operator/(float fl) const
  1238. {
  1239. Vector res;
  1240. VectorDivide( *this, fl, res );
  1241. return res;
  1242. }
  1243. inline Vector Vector::operator/(const Vector& v) const
  1244. {
  1245. Vector res;
  1246. VectorDivide( *this, v, res );
  1247. return res;
  1248. }
  1249. inline Vector operator*(float fl, const Vector& v)
  1250. {
  1251. return v * fl;
  1252. }
  1253. //-----------------------------------------------------------------------------
  1254. // cross product
  1255. //-----------------------------------------------------------------------------
  1256. inline Vector Vector::Cross(const Vector& vOther) const
  1257. {
  1258. Vector res;
  1259. CrossProduct( *this, vOther, res );
  1260. return res;
  1261. }
  1262. //-----------------------------------------------------------------------------
  1263. // 2D
  1264. //-----------------------------------------------------------------------------
  1265. inline vec_t Vector::Length2D(void) const
  1266. {
  1267. return (vec_t)FastSqrt(x*x + y*y);
  1268. }
  1269. inline vec_t Vector::Length2DSqr(void) const
  1270. {
  1271. return (x*x + y*y);
  1272. }
  1273. inline Vector CrossProduct(const Vector& a, const Vector& b)
  1274. {
  1275. return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x );
  1276. }
  1277. inline void VectorMin( const Vector &a, const Vector &b, Vector &result )
  1278. {
  1279. result.x = fpmin(a.x, b.x);
  1280. result.y = fpmin(a.y, b.y);
  1281. result.z = fpmin(a.z, b.z);
  1282. }
  1283. inline void VectorMax( const Vector &a, const Vector &b, Vector &result )
  1284. {
  1285. result.x = fpmax(a.x, b.x);
  1286. result.y = fpmax(a.y, b.y);
  1287. result.z = fpmax(a.z, b.z);
  1288. }
  1289. // and when you want to return the vector rather than cause a LHS with it...
  1290. inline Vector VectorMin( const Vector &a, const Vector &b )
  1291. {
  1292. return Vector( fpmin(a.x, b.x), fpmin(a.y, b.y), fpmin(a.z, b.z) );
  1293. }
  1294. inline Vector VectorMax( const Vector &a, const Vector &b )
  1295. {
  1296. return Vector( fpmax(a.x, b.x), fpmax(a.y, b.y), fpmax(a.z, b.z) );
  1297. }
  1298. inline float ComputeVolume( const Vector &vecMins, const Vector &vecMaxs )
  1299. {
  1300. Vector vecDelta;
  1301. VectorSubtract( vecMaxs, vecMins, vecDelta );
  1302. return DotProduct( vecDelta, vecDelta );
  1303. }
  1304. // Get a random vector.
  1305. inline Vector RandomVector( float minVal, float maxVal )
  1306. {
  1307. Vector random;
  1308. random.Random( minVal, maxVal );
  1309. return random;
  1310. }
  1311. #endif //slow
  1312. //-----------------------------------------------------------------------------
  1313. // Helper debugging stuff....
  1314. //-----------------------------------------------------------------------------
  1315. inline bool operator==( float const* f, const Vector& v )
  1316. {
  1317. // AIIIEEEE!!!!
  1318. Assert(0);
  1319. return false;
  1320. }
  1321. inline bool operator==( const Vector& v, float const* f )
  1322. {
  1323. // AIIIEEEE!!!!
  1324. Assert(0);
  1325. return false;
  1326. }
  1327. inline bool operator!=( float const* f, const Vector& v )
  1328. {
  1329. // AIIIEEEE!!!!
  1330. Assert(0);
  1331. return false;
  1332. }
  1333. inline bool operator!=( const Vector& v, float const* f )
  1334. {
  1335. // AIIIEEEE!!!!
  1336. Assert(0);
  1337. return false;
  1338. }
  1339. // return a vector perpendicular to another, with smooth variation. The difference between this and
  1340. // something like VectorVectors is that there are now discontinuities. _unlike_ VectorVectors,
  1341. // you won't get an "u
  1342. void VectorPerpendicularToVector( Vector const &in, Vector *pvecOut );
  1343. //-----------------------------------------------------------------------------
  1344. // AngularImpulse
  1345. //-----------------------------------------------------------------------------
  1346. // AngularImpulse are exponetial maps (an axis scaled by a "twist" angle in degrees)
  1347. typedef Vector AngularImpulse;
  1348. #ifndef VECTOR_NO_SLOW_OPERATIONS
  1349. inline AngularImpulse RandomAngularImpulse( float minVal, float maxVal )
  1350. {
  1351. AngularImpulse angImp;
  1352. angImp.Random( minVal, maxVal );
  1353. return angImp;
  1354. }
  1355. #endif
  1356. //-----------------------------------------------------------------------------
  1357. // Quaternion
  1358. //-----------------------------------------------------------------------------
  1359. class RadianEuler;
  1360. class Quaternion // same data-layout as engine's vec4_t,
  1361. { // which is a vec_t[4]
  1362. public:
  1363. inline Quaternion(void) {
  1364. // Initialize to NAN to catch errors
  1365. #ifdef _DEBUG
  1366. #ifdef VECTOR_PARANOIA
  1367. x = y = z = w = VEC_T_NAN;
  1368. #endif
  1369. #endif
  1370. }
  1371. inline Quaternion(vec_t ix, vec_t iy, vec_t iz, vec_t iw) : x(ix), y(iy), z(iz), w(iw) { }
  1372. inline Quaternion(RadianEuler const &angle); // evil auto type promotion!!!
  1373. inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f, vec_t iw=0.0f) { x = ix; y = iy; z = iz; w = iw; }
  1374. bool IsValid() const;
  1375. void Invalidate();
  1376. bool operator==( const Quaternion &src ) const;
  1377. bool operator!=( const Quaternion &src ) const;
  1378. inline Quaternion Conjugate() const { return Quaternion( -x, -y, -z, w ); }
  1379. vec_t* Base() { return (vec_t*)this; }
  1380. const vec_t* Base() const { return (vec_t*)this; }
  1381. // convenience for debugging
  1382. inline void Print() const;
  1383. // array access...
  1384. vec_t operator[](int i) const;
  1385. vec_t& operator[](int i);
  1386. vec_t x, y, z, w;
  1387. };
  1388. //-----------------------------------------------------------------------------
  1389. // Array access
  1390. //-----------------------------------------------------------------------------
  1391. inline vec_t& Quaternion::operator[](int i)
  1392. {
  1393. Assert( (i >= 0) && (i < 4) );
  1394. return ((vec_t*)this)[i];
  1395. }
  1396. inline vec_t Quaternion::operator[](int i) const
  1397. {
  1398. Assert( (i >= 0) && (i < 4) );
  1399. return ((vec_t*)this)[i];
  1400. }
  1401. //-----------------------------------------------------------------------------
  1402. // Equality test
  1403. //-----------------------------------------------------------------------------
  1404. inline bool Quaternion::operator==( const Quaternion &src ) const
  1405. {
  1406. return ( x == src.x ) && ( y == src.y ) && ( z == src.z ) && ( w == src.w );
  1407. }
  1408. inline bool Quaternion::operator!=( const Quaternion &src ) const
  1409. {
  1410. return !operator==( src );
  1411. }
  1412. //-----------------------------------------------------------------------------
  1413. // Debugging only
  1414. //-----------------------------------------------------------------------------
  1415. void Quaternion::Print() const
  1416. {
  1417. #ifndef _CERT
  1418. Msg("q{ %.3fi + %.3fj + %.3fk + %.3f }", x, y, z, w );
  1419. #endif
  1420. }
  1421. //-----------------------------------------------------------------------------
  1422. // Quaternion equality with tolerance
  1423. //-----------------------------------------------------------------------------
  1424. inline bool QuaternionsAreEqual( const Quaternion& src1, const Quaternion& src2, float tolerance )
  1425. {
  1426. if (FloatMakePositive(src1.x - src2.x) > tolerance)
  1427. return false;
  1428. if (FloatMakePositive(src1.y - src2.y) > tolerance)
  1429. return false;
  1430. if (FloatMakePositive(src1.z - src2.z) > tolerance)
  1431. return false;
  1432. return (FloatMakePositive(src1.w - src2.w) <= tolerance);
  1433. }
  1434. //-----------------------------------------------------------------------------
  1435. // Here's where we add all those lovely SSE optimized routines
  1436. //-----------------------------------------------------------------------------
  1437. class ALIGN16 QuaternionAligned : public Quaternion
  1438. {
  1439. public:
  1440. inline QuaternionAligned(void) {};
  1441. inline QuaternionAligned(vec_t X, vec_t Y, vec_t Z, vec_t W)
  1442. {
  1443. Init(X,Y,Z,W);
  1444. }
  1445. operator Quaternion * () { return this; }
  1446. operator const Quaternion * () { return this; }
  1447. #ifdef VECTOR_NO_SLOW_OPERATIONS
  1448. private:
  1449. // No copy constructors allowed if we're in optimal mode
  1450. QuaternionAligned(const QuaternionAligned& vOther);
  1451. QuaternionAligned(const Quaternion &vOther);
  1452. #else
  1453. public:
  1454. explicit QuaternionAligned(const Quaternion &vOther)
  1455. {
  1456. Init(vOther.x, vOther.y, vOther.z, vOther.w);
  1457. }
  1458. QuaternionAligned& operator=(const Quaternion &vOther)
  1459. {
  1460. Init(vOther.x, vOther.y, vOther.z, vOther.w);
  1461. return *this;
  1462. }
  1463. QuaternionAligned& operator=(const QuaternionAligned &vOther)
  1464. {
  1465. // we know we're aligned, so use simd
  1466. // we can't use the convenient abstract interface coz it gets declared later
  1467. #ifdef _X360
  1468. XMStoreVector4A(Base(), XMLoadVector4A(vOther.Base()));
  1469. #elif _WIN32
  1470. _mm_store_ps(Base(), _mm_load_ps( vOther.Base() ));
  1471. #else
  1472. Init(vOther.x, vOther.y, vOther.z, vOther.w);
  1473. #endif
  1474. return *this;
  1475. }
  1476. #endif
  1477. #if !defined(NO_MALLOC_OVERRIDE)
  1478. void* operator new[] ( size_t nSize)
  1479. {
  1480. return MemAlloc_AllocAligned(nSize, 16);
  1481. }
  1482. void* operator new[] ( size_t nSize, const char *pFileName, int nLine)
  1483. {
  1484. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  1485. }
  1486. void* operator new[] ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine)
  1487. {
  1488. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  1489. }
  1490. void operator delete[] ( void* p)
  1491. {
  1492. MemAlloc_FreeAligned(p);
  1493. }
  1494. void operator delete[] ( void* p, const char *pFileName, int nLine)
  1495. {
  1496. MemAlloc_FreeAligned(p, pFileName, nLine);
  1497. }
  1498. void operator delete[] ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
  1499. {
  1500. MemAlloc_FreeAligned(p, pFileName, nLine);
  1501. }
  1502. // please don't allocate a single quaternion...
  1503. void* operator new ( size_t nSize )
  1504. {
  1505. return MemAlloc_AllocAligned(nSize, 16);
  1506. }
  1507. void* operator new ( size_t nSize, const char *pFileName, int nLine )
  1508. {
  1509. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  1510. }
  1511. void* operator new ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine )
  1512. {
  1513. return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
  1514. }
  1515. void operator delete ( void* p)
  1516. {
  1517. MemAlloc_FreeAligned(p);
  1518. }
  1519. void operator delete ( void* p, const char *pFileName, int nLine)
  1520. {
  1521. MemAlloc_FreeAligned(p, pFileName, nLine);
  1522. }
  1523. void operator delete ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
  1524. {
  1525. MemAlloc_FreeAligned(p, pFileName, nLine);
  1526. }
  1527. #endif
  1528. } ALIGN16_POST;
  1529. //-----------------------------------------------------------------------------
  1530. // Radian Euler angle aligned to axis (NOT ROLL/PITCH/YAW)
  1531. //-----------------------------------------------------------------------------
  1532. class QAngle;
  1533. class RadianEuler
  1534. {
  1535. public:
  1536. inline RadianEuler(void) { }
  1537. inline RadianEuler(vec_t X, vec_t Y, vec_t Z) { x = X; y = Y; z = Z; }
  1538. inline RadianEuler(Quaternion const &q); // evil auto type promotion!!!
  1539. inline RadianEuler(QAngle const &angles); // evil auto type promotion!!!
  1540. // Initialization
  1541. inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f) { x = ix; y = iy; z = iz; }
  1542. // conversion to qangle
  1543. QAngle ToQAngle( void ) const;
  1544. bool IsValid() const;
  1545. void Invalidate();
  1546. inline vec_t *Base() { return &x; }
  1547. inline const vec_t *Base() const { return &x; }
  1548. // array access...
  1549. vec_t operator[](int i) const;
  1550. vec_t& operator[](int i);
  1551. vec_t x, y, z;
  1552. };
  1553. extern void AngleQuaternion( RadianEuler const &angles, Quaternion &qt );
  1554. extern void QuaternionAngles( Quaternion const &q, RadianEuler &angles );
  1555. inline Quaternion::Quaternion(RadianEuler const &angle)
  1556. {
  1557. AngleQuaternion( angle, *this );
  1558. }
  1559. inline bool Quaternion::IsValid() const
  1560. {
  1561. return IsFinite(x) && IsFinite(y) && IsFinite(z) && IsFinite(w);
  1562. }
  1563. inline void Quaternion::Invalidate()
  1564. {
  1565. //#ifdef _DEBUG
  1566. //#ifdef VECTOR_PARANOIA
  1567. x = y = z = w = VEC_T_NAN;
  1568. //#endif
  1569. //#endif
  1570. }
  1571. inline RadianEuler::RadianEuler(Quaternion const &q)
  1572. {
  1573. QuaternionAngles( q, *this );
  1574. }
  1575. inline void VectorCopy( RadianEuler const& src, RadianEuler &dst )
  1576. {
  1577. CHECK_VALID(src);
  1578. dst.x = src.x;
  1579. dst.y = src.y;
  1580. dst.z = src.z;
  1581. }
  1582. inline void VectorScale( RadianEuler const& src, float b, RadianEuler &dst )
  1583. {
  1584. CHECK_VALID(src);
  1585. Assert( IsFinite(b) );
  1586. dst.x = src.x * b;
  1587. dst.y = src.y * b;
  1588. dst.z = src.z * b;
  1589. }
  1590. inline bool RadianEuler::IsValid() const
  1591. {
  1592. return IsFinite(x) && IsFinite(y) && IsFinite(z);
  1593. }
  1594. inline void RadianEuler::Invalidate()
  1595. {
  1596. //#ifdef _DEBUG
  1597. //#ifdef VECTOR_PARANOIA
  1598. x = y = z = VEC_T_NAN;
  1599. //#endif
  1600. //#endif
  1601. }
  1602. //-----------------------------------------------------------------------------
  1603. // Array access
  1604. //-----------------------------------------------------------------------------
  1605. inline vec_t& RadianEuler::operator[](int i)
  1606. {
  1607. Assert( (i >= 0) && (i < 3) );
  1608. return ((vec_t*)this)[i];
  1609. }
  1610. inline vec_t RadianEuler::operator[](int i) const
  1611. {
  1612. Assert( (i >= 0) && (i < 3) );
  1613. return ((vec_t*)this)[i];
  1614. }
  1615. //-----------------------------------------------------------------------------
  1616. // Degree Euler QAngle pitch, yaw, roll
  1617. //-----------------------------------------------------------------------------
  1618. class QAngleByValue;
  1619. class QAngle
  1620. {
  1621. public:
  1622. // Members
  1623. vec_t x, y, z;
  1624. // Construction/destruction
  1625. QAngle(void);
  1626. QAngle(vec_t X, vec_t Y, vec_t Z);
  1627. #ifndef _PS3
  1628. // QAngle(RadianEuler const &angles); // evil auto type promotion!!!
  1629. #endif
  1630. // Allow pass-by-value
  1631. operator QAngleByValue &() { return *((QAngleByValue *)(this)); }
  1632. operator const QAngleByValue &() const { return *((const QAngleByValue *)(this)); }
  1633. // Initialization
  1634. void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f);
  1635. void Random( vec_t minVal, vec_t maxVal );
  1636. // Got any nasty NAN's?
  1637. bool IsValid() const;
  1638. void Invalidate();
  1639. // array access...
  1640. vec_t operator[](int i) const;
  1641. vec_t& operator[](int i);
  1642. // Base address...
  1643. vec_t* Base();
  1644. vec_t const* Base() const;
  1645. // equality
  1646. bool operator==(const QAngle& v) const;
  1647. bool operator!=(const QAngle& v) const;
  1648. // arithmetic operations
  1649. QAngle& operator+=(const QAngle &v);
  1650. QAngle& operator-=(const QAngle &v);
  1651. QAngle& operator*=(float s);
  1652. QAngle& operator/=(float s);
  1653. // Get the vector's magnitude.
  1654. vec_t Length() const;
  1655. vec_t LengthSqr() const;
  1656. // negate the QAngle components
  1657. //void Negate();
  1658. // No assignment operators either...
  1659. QAngle& operator=( const QAngle& src );
  1660. #ifndef VECTOR_NO_SLOW_OPERATIONS
  1661. // copy constructors
  1662. // arithmetic operations
  1663. QAngle operator-(void) const;
  1664. QAngle operator+(const QAngle& v) const;
  1665. QAngle operator-(const QAngle& v) const;
  1666. QAngle operator*(float fl) const;
  1667. QAngle operator/(float fl) const;
  1668. #else
  1669. private:
  1670. // No copy constructors allowed if we're in optimal mode
  1671. QAngle(const QAngle& vOther);
  1672. #endif
  1673. };
  1674. //-----------------------------------------------------------------------------
  1675. // Allows us to specifically pass the vector by value when we need to
  1676. //-----------------------------------------------------------------------------
  1677. class QAngleByValue : public QAngle
  1678. {
  1679. public:
  1680. // Construction/destruction:
  1681. QAngleByValue(void) : QAngle() {}
  1682. QAngleByValue(vec_t X, vec_t Y, vec_t Z) : QAngle( X, Y, Z ) {}
  1683. QAngleByValue(const QAngleByValue& vOther) { *this = vOther; }
  1684. };
  1685. inline void VectorAdd( const QAngle& a, const QAngle& b, QAngle& result )
  1686. {
  1687. CHECK_VALID(a);
  1688. CHECK_VALID(b);
  1689. result.x = a.x + b.x;
  1690. result.y = a.y + b.y;
  1691. result.z = a.z + b.z;
  1692. }
  1693. inline void VectorMA( const QAngle &start, float scale, const QAngle &direction, QAngle &dest )
  1694. {
  1695. CHECK_VALID(start);
  1696. CHECK_VALID(direction);
  1697. dest.x = start.x + scale * direction.x;
  1698. dest.y = start.y + scale * direction.y;
  1699. dest.z = start.z + scale * direction.z;
  1700. }
  1701. //-----------------------------------------------------------------------------
  1702. // constructors
  1703. //-----------------------------------------------------------------------------
  1704. inline QAngle::QAngle(void)
  1705. {
  1706. #ifdef _DEBUG
  1707. #ifdef VECTOR_PARANOIA
  1708. // Initialize to NAN to catch errors
  1709. x = y = z = VEC_T_NAN;
  1710. #endif
  1711. #endif
  1712. }
  1713. inline QAngle::QAngle(vec_t X, vec_t Y, vec_t Z)
  1714. {
  1715. x = X; y = Y; z = Z;
  1716. CHECK_VALID(*this);
  1717. }
  1718. //-----------------------------------------------------------------------------
  1719. // initialization
  1720. //-----------------------------------------------------------------------------
  1721. inline void QAngle::Init( vec_t ix, vec_t iy, vec_t iz )
  1722. {
  1723. x = ix; y = iy; z = iz;
  1724. CHECK_VALID(*this);
  1725. }
  1726. inline void QAngle::Random( vec_t minVal, vec_t maxVal )
  1727. {
  1728. x = RandomFloat( minVal, maxVal );
  1729. y = RandomFloat( minVal, maxVal );
  1730. z = RandomFloat( minVal, maxVal );
  1731. CHECK_VALID(*this);
  1732. }
  1733. #ifndef VECTOR_NO_SLOW_OPERATIONS
  1734. inline QAngle RandomAngle( float minVal, float maxVal )
  1735. {
  1736. Vector random;
  1737. random.Random( minVal, maxVal );
  1738. QAngle ret( random.x, random.y, random.z );
  1739. return ret;
  1740. }
  1741. #endif
  1742. inline RadianEuler::RadianEuler(QAngle const &angles)
  1743. {
  1744. Init(
  1745. angles.z * 3.14159265358979323846f / 180.f,
  1746. angles.x * 3.14159265358979323846f / 180.f,
  1747. angles.y * 3.14159265358979323846f / 180.f );
  1748. }
  1749. inline QAngle RadianEuler::ToQAngle( void) const
  1750. {
  1751. return QAngle(
  1752. y * 180.f / 3.14159265358979323846f,
  1753. z * 180.f / 3.14159265358979323846f,
  1754. x * 180.f / 3.14159265358979323846f );
  1755. }
  1756. //-----------------------------------------------------------------------------
  1757. // assignment
  1758. //-----------------------------------------------------------------------------
  1759. inline QAngle& QAngle::operator=(const QAngle &vOther)
  1760. {
  1761. CHECK_VALID(vOther);
  1762. x=vOther.x; y=vOther.y; z=vOther.z;
  1763. return *this;
  1764. }
  1765. //-----------------------------------------------------------------------------
  1766. // Array access
  1767. //-----------------------------------------------------------------------------
  1768. inline vec_t& QAngle::operator[](int i)
  1769. {
  1770. Assert( (i >= 0) && (i < 3) );
  1771. return ((vec_t*)this)[i];
  1772. }
  1773. inline vec_t QAngle::operator[](int i) const
  1774. {
  1775. Assert( (i >= 0) && (i < 3) );
  1776. return ((vec_t*)this)[i];
  1777. }
  1778. //-----------------------------------------------------------------------------
  1779. // Base address...
  1780. //-----------------------------------------------------------------------------
  1781. inline vec_t* QAngle::Base()
  1782. {
  1783. return (vec_t*)this;
  1784. }
  1785. inline vec_t const* QAngle::Base() const
  1786. {
  1787. return (vec_t const*)this;
  1788. }
  1789. //-----------------------------------------------------------------------------
  1790. // IsValid?
  1791. //-----------------------------------------------------------------------------
  1792. inline bool QAngle::IsValid() const
  1793. {
  1794. return IsFinite(x) && IsFinite(y) && IsFinite(z);
  1795. }
  1796. //-----------------------------------------------------------------------------
  1797. // Invalidate
  1798. //-----------------------------------------------------------------------------
  1799. inline void QAngle::Invalidate()
  1800. {
  1801. //#ifdef _DEBUG
  1802. //#ifdef VECTOR_PARANOIA
  1803. x = y = z = VEC_T_NAN;
  1804. //#endif
  1805. //#endif
  1806. }
  1807. //-----------------------------------------------------------------------------
  1808. // comparison
  1809. //-----------------------------------------------------------------------------
  1810. inline bool QAngle::operator==( const QAngle& src ) const
  1811. {
  1812. CHECK_VALID(src);
  1813. CHECK_VALID(*this);
  1814. return (src.x == x) && (src.y == y) && (src.z == z);
  1815. }
  1816. inline bool QAngle::operator!=( const QAngle& src ) const
  1817. {
  1818. CHECK_VALID(src);
  1819. CHECK_VALID(*this);
  1820. return (src.x != x) || (src.y != y) || (src.z != z);
  1821. }
  1822. //-----------------------------------------------------------------------------
  1823. // Copy
  1824. //-----------------------------------------------------------------------------
  1825. inline void VectorCopy( const QAngle& src, QAngle& dst )
  1826. {
  1827. CHECK_VALID(src);
  1828. dst.x = src.x;
  1829. dst.y = src.y;
  1830. dst.z = src.z;
  1831. }
  1832. //-----------------------------------------------------------------------------
  1833. // standard math operations
  1834. //-----------------------------------------------------------------------------
  1835. inline QAngle& QAngle::operator+=(const QAngle& v)
  1836. {
  1837. CHECK_VALID(*this);
  1838. CHECK_VALID(v);
  1839. x+=v.x; y+=v.y; z += v.z;
  1840. return *this;
  1841. }
  1842. inline QAngle& QAngle::operator-=(const QAngle& v)
  1843. {
  1844. CHECK_VALID(*this);
  1845. CHECK_VALID(v);
  1846. x-=v.x; y-=v.y; z -= v.z;
  1847. return *this;
  1848. }
  1849. inline QAngle& QAngle::operator*=(float fl)
  1850. {
  1851. x *= fl;
  1852. y *= fl;
  1853. z *= fl;
  1854. CHECK_VALID(*this);
  1855. return *this;
  1856. }
  1857. inline QAngle& QAngle::operator/=(float fl)
  1858. {
  1859. Assert( fl != 0.0f );
  1860. float oofl = 1.0f / fl;
  1861. x *= oofl;
  1862. y *= oofl;
  1863. z *= oofl;
  1864. CHECK_VALID(*this);
  1865. return *this;
  1866. }
  1867. //-----------------------------------------------------------------------------
  1868. // length
  1869. //-----------------------------------------------------------------------------
  1870. inline vec_t QAngle::Length( ) const
  1871. {
  1872. CHECK_VALID(*this);
  1873. return (vec_t)FastSqrt( LengthSqr( ) );
  1874. }
  1875. inline vec_t QAngle::LengthSqr( ) const
  1876. {
  1877. CHECK_VALID(*this);
  1878. return x * x + y * y + z * z;
  1879. }
  1880. //-----------------------------------------------------------------------------
  1881. // Vector equality with tolerance
  1882. //-----------------------------------------------------------------------------
  1883. inline bool QAnglesAreEqual( const QAngle& src1, const QAngle& src2, float tolerance = 0.0f )
  1884. {
  1885. if (FloatMakePositive(src1.x - src2.x) > tolerance)
  1886. return false;
  1887. if (FloatMakePositive(src1.y - src2.y) > tolerance)
  1888. return false;
  1889. return (FloatMakePositive(src1.z - src2.z) <= tolerance);
  1890. }
  1891. //-----------------------------------------------------------------------------
  1892. // arithmetic operations (SLOW!!)
  1893. //-----------------------------------------------------------------------------
  1894. #ifndef VECTOR_NO_SLOW_OPERATIONS
  1895. inline QAngle QAngle::operator-(void) const
  1896. {
  1897. QAngle ret(-x,-y,-z);
  1898. return ret;
  1899. }
  1900. inline QAngle QAngle::operator+(const QAngle& v) const
  1901. {
  1902. QAngle res;
  1903. res.x = x + v.x;
  1904. res.y = y + v.y;
  1905. res.z = z + v.z;
  1906. return res;
  1907. }
  1908. inline QAngle QAngle::operator-(const QAngle& v) const
  1909. {
  1910. QAngle res;
  1911. res.x = x - v.x;
  1912. res.y = y - v.y;
  1913. res.z = z - v.z;
  1914. return res;
  1915. }
  1916. inline QAngle QAngle::operator*(float fl) const
  1917. {
  1918. QAngle res;
  1919. res.x = x * fl;
  1920. res.y = y * fl;
  1921. res.z = z * fl;
  1922. return res;
  1923. }
  1924. inline QAngle QAngle::operator/(float fl) const
  1925. {
  1926. QAngle res;
  1927. res.x = x / fl;
  1928. res.y = y / fl;
  1929. res.z = z / fl;
  1930. return res;
  1931. }
  1932. inline QAngle operator*(float fl, const QAngle& v)
  1933. {
  1934. QAngle ret( v * fl );
  1935. return ret;
  1936. }
  1937. #endif // VECTOR_NO_SLOW_OPERATIONS
  1938. //-----------------------------------------------------------------------------
  1939. // NOTE: These are not completely correct. The representations are not equivalent
  1940. // unless the QAngle represents a rotational impulse along a coordinate axis (x,y,z)
  1941. inline void QAngleToAngularImpulse( const QAngle &angles, AngularImpulse &impulse )
  1942. {
  1943. impulse.x = angles.z;
  1944. impulse.y = angles.x;
  1945. impulse.z = angles.y;
  1946. }
  1947. inline void AngularImpulseToQAngle( const AngularImpulse &impulse, QAngle &angles )
  1948. {
  1949. angles.x = impulse.y;
  1950. angles.y = impulse.z;
  1951. angles.z = impulse.x;
  1952. }
  1953. #if !defined( _X360 ) && !defined( _PS3 )
  1954. FORCEINLINE vec_t InvRSquared( const float* v )
  1955. {
  1956. return 1.0 / MAX( 1.0, v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
  1957. }
  1958. FORCEINLINE vec_t InvRSquared( const Vector &v )
  1959. {
  1960. return InvRSquared( v.Base() );
  1961. }
  1962. #else
  1963. // call directly
  1964. FORCEINLINE float _VMX_InvRSquared( const Vector &v )
  1965. {
  1966. #if !defined (_PS3)
  1967. XMVECTOR xmV = XMVector3ReciprocalLength( XMLoadVector3( v.Base() ) );
  1968. xmV = XMVector3Dot( xmV, xmV );
  1969. return xmV.x;
  1970. #else //!_PS3
  1971. vector_float_union vRet;
  1972. vec_float4 v0, v1, vIn, vOut;
  1973. vector unsigned char permMask;
  1974. v0 = vec_ld( 0, v.Base() );
  1975. permMask = vec_lvsl( 0, v.Base() );
  1976. v1 = vec_ld( 11, v.Base() );
  1977. vIn = vec_perm(v0, v1, permMask);
  1978. vOut = vec_madd( vIn, vIn, _VEC_ZEROF );
  1979. vec_float4 vTmp = vec_sld( vIn, vIn, 4 );
  1980. vec_float4 vTmp2 = vec_sld( vIn, vIn, 8 );
  1981. vOut = vec_madd( vTmp, vTmp, vOut );
  1982. vOut = vec_madd( vTmp2, vTmp2, vOut );
  1983. vOut = vec_re( vec_add(vOut, _VEC_EPSILONF) );
  1984. vec_st(vOut,0,&vRet.vf);
  1985. float ret = vRet.f[0];
  1986. return ret;
  1987. #endif //!_PS3
  1988. }
  1989. #define InvRSquared(x) _VMX_InvRSquared(x)
  1990. #endif // _X360
  1991. #if !defined( _X360 ) && !defined( _PS3 )
  1992. // FIXME: Change this back to a #define once we get rid of the vec_t version
  1993. float VectorNormalize( Vector& v );
  1994. // FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s
  1995. FORCEINLINE float VectorNormalize( float * v )
  1996. {
  1997. return VectorNormalize(*(reinterpret_cast<Vector *>(v)));
  1998. }
  1999. #else
  2000. #if !defined( _PS3 )
  2001. // modified version of Microsoft's XMVector3Length
  2002. // microsoft's version will return INF for very small vectors
  2003. // e.g. Vector vTest(7.98555446e-20,-6.85012984e-21,0); VectorNormalize( vTest );
  2004. // so we clamp to epsilon instead of checking for zero
  2005. XMFINLINE XMVECTOR XMVector3Length_Fixed
  2006. (
  2007. FXMVECTOR V
  2008. )
  2009. {
  2010. // Returns a QNaN on infinite vectors.
  2011. static CONST XMVECTOR g_fl4SmallVectorEpsilon = {1e-24f,1e-24f,1e-24f,1e-24f};
  2012. XMVECTOR D;
  2013. XMVECTOR Rsq;
  2014. XMVECTOR Rcp;
  2015. XMVECTOR Zero;
  2016. XMVECTOR RT;
  2017. XMVECTOR Result;
  2018. XMVECTOR Length;
  2019. XMVECTOR H;
  2020. H = __vspltisw(1);
  2021. D = __vmsum3fp(V, V);
  2022. H = __vcfsx(H, 1);
  2023. Rsq = __vrsqrtefp(D);
  2024. RT = __vmulfp(D, H);
  2025. Rcp = __vmulfp(Rsq, Rsq);
  2026. H = __vnmsubfp(RT, Rcp, H);
  2027. Rsq = __vmaddfp(Rsq, H, Rsq);
  2028. Zero = __vspltisw(0);
  2029. Result = __vcmpgefp( g_fl4SmallVectorEpsilon, D );
  2030. Length = __vmulfp(D, Rsq);
  2031. Result = __vsel(Length, Zero, Result);
  2032. return Result;
  2033. }
  2034. #endif
  2035. // call directly
  2036. FORCEINLINE float _VMX_VectorNormalize( Vector &vec )
  2037. {
  2038. #if !defined _PS3
  2039. float mag = XMVector3Length_Fixed( XMLoadVector3( vec.Base() ) ).x;
  2040. float den = 1.f / (mag + FLT_EPSILON );
  2041. vec.x *= den;
  2042. vec.y *= den;
  2043. vec.z *= den;
  2044. return mag;
  2045. #else // !_PS3
  2046. vec_float4 vIn;
  2047. vec_float4 v0, v1;
  2048. vector unsigned char permMask;
  2049. v0 = vec_ld( 0, vec.Base() );
  2050. permMask = vec_lvsl( 0, vec.Base() );
  2051. v1 = vec_ld( 11, vec.Base() );
  2052. vIn = vec_perm(v0, v1, permMask);
  2053. float mag = vmathV3Length((VmathVector3 *)&vIn);
  2054. float den = 1.f / (mag + FLT_EPSILON );
  2055. vec.x *= den;
  2056. vec.y *= den;
  2057. vec.z *= den;
  2058. return mag;
  2059. #endif // !_PS3
  2060. }
  2061. // FIXME: Change this back to a #define once we get rid of the vec_t version
  2062. FORCEINLINE float VectorNormalize( Vector& v )
  2063. {
  2064. return _VMX_VectorNormalize( v );
  2065. }
  2066. // FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s
  2067. FORCEINLINE float VectorNormalize( float *pV )
  2068. {
  2069. return _VMX_VectorNormalize(*(reinterpret_cast<Vector*>(pV)));
  2070. }
  2071. #endif // _X360
  2072. #if !defined( _X360 ) && !defined( _PS3 )
  2073. FORCEINLINE void VectorNormalizeFast (Vector& vec)
  2074. {
  2075. float ool = FastRSqrt( FLT_EPSILON + vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
  2076. vec.x *= ool;
  2077. vec.y *= ool;
  2078. vec.z *= ool;
  2079. }
  2080. #else
  2081. // call directly
  2082. FORCEINLINE void VectorNormalizeFast( Vector &vec )
  2083. {
  2084. #if !defined (_PS3)
  2085. XMVECTOR xmV = XMVector3LengthEst( XMLoadVector3( vec.Base() ) );
  2086. float den = 1.f / (xmV.x + FLT_EPSILON);
  2087. vec.x *= den;
  2088. vec.y *= den;
  2089. vec.z *= den;
  2090. #else // !_PS3
  2091. vector_float_union vVec;
  2092. vec_float4 vIn, vOut, vOOLen, vDot;
  2093. // load
  2094. vec_float4 v0, v1;
  2095. vector unsigned char permMask;
  2096. v0 = vec_ld( 0, vec.Base() );
  2097. permMask = vec_lvsl( 0, vec.Base() );
  2098. v1 = vec_ld( 11, vec.Base() );
  2099. vIn = vec_perm(v0, v1, permMask);
  2100. // vec.vec
  2101. vOut = vec_madd( vIn, vIn, _VEC_ZEROF );
  2102. vec_float4 vTmp = vec_sld( vIn, vIn, 4 );
  2103. vec_float4 vTmp2 = vec_sld( vIn, vIn, 8 );
  2104. vOut = vec_madd( vTmp, vTmp, vOut );
  2105. vOut = vec_madd( vTmp2, vTmp2, vOut );
  2106. // splat dot to all
  2107. vDot = vec_splat( vOut, 0 );
  2108. vOOLen = vec_rsqrte( vec_add( vDot, _VEC_EPSILONF ) );
  2109. // vec * 1.0/sqrt(vec.vec)
  2110. vOut = vec_madd( vIn, vOOLen, _VEC_ZEROF );
  2111. // store
  2112. vec_st(vOut,0,&vVec.vf);
  2113. // store vec
  2114. vec.x = vVec.f[0];
  2115. vec.y = vVec.f[1];
  2116. vec.z = vVec.f[2];
  2117. #endif // !_PS3
  2118. }
  2119. #endif // _X360
  2120. inline vec_t Vector::NormalizeInPlace()
  2121. {
  2122. return VectorNormalize( *this );
  2123. }
  2124. inline Vector Vector::Normalized() const
  2125. {
  2126. Vector norm = *this;
  2127. VectorNormalize( norm );
  2128. return norm;
  2129. }
  2130. inline bool Vector::IsLengthGreaterThan( float val ) const
  2131. {
  2132. return LengthSqr() > val*val;
  2133. }
  2134. inline bool Vector::IsLengthLessThan( float val ) const
  2135. {
  2136. return LengthSqr() < val*val;
  2137. }
  2138. #endif