mini_glm.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /* ==========================================================================
  2. * Copyright (c) 2022 SuperTuxKart-Team
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to permit
  9. * persons to whom the Software is furnished to do so, subject to the
  10. * following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  18. * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  19. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. * ==========================================================================
  23. */
  24. #ifndef HEADER_MINI_GLM_HPP
  25. #define HEADER_MINI_GLM_HPP
  26. #include "LinearMath/btQuaternion.h"
  27. #include "LinearMath/btTransform.h"
  28. #include "LinearMath/btVector3.h"
  29. #include <algorithm>
  30. #include <array>
  31. #include <cassert>
  32. #include <cmath>
  33. #include <cstdint>
  34. #include <quaternion.h>
  35. #include <vector3d.h>
  36. #include "irrMath.h"
  37. using namespace irr;
  38. // GLM without template
  39. namespace MiniGLM
  40. {
  41. // ------------------------------------------------------------------------
  42. inline float overflow()
  43. {
  44. volatile float f = 1e10;
  45. for (int i = 0; i < 10; i++)
  46. f *= f; // this will overflow before the for loop terminates
  47. return f;
  48. } // overflow
  49. // ------------------------------------------------------------------------
  50. inline float toFloat32(short value)
  51. {
  52. int s = (value >> 15) & 0x00000001;
  53. int e = (value >> 10) & 0x0000001f;
  54. int m = value & 0x000003ff;
  55. if (e == 0)
  56. {
  57. if (m == 0)
  58. {
  59. //
  60. // Plus or minus zero
  61. //
  62. uint32_t tmp_data = (unsigned int)(s << 31);
  63. float ret;
  64. memcpy(&ret, &tmp_data, 4);
  65. return ret;
  66. }
  67. else
  68. {
  69. //
  70. // Denormalized number -- renormalize it
  71. //
  72. while(!(m & 0x00000400))
  73. {
  74. m <<= 1;
  75. e -= 1;
  76. }
  77. e += 1;
  78. m &= ~0x00000400;
  79. }
  80. }
  81. else if (e == 31)
  82. {
  83. if (m == 0)
  84. {
  85. //
  86. // Positive or negative infinity
  87. //
  88. uint32_t tmp_data = (unsigned int)((s << 31) | 0x7f800000);
  89. float ret;
  90. memcpy(&ret, &tmp_data, 4);
  91. return ret;
  92. }
  93. else
  94. {
  95. //
  96. // Nan -- preserve sign and significand bits
  97. //
  98. uint32_t tmp_data = (unsigned int)((s << 31) | 0x7f800000 |
  99. (m << 13));
  100. float ret;
  101. memcpy(&ret, &tmp_data, 4);
  102. return ret;
  103. }
  104. }
  105. //
  106. // Normalized number
  107. //
  108. e = e + (127 - 15);
  109. m = m << 13;
  110. //
  111. // Assemble s, e and m.
  112. //
  113. uint32_t tmp_data = (unsigned int)((s << 31) | (e << 23) | m);
  114. float ret;
  115. memcpy(&ret, &tmp_data, 4);
  116. return ret;
  117. } // toFloat32
  118. // ------------------------------------------------------------------------
  119. inline short toFloat16(float const & f)
  120. {
  121. int i;
  122. memcpy(&i, &f, 4);
  123. //
  124. // Our floating point number, f, is represented by the bit
  125. // pattern in integer i. Disassemble that bit pattern into
  126. // the sign, s, the exponent, e, and the significand, m.
  127. // Shift s into the position where it will go in in the
  128. // resulting half number.
  129. // Adjust e, accounting for the different exponent bias
  130. // of float and half (127 versus 15).
  131. //
  132. int s = (i >> 16) & 0x00008000;
  133. int e = ((i >> 23) & 0x000000ff) - (127 - 15);
  134. int m = i & 0x007fffff;
  135. //
  136. // Now reassemble s, e and m into a half:
  137. //
  138. if (e <= 0)
  139. {
  140. if (e < -10)
  141. {
  142. //
  143. // E is less than -10. The absolute value of f is
  144. // less than half_MIN (f may be a small normalized
  145. // float, a denormalized float or a zero).
  146. //
  147. // We convert f to a half zero.
  148. //
  149. return short(s);
  150. }
  151. //
  152. // E is between -10 and 0. F is a normalized float,
  153. // whose magnitude is less than __half_NRM_MIN.
  154. //
  155. // We convert f to a denormalized half.
  156. //
  157. m = (m | 0x00800000) >> (1 - e);
  158. //
  159. // Round to nearest, round "0.5" up.
  160. //
  161. // Rounding may cause the significand to overflow and make
  162. // our number normalized. Because of the way a half's bits
  163. // are laid out, we don't have to treat this case separately;
  164. // the code below will handle it correctly.
  165. //
  166. if (m & 0x00001000)
  167. m += 0x00002000;
  168. //
  169. // Assemble the half from s, e (zero) and m.
  170. //
  171. return short(s | (m >> 13));
  172. }
  173. else if (e == 0xff - (127 - 15))
  174. {
  175. if (m == 0)
  176. {
  177. //
  178. // F is an infinity; convert f to a half
  179. // infinity with the same sign as f.
  180. //
  181. return short(s | 0x7c00);
  182. }
  183. else
  184. {
  185. //
  186. // F is a NAN; we produce a half NAN that preserves
  187. // the sign bit and the 10 leftmost bits of the
  188. // significand of f, with one exception: If the 10
  189. // leftmost bits are all zero, the NAN would turn
  190. // into an infinity, so we have to set at least one
  191. // bit in the significand.
  192. //
  193. m >>= 13;
  194. return short(s | 0x7c00 | m | (m == 0));
  195. }
  196. }
  197. else
  198. {
  199. //
  200. // E is greater than zero. F is a normalized float.
  201. // We try to convert f to a normalized half.
  202. //
  203. //
  204. // Round to nearest, round "0.5" up
  205. //
  206. if (m & 0x00001000)
  207. {
  208. m += 0x00002000;
  209. if (m & 0x00800000)
  210. {
  211. m = 0; // overflow in significand,
  212. e += 1; // adjust exponent
  213. }
  214. }
  215. //
  216. // Handle exponent overflow
  217. //
  218. if (e > 30)
  219. {
  220. overflow(); // Cause a hardware floating point overflow;
  221. return short(s | 0x7c00);
  222. // if this returns, the half becomes an
  223. } // infinity with the same sign as f.
  224. //
  225. // Assemble the half from s, e and m.
  226. //
  227. return short(s | (e << 10) | (m >> 13));
  228. }
  229. } // toFloat16
  230. // ------------------------------------------------------------------------
  231. inline uint32_t normalizedSignedFloatsTo1010102
  232. (const std::array<float, 3>& src, int extra_2_bit = -1)
  233. {
  234. int part = 0;
  235. uint32_t packed = 0;
  236. float v = fminf(1.0f, fmaxf(-1.0f, src[0]));
  237. if (v > 0.0f)
  238. {
  239. part = (int)((v * 511.0f) + 0.5f);
  240. }
  241. else
  242. {
  243. part = (int)((v * 512.0f) - 0.5f);
  244. }
  245. packed |= ((uint32_t)part & 1023) << 0;
  246. v = fminf(1.0f, fmaxf(-1.0f, src[1]));
  247. if (v > 0.0f)
  248. {
  249. part = (int)((v * 511.0f) + 0.5f);
  250. }
  251. else
  252. {
  253. part = (int)((v * 512.0f) - 0.5f);
  254. }
  255. packed |= ((uint32_t)part & 1023) << 10;
  256. v = fminf(1.0f, fmaxf(-1.0f, src[2]));
  257. if (v > 0.0f)
  258. {
  259. part = (int)((v * 511.0f) + 0.5f);
  260. }
  261. else
  262. {
  263. part = (int)((v * 512.0f) - 0.5f);
  264. }
  265. packed |= ((uint32_t)part & 1023) << 20;
  266. if (extra_2_bit >= 0)
  267. {
  268. part = extra_2_bit;
  269. }
  270. else
  271. {
  272. part = (int)(-0.5f);
  273. }
  274. packed |= ((uint32_t)part & 3) << 30;
  275. return packed;
  276. } // normalizedSignedFloatsTo1010102
  277. // ------------------------------------------------------------------------
  278. inline std::array<short, 4> vertexType2101010RevTo4HF(uint32_t packed)
  279. {
  280. std::array<float, 4> ret;
  281. int part = packed & 1023;
  282. if (part & 512)
  283. {
  284. ret[0] = (float)(1024 - part) * (-1.0f / 512.0f);
  285. }
  286. else
  287. {
  288. ret[0] = (float)part * (1.0f / 511.0f);
  289. }
  290. part = (packed >> 10) & 1023;
  291. if (part & 512)
  292. {
  293. ret[1] = (float)(1024 - part) * (-1.0f / 512.0f);
  294. }
  295. else
  296. {
  297. ret[1] = (float)part * (1.0f / 511.0f);
  298. }
  299. part = (packed >> 20) & 1023;
  300. if (part & 512)
  301. {
  302. ret[2] = (float)(1024 - part) * (-1.0f / 512.0f);
  303. }
  304. else
  305. {
  306. ret[2] = (float)part * (1.0f / 511.0f);
  307. }
  308. part = (packed >> 30) & 3;
  309. if (part & 2)
  310. {
  311. ret[3] = (float)(4 - part) * (-1.0f / 2.0f);
  312. }
  313. else
  314. {
  315. ret[3] = (float)part;
  316. }
  317. std::array<short, 4> result;
  318. for (int i = 0; i < 4; i++)
  319. {
  320. result[i] = toFloat16(ret[i]);
  321. }
  322. return result;
  323. } // vertexType2101010RevTo4HF
  324. // ------------------------------------------------------------------------
  325. inline std::array<float, 4> extractNormalizedSignedFloats(uint32_t packed,
  326. bool calculate_w = false)
  327. {
  328. std::array<float, 4> ret = {};
  329. int part = packed & 1023;
  330. if (part & 512)
  331. {
  332. ret[0] = (float)(1024 - part) * (-1.0f / 512.0f);
  333. }
  334. else
  335. {
  336. ret[0] = (float)part * (1.0f / 511.0f);
  337. }
  338. part = (packed >> 10) & 1023;
  339. if (part & 512)
  340. {
  341. ret[1] = (float)(1024 - part) * (-1.0f / 512.0f);
  342. }
  343. else
  344. {
  345. ret[1] = (float)part * (1.0f / 511.0f);
  346. }
  347. part = (packed >> 20) & 1023;
  348. if (part & 512)
  349. {
  350. ret[2] = (float)(1024 - part) * (-1.0f / 512.0f);
  351. }
  352. else
  353. {
  354. ret[2] = (float)part * (1.0f / 511.0f);
  355. }
  356. if (calculate_w)
  357. {
  358. float inv_sqrt_2 = 1.0f / sqrtf(2.0f);
  359. ret[0] *= inv_sqrt_2;
  360. ret[1] *= inv_sqrt_2;
  361. ret[2] *= inv_sqrt_2;
  362. float largest_val = sqrtf(fmaxf(0.0f, 1.0f -
  363. (ret[0] * ret[0]) - (ret[1] * ret[1]) - (ret[2] * ret[2])));
  364. part = (packed >> 30) & 3;
  365. switch(part)
  366. {
  367. case 0:
  368. {
  369. auto tmp = ret;
  370. ret[0] = largest_val;
  371. ret[1] = tmp[0];
  372. ret[2] = tmp[1];
  373. ret[3] = tmp[2];
  374. break;
  375. }
  376. case 1:
  377. {
  378. auto tmp = ret;
  379. ret[0] = tmp[0];
  380. ret[1] = largest_val;
  381. ret[2] = tmp[1];
  382. ret[3] = tmp[2];
  383. break;
  384. }
  385. case 2:
  386. {
  387. auto tmp = ret;
  388. ret[0] = tmp[0];
  389. ret[1] = tmp[1];
  390. ret[2] = largest_val;
  391. ret[3] = tmp[2];
  392. break;
  393. }
  394. case 3:
  395. ret[3] = largest_val;
  396. break;
  397. default:
  398. assert(false);
  399. break;
  400. }
  401. }
  402. return ret;
  403. } // extractNormalizedSignedFloats
  404. // ------------------------------------------------------------------------
  405. // Please normalize vector before compressing
  406. // ------------------------------------------------------------------------
  407. inline uint32_t compressVector3(const irr::core::vector3df& vec)
  408. {
  409. return normalizedSignedFloatsTo1010102({{vec.X, vec.Y, vec.Z}});
  410. } // compressVector3
  411. // ------------------------------------------------------------------------
  412. inline core::vector3df decompressVector3(uint32_t packed)
  413. {
  414. const std::array<float, 4> out = extractNormalizedSignedFloats(packed);
  415. core::vector3df ret(out[0], out[1], out[2]);
  416. return ret.normalize();
  417. } // decompressVector3
  418. // ------------------------------------------------------------------------
  419. inline uint32_t compressQuaternion(const btQuaternion& q)
  420. {
  421. const float length = q.length();
  422. assert(length != 0.0f);
  423. std::array<float, 4> tmp_2 =
  424. {{
  425. q.x() / length,
  426. q.y() / length,
  427. q.z() / length,
  428. q.w() / length
  429. }};
  430. std::array<float, 3> tmp_3 = {};
  431. auto ret = std::max_element(tmp_2.begin(), tmp_2.end(),
  432. [](float a, float b) { return std::abs(a) < std::abs(b); });
  433. int extra_2_bit = int(std::distance(tmp_2.begin(), ret));
  434. float sqrt_2 = sqrtf(2.0f);
  435. switch (extra_2_bit)
  436. {
  437. case 0:
  438. {
  439. float neg = tmp_2[0] < 0.0f ? -1.0f : 1.0f;
  440. tmp_3[0] = tmp_2[1] * neg * sqrt_2;
  441. tmp_3[1] = tmp_2[2] * neg * sqrt_2;
  442. tmp_3[2] = tmp_2[3] * neg * sqrt_2;
  443. break;
  444. }
  445. case 1:
  446. {
  447. float neg = tmp_2[1] < 0.0f ? -1.0f : 1.0f;
  448. tmp_3[0] = tmp_2[0] * neg * sqrt_2;
  449. tmp_3[1] = tmp_2[2] * neg * sqrt_2;
  450. tmp_3[2] = tmp_2[3] * neg * sqrt_2;
  451. break;
  452. }
  453. case 2:
  454. {
  455. float neg = tmp_2[2] < 0.0f ? -1.0f : 1.0f;
  456. tmp_3[0] = tmp_2[0] * neg * sqrt_2;
  457. tmp_3[1] = tmp_2[1] * neg * sqrt_2;
  458. tmp_3[2] = tmp_2[3] * neg * sqrt_2;
  459. break;
  460. }
  461. case 3:
  462. {
  463. float neg = tmp_2[3] < 0.0f ? -1.0f : 1.0f;
  464. tmp_3[0] = tmp_2[0] * neg * sqrt_2;
  465. tmp_3[1] = tmp_2[1] * neg * sqrt_2;
  466. tmp_3[2] = tmp_2[2] * neg * sqrt_2;
  467. break;
  468. }
  469. default:
  470. assert(false);
  471. break;
  472. }
  473. return normalizedSignedFloatsTo1010102(tmp_3, extra_2_bit);
  474. } // compressQuaternion
  475. // ------------------------------------------------------------------------
  476. inline uint32_t compressIrrQuaternion(const core::quaternion& q)
  477. {
  478. return compressQuaternion(btQuaternion(q.X, q.Y, q.Z, q.W));
  479. }
  480. // ------------------------------------------------------------------------
  481. inline core::quaternion decompressQuaternion(uint32_t packed)
  482. {
  483. const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
  484. true/*calculate_w*/);
  485. core::quaternion ret(out[0], out[1], out[2], out[3]);
  486. return ret.normalize();
  487. } // decompressQuaternion
  488. // ------------------------------------------------------------------------
  489. inline btQuaternion decompressbtQuaternion(uint32_t packed)
  490. {
  491. const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
  492. true/*calculate_w*/);
  493. btQuaternion ret(out[0], out[1], out[2], out[3]);
  494. return ret.normalize();
  495. } // decompressbtQuaternion
  496. // ------------------------------------------------------------------------
  497. inline std::array<float, 4> getQuaternionInternal(const core::matrix4& m)
  498. {
  499. btVector3 row[3];
  500. memcpy(&row[0][0], &m[0], 12);
  501. memcpy(&row[1][0], &m[4], 12);
  502. memcpy(&row[2][0], &m[8], 12);
  503. std::array<float, 4> q;
  504. float root = row[0].x() + row[1].y() + row[2].z();
  505. const float trace = root;
  506. if (trace > 0.0f)
  507. {
  508. root = sqrtf(trace + 1.0f);
  509. q[3] = 0.5f * root;
  510. root = 0.5f / root;
  511. q[0] = root * (row[1].z() - row[2].y());
  512. q[1] = root * (row[2].x() - row[0].z());
  513. q[2] = root * (row[0].y() - row[1].x());
  514. }
  515. else
  516. {
  517. static int next[3] = {1, 2, 0};
  518. int i = 0;
  519. int j = 0;
  520. int k = 0;
  521. if (row[1].y() > row[0].x())
  522. {
  523. i = 1;
  524. }
  525. if (row[2].z() > row[i][i])
  526. {
  527. i = 2;
  528. }
  529. j = next[i];
  530. k = next[j];
  531. root = sqrtf(row[i][i] - row[j][j] - row[k][k] + 1.0f);
  532. q[i] = 0.5f * root;
  533. root = 0.5f / root;
  534. q[j] = root * (row[i][j] + row[j][i]);
  535. q[k] = root * (row[i][k] + row[k][i]);
  536. q[3] = root * (row[j][k] - row[k][j]);
  537. }
  538. return q;
  539. }
  540. // ------------------------------------------------------------------------
  541. inline core::quaternion getQuaternion(const core::matrix4& m)
  542. {
  543. std::array<float, 4> q = getQuaternionInternal(m);
  544. return core::quaternion(q[0], q[1], q[2], q[3]).normalize();
  545. }
  546. // ------------------------------------------------------------------------
  547. inline btQuaternion getBulletQuaternion(const core::matrix4& m)
  548. {
  549. std::array<float, 4> q = getQuaternionInternal(m);
  550. return btQuaternion(q[0], q[1], q[2], q[3]).normalize();
  551. }
  552. // ------------------------------------------------------------------------
  553. inline uint32_t quickTangent(uint32_t packed_normal)
  554. {
  555. core::vector3df normal = decompressVector3(packed_normal);
  556. core::vector3df tangent;
  557. core::vector3df c1 =
  558. normal.crossProduct(core::vector3df(0.0f, 0.0f, 1.0f));
  559. core::vector3df c2 =
  560. normal.crossProduct(core::vector3df(0.0f, 1.0f, 0.0f));
  561. if (c1.getLengthSQ() > c2.getLengthSQ())
  562. {
  563. tangent = c1;
  564. }
  565. else
  566. {
  567. tangent = c2;
  568. }
  569. tangent.normalize();
  570. // Assume bitangent sign is positive 1.0f
  571. return compressVector3(tangent) | 1 << 30;
  572. } // quickTangent
  573. // ------------------------------------------------------------------------
  574. /** Round and save compressed values (optionally) btTransform.
  575. * It will round with 2 digits with min / max +/- 2^23 / 100 for origin in
  576. * btTransform and call compressQuaternion above to compress the rotation
  577. * part, if compressed_data is provided, 3 24 bits and 1 32 bits of
  578. * compressed data will be written in an int[4] array.
  579. */
  580. inline void compressbtTransform(btTransform& cur_t,
  581. int* compressed_data = NULL)
  582. {
  583. int x = (int)(cur_t.getOrigin().x() * 100.0f);
  584. int y = (int)(cur_t.getOrigin().y() * 100.0f);
  585. int z = (int)(cur_t.getOrigin().z() * 100.0f);
  586. x = core::clamp(x, -0x800000, 0x7fffff);
  587. y = core::clamp(y, -0x800000, 0x7fffff);
  588. z = core::clamp(z, -0x800000, 0x7fffff);
  589. uint32_t compressed_q = compressQuaternion(cur_t.getRotation());
  590. cur_t.setOrigin(btVector3(
  591. (float)x / 100.0f,
  592. (float)y / 100.0f,
  593. (float)z / 100.0f));
  594. cur_t.setRotation(decompressbtQuaternion(compressed_q));
  595. if (compressed_data)
  596. {
  597. compressed_data[0] = x;
  598. compressed_data[1] = y;
  599. compressed_data[2] = z;
  600. compressed_data[3] = (int)compressed_q;
  601. }
  602. } // compressbtTransform
  603. // ------------------------------------------------------------------------
  604. inline btTransform decompressbtTransform(int* compressed_data)
  605. {
  606. btTransform trans;
  607. trans.setOrigin(btVector3(
  608. (float)compressed_data[0] / 100.0f,
  609. (float)compressed_data[1] / 100.0f,
  610. (float)compressed_data[2] / 100.0f));
  611. trans.setRotation(decompressbtQuaternion(
  612. (uint32_t)compressed_data[3]));
  613. return trans;
  614. } // decompressbtTransform
  615. // ------------------------------------------------------------------------
  616. void unitTesting();
  617. }
  618. #endif