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.

670 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef VECTOR2D_H
  9. #define VECTOR2D_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. // For rand(). We really need a library!
  18. #include <stdlib.h>
  19. #include "tier0/dbg.h"
  20. #include "mathlib/math_pfns.h"
  21. //=========================================================
  22. // 2D Vector2D
  23. //=========================================================
  24. class Vector2D
  25. {
  26. public:
  27. // Members
  28. vec_t x, y;
  29. // Construction/destruction
  30. Vector2D(void);
  31. Vector2D(vec_t X, vec_t Y);
  32. Vector2D(const float *pFloat);
  33. // Initialization
  34. void Init(vec_t ix=0.0f, vec_t iy=0.0f);
  35. // Got any nasty NAN's?
  36. bool IsValid() const;
  37. // array access...
  38. vec_t operator[](int i) const;
  39. vec_t& operator[](int i);
  40. // Base address...
  41. vec_t* Base();
  42. vec_t const* Base() const;
  43. // Initialization methods
  44. void Random( float minVal, float maxVal );
  45. // equality
  46. bool operator==(const Vector2D& v) const;
  47. bool operator!=(const Vector2D& v) const;
  48. // arithmetic operations
  49. Vector2D& operator+=(const Vector2D &v);
  50. Vector2D& operator-=(const Vector2D &v);
  51. Vector2D& operator*=(const Vector2D &v);
  52. Vector2D& operator*=(float s);
  53. Vector2D& operator/=(const Vector2D &v);
  54. Vector2D& operator/=(float s);
  55. // negate the Vector2D components
  56. void Negate();
  57. // Get the Vector2D's magnitude.
  58. vec_t Length() const;
  59. // Get the Vector2D's magnitude squared.
  60. vec_t LengthSqr(void) const;
  61. // return true if this vector is (0,0) within tolerance
  62. bool IsZero( float tolerance = 0.01f ) const
  63. {
  64. return (x > -tolerance && x < tolerance &&
  65. y > -tolerance && y < tolerance);
  66. }
  67. // Normalize in place and return the old length.
  68. vec_t NormalizeInPlace();
  69. // Compare length.
  70. bool IsLengthGreaterThan( float val ) const;
  71. bool IsLengthLessThan( float val ) const;
  72. // Get the distance from this Vector2D to the other one.
  73. vec_t DistTo(const Vector2D &vOther) const;
  74. // Get the distance from this Vector2D to the other one squared.
  75. vec_t DistToSqr(const Vector2D &vOther) const;
  76. // Copy
  77. void CopyToArray(float* rgfl) const;
  78. // Multiply, add, and assign to this (ie: *this = a + b * scalar). This
  79. // is about 12% faster than the actual Vector2D equation (because it's done per-component
  80. // rather than per-Vector2D).
  81. void MulAdd(const Vector2D& a, const Vector2D& b, float scalar);
  82. // Dot product.
  83. vec_t Dot(const Vector2D& vOther) const;
  84. // assignment
  85. Vector2D& operator=(const Vector2D &vOther);
  86. #ifndef VECTOR_NO_SLOW_OPERATIONS
  87. // copy constructors
  88. Vector2D(const Vector2D &vOther);
  89. // arithmetic operations
  90. Vector2D operator-(void) const;
  91. Vector2D operator+(const Vector2D& v) const;
  92. Vector2D operator-(const Vector2D& v) const;
  93. Vector2D operator*(const Vector2D& v) const;
  94. Vector2D operator/(const Vector2D& v) const;
  95. Vector2D operator*(float fl) const;
  96. Vector2D operator/(float fl) const;
  97. // Cross product between two vectors.
  98. Vector2D Cross(const Vector2D &vOther) const;
  99. // Returns a Vector2D with the min or max in X, Y, and Z.
  100. Vector2D Min(const Vector2D &vOther) const;
  101. Vector2D Max(const Vector2D &vOther) const;
  102. #else
  103. private:
  104. // No copy constructors allowed if we're in optimal mode
  105. Vector2D(const Vector2D& vOther);
  106. #endif
  107. };
  108. //-----------------------------------------------------------------------------
  109. const Vector2D vec2_origin(0,0);
  110. const Vector2D vec2_invalid( FLT_MAX, FLT_MAX );
  111. //-----------------------------------------------------------------------------
  112. // Vector2D related operations
  113. //-----------------------------------------------------------------------------
  114. // Vector2D clear
  115. void Vector2DClear( Vector2D& a );
  116. // Copy
  117. void Vector2DCopy( const Vector2D& src, Vector2D& dst );
  118. // Vector2D arithmetic
  119. void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& result );
  120. void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& result );
  121. void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& result );
  122. void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& result );
  123. void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& result );
  124. void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& result );
  125. void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result );
  126. // Store the min or max of each of x, y, and z into the result.
  127. void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result );
  128. void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result );
  129. #define Vector2DExpand( v ) (v).x, (v).y
  130. // Normalization
  131. vec_t Vector2DNormalize( Vector2D& v );
  132. // Length
  133. vec_t Vector2DLength( const Vector2D& v );
  134. // Dot Product
  135. vec_t DotProduct2D(const Vector2D& a, const Vector2D& b);
  136. // Linearly interpolate between two vectors
  137. void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest );
  138. //-----------------------------------------------------------------------------
  139. //
  140. // Inlined Vector2D methods
  141. //
  142. //-----------------------------------------------------------------------------
  143. //-----------------------------------------------------------------------------
  144. // constructors
  145. //-----------------------------------------------------------------------------
  146. inline Vector2D::Vector2D(void)
  147. {
  148. #ifdef _DEBUG
  149. // Initialize to NAN to catch errors
  150. x = y = VEC_T_NAN;
  151. #endif
  152. }
  153. inline Vector2D::Vector2D(vec_t X, vec_t Y)
  154. {
  155. x = X; y = Y;
  156. Assert( IsValid() );
  157. }
  158. inline Vector2D::Vector2D(const float *pFloat)
  159. {
  160. Assert( pFloat );
  161. x = pFloat[0]; y = pFloat[1];
  162. Assert( IsValid() );
  163. }
  164. //-----------------------------------------------------------------------------
  165. // copy constructor
  166. //-----------------------------------------------------------------------------
  167. inline Vector2D::Vector2D(const Vector2D &vOther)
  168. {
  169. Assert( vOther.IsValid() );
  170. x = vOther.x; y = vOther.y;
  171. }
  172. //-----------------------------------------------------------------------------
  173. // initialization
  174. //-----------------------------------------------------------------------------
  175. inline void Vector2D::Init( vec_t ix, vec_t iy )
  176. {
  177. x = ix; y = iy;
  178. Assert( IsValid() );
  179. }
  180. inline void Vector2D::Random( float minVal, float maxVal )
  181. {
  182. x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
  183. y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
  184. }
  185. inline void Vector2DClear( Vector2D& a )
  186. {
  187. a.x = a.y = 0.0f;
  188. }
  189. //-----------------------------------------------------------------------------
  190. // assignment
  191. //-----------------------------------------------------------------------------
  192. inline Vector2D& Vector2D::operator=(const Vector2D &vOther)
  193. {
  194. Assert( vOther.IsValid() );
  195. x=vOther.x; y=vOther.y;
  196. return *this;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Array access
  200. //-----------------------------------------------------------------------------
  201. inline vec_t& Vector2D::operator[](int i)
  202. {
  203. Assert( (i >= 0) && (i < 2) );
  204. return ((vec_t*)this)[i];
  205. }
  206. inline vec_t Vector2D::operator[](int i) const
  207. {
  208. Assert( (i >= 0) && (i < 2) );
  209. return ((vec_t*)this)[i];
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Base address...
  213. //-----------------------------------------------------------------------------
  214. inline vec_t* Vector2D::Base()
  215. {
  216. return (vec_t*)this;
  217. }
  218. inline vec_t const* Vector2D::Base() const
  219. {
  220. return (vec_t const*)this;
  221. }
  222. //-----------------------------------------------------------------------------
  223. // IsValid?
  224. //-----------------------------------------------------------------------------
  225. inline bool Vector2D::IsValid() const
  226. {
  227. return IsFinite(x) && IsFinite(y);
  228. }
  229. //-----------------------------------------------------------------------------
  230. // comparison
  231. //-----------------------------------------------------------------------------
  232. inline bool Vector2D::operator==( const Vector2D& src ) const
  233. {
  234. Assert( src.IsValid() && IsValid() );
  235. return (src.x == x) && (src.y == y);
  236. }
  237. inline bool Vector2D::operator!=( const Vector2D& src ) const
  238. {
  239. Assert( src.IsValid() && IsValid() );
  240. return (src.x != x) || (src.y != y);
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Copy
  244. //-----------------------------------------------------------------------------
  245. inline void Vector2DCopy( const Vector2D& src, Vector2D& dst )
  246. {
  247. Assert( src.IsValid() );
  248. dst.x = src.x;
  249. dst.y = src.y;
  250. }
  251. inline void Vector2D::CopyToArray(float* rgfl) const
  252. {
  253. Assert( IsValid() );
  254. Assert( rgfl );
  255. rgfl[0] = x; rgfl[1] = y;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // standard math operations
  259. //-----------------------------------------------------------------------------
  260. inline void Vector2D::Negate()
  261. {
  262. Assert( IsValid() );
  263. x = -x; y = -y;
  264. }
  265. inline Vector2D& Vector2D::operator+=(const Vector2D& v)
  266. {
  267. Assert( IsValid() && v.IsValid() );
  268. x+=v.x; y+=v.y;
  269. return *this;
  270. }
  271. inline Vector2D& Vector2D::operator-=(const Vector2D& v)
  272. {
  273. Assert( IsValid() && v.IsValid() );
  274. x-=v.x; y-=v.y;
  275. return *this;
  276. }
  277. inline Vector2D& Vector2D::operator*=(float fl)
  278. {
  279. x *= fl;
  280. y *= fl;
  281. Assert( IsValid() );
  282. return *this;
  283. }
  284. inline Vector2D& Vector2D::operator*=(const Vector2D& v)
  285. {
  286. x *= v.x;
  287. y *= v.y;
  288. Assert( IsValid() );
  289. return *this;
  290. }
  291. inline Vector2D& Vector2D::operator/=(float fl)
  292. {
  293. Assert( fl != 0.0f );
  294. float oofl = 1.0f / fl;
  295. x *= oofl;
  296. y *= oofl;
  297. Assert( IsValid() );
  298. return *this;
  299. }
  300. inline Vector2D& Vector2D::operator/=(const Vector2D& v)
  301. {
  302. Assert( v.x != 0.0f && v.y != 0.0f );
  303. x /= v.x;
  304. y /= v.y;
  305. Assert( IsValid() );
  306. return *this;
  307. }
  308. inline void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& c )
  309. {
  310. Assert( a.IsValid() && b.IsValid() );
  311. c.x = a.x + b.x;
  312. c.y = a.y + b.y;
  313. }
  314. inline void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& c )
  315. {
  316. Assert( a.IsValid() && b.IsValid() );
  317. c.x = a.x - b.x;
  318. c.y = a.y - b.y;
  319. }
  320. inline void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& c )
  321. {
  322. Assert( a.IsValid() && IsFinite(b) );
  323. c.x = a.x * b;
  324. c.y = a.y * b;
  325. }
  326. inline void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& c )
  327. {
  328. Assert( a.IsValid() && b.IsValid() );
  329. c.x = a.x * b.x;
  330. c.y = a.y * b.y;
  331. }
  332. inline void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& c )
  333. {
  334. Assert( a.IsValid() );
  335. Assert( b != 0.0f );
  336. vec_t oob = 1.0f / b;
  337. c.x = a.x * oob;
  338. c.y = a.y * oob;
  339. }
  340. inline void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& c )
  341. {
  342. Assert( a.IsValid() );
  343. Assert( (b.x != 0.0f) && (b.y != 0.0f) );
  344. c.x = a.x / b.x;
  345. c.y = a.y / b.y;
  346. }
  347. inline void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result )
  348. {
  349. Assert( start.IsValid() && IsFinite(s) && dir.IsValid() );
  350. result.x = start.x + s*dir.x;
  351. result.y = start.y + s*dir.y;
  352. }
  353. // FIXME: Remove
  354. // For backwards compatability
  355. inline void Vector2D::MulAdd(const Vector2D& a, const Vector2D& b, float scalar)
  356. {
  357. x = a.x + b.x * scalar;
  358. y = a.y + b.y * scalar;
  359. }
  360. inline void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest )
  361. {
  362. dest[0] = src1[0] + (src2[0] - src1[0]) * t;
  363. dest[1] = src1[1] + (src2[1] - src1[1]) * t;
  364. }
  365. //-----------------------------------------------------------------------------
  366. // dot, cross
  367. //-----------------------------------------------------------------------------
  368. inline vec_t DotProduct2D(const Vector2D& a, const Vector2D& b)
  369. {
  370. Assert( a.IsValid() && b.IsValid() );
  371. return( a.x*b.x + a.y*b.y );
  372. }
  373. // for backwards compatability
  374. inline vec_t Vector2D::Dot( const Vector2D& vOther ) const
  375. {
  376. return DotProduct2D( *this, vOther );
  377. }
  378. //-----------------------------------------------------------------------------
  379. // length
  380. //-----------------------------------------------------------------------------
  381. inline vec_t Vector2DLength( const Vector2D& v )
  382. {
  383. Assert( v.IsValid() );
  384. return (vec_t)FastSqrt(v.x*v.x + v.y*v.y);
  385. }
  386. inline vec_t Vector2D::LengthSqr(void) const
  387. {
  388. Assert( IsValid() );
  389. return (x*x + y*y);
  390. }
  391. inline vec_t Vector2D::NormalizeInPlace()
  392. {
  393. return Vector2DNormalize( *this );
  394. }
  395. inline bool Vector2D::IsLengthGreaterThan( float val ) const
  396. {
  397. return LengthSqr() > val*val;
  398. }
  399. inline bool Vector2D::IsLengthLessThan( float val ) const
  400. {
  401. return LengthSqr() < val*val;
  402. }
  403. inline vec_t Vector2D::Length(void) const
  404. {
  405. return Vector2DLength( *this );
  406. }
  407. inline void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result )
  408. {
  409. result.x = (a.x < b.x) ? a.x : b.x;
  410. result.y = (a.y < b.y) ? a.y : b.y;
  411. }
  412. inline void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result )
  413. {
  414. result.x = (a.x > b.x) ? a.x : b.x;
  415. result.y = (a.y > b.y) ? a.y : b.y;
  416. }
  417. //-----------------------------------------------------------------------------
  418. // Normalization
  419. //-----------------------------------------------------------------------------
  420. inline vec_t Vector2DNormalize( Vector2D& v )
  421. {
  422. Assert( v.IsValid() );
  423. vec_t l = v.Length();
  424. if (l != 0.0f)
  425. {
  426. v /= l;
  427. }
  428. else
  429. {
  430. v.x = v.y = 0.0f;
  431. }
  432. return l;
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Get the distance from this Vector2D to the other one
  436. //-----------------------------------------------------------------------------
  437. inline vec_t Vector2D::DistTo(const Vector2D &vOther) const
  438. {
  439. Vector2D delta;
  440. Vector2DSubtract( *this, vOther, delta );
  441. return delta.Length();
  442. }
  443. inline vec_t Vector2D::DistToSqr(const Vector2D &vOther) const
  444. {
  445. Vector2D delta;
  446. Vector2DSubtract( *this, vOther, delta );
  447. return delta.LengthSqr();
  448. }
  449. //-----------------------------------------------------------------------------
  450. // Computes the closest point to vecTarget no farther than flMaxDist from vecStart
  451. //-----------------------------------------------------------------------------
  452. inline void ComputeClosestPoint2D( const Vector2D& vecStart, float flMaxDist, const Vector2D& vecTarget, Vector2D *pResult )
  453. {
  454. Vector2D vecDelta;
  455. Vector2DSubtract( vecTarget, vecStart, vecDelta );
  456. float flDistSqr = vecDelta.LengthSqr();
  457. if ( flDistSqr <= flMaxDist * flMaxDist )
  458. {
  459. *pResult = vecTarget;
  460. }
  461. else
  462. {
  463. vecDelta /= FastSqrt( flDistSqr );
  464. Vector2DMA( vecStart, flMaxDist, vecDelta, *pResult );
  465. }
  466. }
  467. //-----------------------------------------------------------------------------
  468. //
  469. // Slow methods
  470. //
  471. //-----------------------------------------------------------------------------
  472. #ifndef VECTOR_NO_SLOW_OPERATIONS
  473. //-----------------------------------------------------------------------------
  474. // Returns a Vector2D with the min or max in X, Y, and Z.
  475. //-----------------------------------------------------------------------------
  476. inline Vector2D Vector2D::Min(const Vector2D &vOther) const
  477. {
  478. return Vector2D(x < vOther.x ? x : vOther.x,
  479. y < vOther.y ? y : vOther.y);
  480. }
  481. inline Vector2D Vector2D::Max(const Vector2D &vOther) const
  482. {
  483. return Vector2D(x > vOther.x ? x : vOther.x,
  484. y > vOther.y ? y : vOther.y);
  485. }
  486. //-----------------------------------------------------------------------------
  487. // arithmetic operations
  488. //-----------------------------------------------------------------------------
  489. inline Vector2D Vector2D::operator-(void) const
  490. {
  491. return Vector2D(-x,-y);
  492. }
  493. inline Vector2D Vector2D::operator+(const Vector2D& v) const
  494. {
  495. Vector2D res;
  496. Vector2DAdd( *this, v, res );
  497. return res;
  498. }
  499. inline Vector2D Vector2D::operator-(const Vector2D& v) const
  500. {
  501. Vector2D res;
  502. Vector2DSubtract( *this, v, res );
  503. return res;
  504. }
  505. inline Vector2D Vector2D::operator*(float fl) const
  506. {
  507. Vector2D res;
  508. Vector2DMultiply( *this, fl, res );
  509. return res;
  510. }
  511. inline Vector2D Vector2D::operator*(const Vector2D& v) const
  512. {
  513. Vector2D res;
  514. Vector2DMultiply( *this, v, res );
  515. return res;
  516. }
  517. inline Vector2D Vector2D::operator/(float fl) const
  518. {
  519. Vector2D res;
  520. Vector2DDivide( *this, fl, res );
  521. return res;
  522. }
  523. inline Vector2D Vector2D::operator/(const Vector2D& v) const
  524. {
  525. Vector2D res;
  526. Vector2DDivide( *this, v, res );
  527. return res;
  528. }
  529. inline Vector2D operator*(float fl, const Vector2D& v)
  530. {
  531. return v * fl;
  532. }
  533. #endif //slow
  534. #endif // VECTOR2D_H