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.

608 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef COMPRESSED_VECTOR_H
  9. #define COMPRESSED_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 "basetypes.h"
  17. // For rand(). We really need a library!
  18. #include <stdlib.h>
  19. #include "tier0/dbg.h"
  20. #include "mathlib/vector.h"
  21. #include "mathlib/mathlib.h"
  22. #if defined( _X360 )
  23. #pragma bitfield_order( push, lsb_to_msb )
  24. #endif
  25. //=========================================================
  26. // fit a 3D vector into 32 bits
  27. //=========================================================
  28. class Vector32
  29. {
  30. public:
  31. // Construction/destruction:
  32. Vector32(void);
  33. Vector32(vec_t X, vec_t Y, vec_t Z);
  34. // assignment
  35. Vector32& operator=(const Vector &vOther);
  36. operator Vector ();
  37. private:
  38. unsigned short x:10;
  39. unsigned short y:10;
  40. unsigned short z:10;
  41. unsigned short exp:2;
  42. };
  43. inline Vector32& Vector32::operator=(const Vector &vOther)
  44. {
  45. CHECK_VALID(vOther);
  46. static float expScale[4] = { 4.0f, 16.0f, 32.f, 64.f };
  47. float fmax = Max( fabs( vOther.x ), fabs( vOther.y ) );
  48. fmax = Max( fmax, (float)fabs( vOther.z ) );
  49. for (exp = 0; exp < 3; exp++)
  50. {
  51. if (fmax < expScale[exp])
  52. break;
  53. }
  54. Assert( fmax < expScale[exp] );
  55. float fexp = 512.0f / expScale[exp];
  56. x = Clamp( (int)(vOther.x * fexp) + 512, 0, 1023 );
  57. y = Clamp( (int)(vOther.y * fexp) + 512, 0, 1023 );
  58. z = Clamp( (int)(vOther.z * fexp) + 512, 0, 1023 );
  59. return *this;
  60. }
  61. inline Vector32::operator Vector ()
  62. {
  63. Vector tmp;
  64. static float expScale[4] = { 4.0f, 16.0f, 32.f, 64.f };
  65. float fexp = expScale[exp] / 512.0f;
  66. tmp.x = (((int)x) - 512) * fexp;
  67. tmp.y = (((int)y) - 512) * fexp;
  68. tmp.z = (((int)z) - 512) * fexp;
  69. return tmp;
  70. }
  71. //=========================================================
  72. // Fit a unit vector into 32 bits
  73. //=========================================================
  74. class Normal32
  75. {
  76. public:
  77. // Construction/destruction:
  78. Normal32(void);
  79. Normal32(vec_t X, vec_t Y, vec_t Z);
  80. // assignment
  81. Normal32& operator=(const Vector &vOther);
  82. operator Vector ();
  83. private:
  84. unsigned short x:15;
  85. unsigned short y:15;
  86. unsigned short zneg:1;
  87. };
  88. inline Normal32& Normal32::operator=(const Vector &vOther)
  89. {
  90. CHECK_VALID(vOther);
  91. x = Clamp( (int)(vOther.x * 16384) + 16384, 0, 32767 );
  92. y = Clamp( (int)(vOther.y * 16384) + 16384, 0, 32767 );
  93. zneg = (vOther.z < 0);
  94. //x = vOther.x;
  95. //y = vOther.y;
  96. //z = vOther.z;
  97. return *this;
  98. }
  99. inline Normal32::operator Vector ()
  100. {
  101. Vector tmp;
  102. tmp.x = ((int)x - 16384) * (1 / 16384.0);
  103. tmp.y = ((int)y - 16384) * (1 / 16384.0);
  104. tmp.z = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y );
  105. if (zneg)
  106. tmp.z = -tmp.z;
  107. return tmp;
  108. }
  109. //=========================================================
  110. // 64 bit Quaternion
  111. //=========================================================
  112. class Quaternion64
  113. {
  114. public:
  115. // Construction/destruction:
  116. Quaternion64(void);
  117. Quaternion64(vec_t X, vec_t Y, vec_t Z);
  118. // assignment
  119. // Quaternion& operator=(const Quaternion64 &vOther);
  120. Quaternion64& operator=(const Quaternion &vOther);
  121. operator Quaternion ();
  122. private:
  123. uint64 x:21;
  124. uint64 y:21;
  125. uint64 z:21;
  126. uint64 wneg:1;
  127. };
  128. inline Quaternion64::operator Quaternion ()
  129. {
  130. Quaternion tmp;
  131. // shift to -1048576, + 1048575, then round down slightly to -1.0 < x < 1.0
  132. tmp.x = ((int)x - 1048576) * (1 / 1048576.5f);
  133. tmp.y = ((int)y - 1048576) * (1 / 1048576.5f);
  134. tmp.z = ((int)z - 1048576) * (1 / 1048576.5f);
  135. tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z );
  136. if (wneg)
  137. tmp.w = -tmp.w;
  138. return tmp;
  139. }
  140. inline Quaternion64& Quaternion64::operator=(const Quaternion &vOther)
  141. {
  142. CHECK_VALID(vOther);
  143. x = Clamp( (int)(vOther.x * 1048576) + 1048576, 0, 2097151 );
  144. y = Clamp( (int)(vOther.y * 1048576) + 1048576, 0, 2097151 );
  145. z = Clamp( (int)(vOther.z * 1048576) + 1048576, 0, 2097151 );
  146. wneg = (vOther.w < 0);
  147. return *this;
  148. }
  149. //=========================================================
  150. // 48 bit Quaternion
  151. //=========================================================
  152. class Quaternion48
  153. {
  154. public:
  155. // Construction/destruction:
  156. Quaternion48(void);
  157. Quaternion48(vec_t X, vec_t Y, vec_t Z);
  158. // assignment
  159. // Quaternion& operator=(const Quaternion48 &vOther);
  160. Quaternion48& operator=(const Quaternion &vOther);
  161. operator Quaternion ();
  162. private:
  163. unsigned short x:16;
  164. unsigned short y:16;
  165. unsigned short z:15;
  166. unsigned short wneg:1;
  167. };
  168. inline Quaternion48::operator Quaternion ()
  169. {
  170. Quaternion tmp;
  171. tmp.x = ((int)x - 32768) * (1 / 32768.0);
  172. tmp.y = ((int)y - 32768) * (1 / 32768.0);
  173. tmp.z = ((int)z - 16384) * (1 / 16384.0);
  174. tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z );
  175. if (wneg)
  176. tmp.w = -tmp.w;
  177. return tmp;
  178. }
  179. inline Quaternion48& Quaternion48::operator=(const Quaternion &vOther)
  180. {
  181. CHECK_VALID(vOther);
  182. x = Clamp( (int)(vOther.x * 32768) + 32768, 0, 65535 );
  183. y = Clamp( (int)(vOther.y * 32768) + 32768, 0, 65535 );
  184. z = Clamp( (int)(vOther.z * 16384) + 16384, 0, 32767 );
  185. wneg = (vOther.w < 0);
  186. return *this;
  187. }
  188. //=========================================================
  189. // 32 bit Quaternion
  190. //=========================================================
  191. class Quaternion32
  192. {
  193. public:
  194. // Construction/destruction:
  195. Quaternion32(void);
  196. Quaternion32(vec_t X, vec_t Y, vec_t Z);
  197. // assignment
  198. // Quaternion& operator=(const Quaternion48 &vOther);
  199. Quaternion32& operator=(const Quaternion &vOther);
  200. operator Quaternion ();
  201. private:
  202. unsigned int x:11;
  203. unsigned int y:10;
  204. unsigned int z:10;
  205. unsigned int wneg:1;
  206. };
  207. inline Quaternion32::operator Quaternion ()
  208. {
  209. Quaternion tmp;
  210. tmp.x = ((int)x - 1024) * (1 / 1024.0);
  211. tmp.y = ((int)y - 512) * (1 / 512.0);
  212. tmp.z = ((int)z - 512) * (1 / 512.0);
  213. tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z );
  214. if (wneg)
  215. tmp.w = -tmp.w;
  216. return tmp;
  217. }
  218. inline Quaternion32& Quaternion32::operator=(const Quaternion &vOther)
  219. {
  220. CHECK_VALID(vOther);
  221. x = Clamp( (int)(vOther.x * 1024) + 1024, 0, 2047 );
  222. y = Clamp( (int)(vOther.y * 512) + 512, 0, 1023 );
  223. z = Clamp( (int)(vOther.z * 512) + 512, 0, 1023 );
  224. wneg = (vOther.w < 0);
  225. return *this;
  226. }
  227. //=========================================================
  228. // 16 bit float
  229. //=========================================================
  230. const int float32bias = 127;
  231. const int float16bias = 15;
  232. const float maxfloat16bits = 65504.0f;
  233. class float16
  234. {
  235. public:
  236. //float16() {}
  237. //float16( float f ) { m_storage.rawWord = ConvertFloatTo16bits(f); }
  238. void Init() { m_storage.rawWord = 0; }
  239. // float16& operator=(const float16 &other) { m_storage.rawWord = other.m_storage.rawWord; return *this; }
  240. // float16& operator=(const float &other) { m_storage.rawWord = ConvertFloatTo16bits(other); return *this; }
  241. // operator unsigned short () { return m_storage.rawWord; }
  242. // operator float () { return Convert16bitFloatTo32bits( m_storage.rawWord ); }
  243. unsigned short GetBits() const
  244. {
  245. return m_storage.rawWord;
  246. }
  247. float GetFloat() const
  248. {
  249. return Convert16bitFloatTo32bits( m_storage.rawWord );
  250. }
  251. void SetFloat( float in )
  252. {
  253. m_storage.rawWord = ConvertFloatTo16bits( in );
  254. }
  255. bool IsInfinity() const
  256. {
  257. return m_storage.bits.biased_exponent == 31 && m_storage.bits.mantissa == 0;
  258. }
  259. bool IsNaN() const
  260. {
  261. return m_storage.bits.biased_exponent == 31 && m_storage.bits.mantissa != 0;
  262. }
  263. bool operator==(const float16 other) const { return m_storage.rawWord == other.m_storage.rawWord; }
  264. bool operator!=(const float16 other) const { return m_storage.rawWord != other.m_storage.rawWord; }
  265. // bool operator< (const float other) const { return GetFloat() < other; }
  266. // bool operator> (const float other) const { return GetFloat() > other; }
  267. protected:
  268. union float32bits
  269. {
  270. float rawFloat;
  271. struct
  272. {
  273. unsigned int mantissa : 23;
  274. unsigned int biased_exponent : 8;
  275. unsigned int sign : 1;
  276. } bits;
  277. };
  278. union float16bits
  279. {
  280. unsigned short rawWord;
  281. struct
  282. {
  283. unsigned short mantissa : 10;
  284. unsigned short biased_exponent : 5;
  285. unsigned short sign : 1;
  286. } bits;
  287. };
  288. static bool IsNaN( float16bits in )
  289. {
  290. return in.bits.biased_exponent == 31 && in.bits.mantissa != 0;
  291. }
  292. static bool IsInfinity( float16bits in )
  293. {
  294. return in.bits.biased_exponent == 31 && in.bits.mantissa == 0;
  295. }
  296. // 0x0001 - 0x03ff
  297. static unsigned short ConvertFloatTo16bits( float input )
  298. {
  299. if ( input > maxfloat16bits )
  300. input = maxfloat16bits;
  301. else if ( input < -maxfloat16bits )
  302. input = -maxfloat16bits;
  303. float16bits output;
  304. float32bits inFloat;
  305. inFloat.rawFloat = input;
  306. output.bits.sign = inFloat.bits.sign;
  307. if ( (inFloat.bits.biased_exponent==0) && (inFloat.bits.mantissa==0) )
  308. {
  309. // zero
  310. output.bits.mantissa = 0;
  311. output.bits.biased_exponent = 0;
  312. }
  313. else if ( (inFloat.bits.biased_exponent==0) && (inFloat.bits.mantissa!=0) )
  314. {
  315. // denorm -- denorm float maps to 0 half
  316. output.bits.mantissa = 0;
  317. output.bits.biased_exponent = 0;
  318. }
  319. else if ( (inFloat.bits.biased_exponent==0xff) && (inFloat.bits.mantissa==0) )
  320. {
  321. #if 0
  322. // infinity
  323. output.bits.mantissa = 0;
  324. output.bits.biased_exponent = 31;
  325. #else
  326. // infinity maps to maxfloat
  327. output.bits.mantissa = 0x3ff;
  328. output.bits.biased_exponent = 0x1e;
  329. #endif
  330. }
  331. else if ( (inFloat.bits.biased_exponent==0xff) && (inFloat.bits.mantissa!=0) )
  332. {
  333. #if 0
  334. // NaN
  335. output.bits.mantissa = 1;
  336. output.bits.biased_exponent = 31;
  337. #else
  338. // NaN maps to zero
  339. output.bits.mantissa = 0;
  340. output.bits.biased_exponent = 0;
  341. #endif
  342. }
  343. else
  344. {
  345. // regular number
  346. int new_exp = inFloat.bits.biased_exponent-127;
  347. if (new_exp<-24)
  348. {
  349. // this maps to 0
  350. output.bits.mantissa = 0;
  351. output.bits.biased_exponent = 0;
  352. }
  353. if (new_exp<-14)
  354. {
  355. // this maps to a denorm
  356. output.bits.biased_exponent = 0;
  357. unsigned int exp_val = ( unsigned int )( -14 - ( inFloat.bits.biased_exponent - float32bias ) );
  358. if( exp_val > 0 && exp_val < 11 )
  359. {
  360. output.bits.mantissa = ( 1 << ( 10 - exp_val ) ) + ( inFloat.bits.mantissa >> ( 13 + exp_val ) );
  361. }
  362. }
  363. else if (new_exp>15)
  364. {
  365. #if 0
  366. // map this value to infinity
  367. output.bits.mantissa = 0;
  368. output.bits.biased_exponent = 31;
  369. #else
  370. // to big. . . maps to maxfloat
  371. output.bits.mantissa = 0x3ff;
  372. output.bits.biased_exponent = 0x1e;
  373. #endif
  374. }
  375. else
  376. {
  377. output.bits.biased_exponent = new_exp+15;
  378. output.bits.mantissa = (inFloat.bits.mantissa >> 13);
  379. }
  380. }
  381. return output.rawWord;
  382. }
  383. static float Convert16bitFloatTo32bits( unsigned short input )
  384. {
  385. float32bits output;
  386. const float16bits &inFloat = *((float16bits *)&input);
  387. if( IsInfinity( inFloat ) )
  388. {
  389. return maxfloat16bits * ( ( inFloat.bits.sign == 1 ) ? -1.0f : 1.0f );
  390. }
  391. if( IsNaN( inFloat ) )
  392. {
  393. return 0.0;
  394. }
  395. if( inFloat.bits.biased_exponent == 0 && inFloat.bits.mantissa != 0 )
  396. {
  397. // denorm
  398. const float half_denorm = (1.0f/16384.0f); // 2^-14
  399. float mantissa = ((float)(inFloat.bits.mantissa)) / 1024.0f;
  400. float sgn = (inFloat.bits.sign)? -1.0f :1.0f;
  401. output.rawFloat = sgn*mantissa*half_denorm;
  402. }
  403. else
  404. {
  405. // regular number
  406. unsigned mantissa = inFloat.bits.mantissa;
  407. unsigned biased_exponent = inFloat.bits.biased_exponent;
  408. unsigned sign = ((unsigned)inFloat.bits.sign) << 31;
  409. biased_exponent = ( (biased_exponent - float16bias + float32bias) * (biased_exponent != 0) ) << 23;
  410. mantissa <<= (23-10);
  411. *((unsigned *)&output) = ( mantissa | biased_exponent | sign );
  412. }
  413. return output.rawFloat;
  414. }
  415. float16bits m_storage;
  416. };
  417. class float16_with_assign : public float16
  418. {
  419. public:
  420. float16_with_assign() {}
  421. float16_with_assign( float f ) { m_storage.rawWord = ConvertFloatTo16bits(f); }
  422. float16& operator=(const float16 &other) { m_storage.rawWord = ((float16_with_assign &)other).m_storage.rawWord; return *this; }
  423. float16& operator=(const float &other) { m_storage.rawWord = ConvertFloatTo16bits(other); return *this; }
  424. // operator unsigned short () const { return m_storage.rawWord; }
  425. operator float () const { return Convert16bitFloatTo32bits( m_storage.rawWord ); }
  426. };
  427. //=========================================================
  428. // Fit a 3D vector in 48 bits
  429. //=========================================================
  430. class Vector48
  431. {
  432. public:
  433. // Construction/destruction:
  434. Vector48(void) {}
  435. Vector48(vec_t X, vec_t Y, vec_t Z) { x.SetFloat( X ); y.SetFloat( Y ); z.SetFloat( Z ); }
  436. // assignment
  437. Vector48& operator=(const Vector &vOther);
  438. operator Vector ();
  439. const float operator[]( int i ) const { return (((float16 *)this)[i]).GetFloat(); }
  440. float16 x;
  441. float16 y;
  442. float16 z;
  443. };
  444. inline Vector48& Vector48::operator=(const Vector &vOther)
  445. {
  446. CHECK_VALID(vOther);
  447. x.SetFloat( vOther.x );
  448. y.SetFloat( vOther.y );
  449. z.SetFloat( vOther.z );
  450. return *this;
  451. }
  452. inline Vector48::operator Vector ()
  453. {
  454. Vector tmp;
  455. tmp.x = x.GetFloat();
  456. tmp.y = y.GetFloat();
  457. tmp.z = z.GetFloat();
  458. return tmp;
  459. }
  460. //=========================================================
  461. // Fit a 2D vector in 32 bits
  462. //=========================================================
  463. class Vector2d32
  464. {
  465. public:
  466. // Construction/destruction:
  467. Vector2d32(void) {}
  468. Vector2d32(vec_t X, vec_t Y) { x.SetFloat( X ); y.SetFloat( Y ); }
  469. // assignment
  470. Vector2d32& operator=(const Vector &vOther);
  471. Vector2d32& operator=(const Vector2D &vOther);
  472. operator Vector2D ();
  473. void Init( vec_t ix = 0.f, vec_t iy = 0.f);
  474. float16_with_assign x;
  475. float16_with_assign y;
  476. };
  477. inline Vector2d32& Vector2d32::operator=(const Vector2D &vOther)
  478. {
  479. x.SetFloat( vOther.x );
  480. y.SetFloat( vOther.y );
  481. return *this;
  482. }
  483. inline Vector2d32::operator Vector2D ()
  484. {
  485. Vector2D tmp;
  486. tmp.x = x.GetFloat();
  487. tmp.y = y.GetFloat();
  488. return tmp;
  489. }
  490. inline void Vector2d32::Init( vec_t ix, vec_t iy )
  491. {
  492. x.SetFloat(ix);
  493. y.SetFloat(iy);
  494. }
  495. #if defined( _X360 )
  496. #pragma bitfield_order( pop )
  497. #endif
  498. #endif