bounds.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Copyright 2011-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <bx/rng.h>
  6. #include "bounds.h"
  7. #include "math.h"
  8. void aabbToObb(Obb& _obb, const Aabb& _aabb)
  9. {
  10. memset(_obb.m_mtx, 0, sizeof(_obb.m_mtx) );
  11. _obb.m_mtx[ 0] = (_aabb.m_max[0] - _aabb.m_min[0]) * 0.5f;
  12. _obb.m_mtx[ 5] = (_aabb.m_max[1] - _aabb.m_min[1]) * 0.5f;
  13. _obb.m_mtx[10] = (_aabb.m_max[2] - _aabb.m_min[2]) * 0.5f;
  14. _obb.m_mtx[12] = (_aabb.m_min[0] + _aabb.m_max[0]) * 0.5f;
  15. _obb.m_mtx[13] = (_aabb.m_min[1] + _aabb.m_max[1]) * 0.5f;
  16. _obb.m_mtx[14] = (_aabb.m_min[2] + _aabb.m_max[2]) * 0.5f;
  17. _obb.m_mtx[15] = 1.0f;
  18. }
  19. void aabbTransformToObb(Obb& _obb, const Aabb& _aabb, const float* _mtx)
  20. {
  21. aabbToObb(_obb, _aabb);
  22. float result[16];
  23. mtxMul(result, _obb.m_mtx, _mtx);
  24. memcpy(_obb.m_mtx, result, sizeof(result) );
  25. }
  26. float calcAreaAabb(Aabb& _aabb)
  27. {
  28. float ww = _aabb.m_max[0] - _aabb.m_min[0];
  29. float hh = _aabb.m_max[1] - _aabb.m_min[1];
  30. float dd = _aabb.m_max[2] - _aabb.m_min[2];
  31. return 2.0f * (ww*hh + ww*dd + hh*dd);
  32. }
  33. void calcAabb(Aabb& _aabb, const void* _vertices, uint32_t _numVertices, uint32_t _stride)
  34. {
  35. float min[3], max[3];
  36. uint8_t* vertex = (uint8_t*)_vertices;
  37. float* position = (float*)vertex;
  38. min[0] = max[0] = position[0];
  39. min[1] = max[1] = position[1];
  40. min[2] = max[2] = position[2];
  41. vertex += _stride;
  42. for (uint32_t ii = 1; ii < _numVertices; ++ii)
  43. {
  44. position = (float*)vertex;
  45. vertex += _stride;
  46. float xx = position[0];
  47. float yy = position[1];
  48. float zz = position[2];
  49. min[0] = fmin(xx, min[0]);
  50. min[1] = fmin(yy, min[1]);
  51. min[2] = fmin(zz, min[2]);
  52. max[0] = fmax(xx, max[0]);
  53. max[1] = fmax(yy, max[1]);
  54. max[2] = fmax(zz, max[2]);
  55. }
  56. _aabb.m_min[0] = min[0];
  57. _aabb.m_min[1] = min[1];
  58. _aabb.m_min[2] = min[2];
  59. _aabb.m_max[0] = max[0];
  60. _aabb.m_max[1] = max[1];
  61. _aabb.m_max[2] = max[2];
  62. }
  63. void calcAabb(Aabb& _aabb, const float* _mtx, const void* _vertices, uint32_t _numVertices, uint32_t _stride)
  64. {
  65. float min[3], max[3];
  66. uint8_t* vertex = (uint8_t*)_vertices;
  67. float position[3];
  68. vec3MulMtx(position, (float*)vertex, _mtx);
  69. min[0] = max[0] = position[0];
  70. min[1] = max[1] = position[1];
  71. min[2] = max[2] = position[2];
  72. vertex += _stride;
  73. for (uint32_t ii = 1; ii < _numVertices; ++ii)
  74. {
  75. vec3MulMtx(position, (float*)vertex, _mtx);
  76. vertex += _stride;
  77. float xx = position[0];
  78. float yy = position[1];
  79. float zz = position[2];
  80. min[0] = fmin(xx, min[0]);
  81. min[1] = fmin(yy, min[1]);
  82. min[2] = fmin(zz, min[2]);
  83. max[0] = fmax(xx, max[0]);
  84. max[1] = fmax(yy, max[1]);
  85. max[2] = fmax(zz, max[2]);
  86. }
  87. _aabb.m_min[0] = min[0];
  88. _aabb.m_min[1] = min[1];
  89. _aabb.m_min[2] = min[2];
  90. _aabb.m_max[0] = max[0];
  91. _aabb.m_max[1] = max[1];
  92. _aabb.m_max[2] = max[2];
  93. }
  94. void calcObb(Obb& _obb, const void* _vertices, uint32_t _numVertices, uint32_t _stride, uint32_t _steps)
  95. {
  96. Aabb aabb;
  97. calcAabb(aabb, _vertices, _numVertices, _stride);
  98. float minArea = calcAreaAabb(aabb);
  99. Obb best;
  100. aabbToObb(best, aabb);
  101. float angleStep = float(M_PI_2/_steps);
  102. float ax = 0.0f;
  103. float mtx[16];
  104. for (uint32_t ii = 0; ii < _steps; ++ii)
  105. {
  106. float ay = 0.0f;
  107. for (uint32_t jj = 0; jj < _steps; ++jj)
  108. {
  109. float az = 0.0f;
  110. for (uint32_t kk = 0; kk < _steps; ++kk)
  111. {
  112. mtxRotateXYZ(mtx, ax, ay, az);
  113. float mtxT[16];
  114. mtxTranspose(mtxT, mtx);
  115. calcAabb(aabb, mtxT, _vertices, _numVertices, _stride);
  116. float area = calcAreaAabb(aabb);
  117. if (area < minArea)
  118. {
  119. minArea = area;
  120. aabbTransformToObb(best, aabb, mtx);
  121. }
  122. az += angleStep;
  123. }
  124. ay += angleStep;
  125. }
  126. ax += angleStep;
  127. }
  128. memcpy(&_obb, &best, sizeof(Obb) );
  129. }
  130. void calcMaxBoundingSphere(Sphere& _sphere, const void* _vertices, uint32_t _numVertices, uint32_t _stride)
  131. {
  132. Aabb aabb;
  133. calcAabb(aabb, _vertices, _numVertices, _stride);
  134. float center[3];
  135. center[0] = (aabb.m_min[0] + aabb.m_max[0]) * 0.5f;
  136. center[1] = (aabb.m_min[1] + aabb.m_max[1]) * 0.5f;
  137. center[2] = (aabb.m_min[2] + aabb.m_max[2]) * 0.5f;
  138. float maxDistSq = 0.0f;
  139. uint8_t* vertex = (uint8_t*)_vertices;
  140. for (uint32_t ii = 0; ii < _numVertices; ++ii)
  141. {
  142. float* position = (float*)vertex;
  143. vertex += _stride;
  144. float xx = position[0] - center[0];
  145. float yy = position[1] - center[1];
  146. float zz = position[2] - center[2];
  147. float distSq = xx*xx + yy*yy + zz*zz;
  148. maxDistSq = fmax(distSq, maxDistSq);
  149. }
  150. _sphere.m_center[0] = center[0];
  151. _sphere.m_center[1] = center[1];
  152. _sphere.m_center[2] = center[2];
  153. _sphere.m_radius = sqrtf(maxDistSq);
  154. }
  155. void calcMinBoundingSphere(Sphere& _sphere, const void* _vertices, uint32_t _numVertices, uint32_t _stride, float _step)
  156. {
  157. bx::RngMwc rng;
  158. uint8_t* vertex = (uint8_t*)_vertices;
  159. float center[3];
  160. float* position = (float*)&vertex[0];
  161. center[0] = position[0];
  162. center[1] = position[1];
  163. center[2] = position[2];
  164. position = (float*)&vertex[1*_stride];
  165. center[0] += position[0];
  166. center[1] += position[1];
  167. center[2] += position[2];
  168. center[0] *= 0.5f;
  169. center[1] *= 0.5f;
  170. center[2] *= 0.5f;
  171. float xx = position[0] - center[0];
  172. float yy = position[1] - center[1];
  173. float zz = position[2] - center[2];
  174. float maxDistSq = xx*xx + yy*yy + zz*zz;
  175. float radiusStep = _step * 0.37f;
  176. bool done;
  177. do
  178. {
  179. done = true;
  180. for (uint32_t ii = 0, index = rng.gen()%_numVertices; ii < _numVertices; ++ii, index = (index + 1)%_numVertices)
  181. {
  182. position = (float*)&vertex[index*_stride];
  183. float xx = position[0] - center[0];
  184. float yy = position[1] - center[1];
  185. float zz = position[2] - center[2];
  186. float distSq = xx*xx + yy*yy + zz*zz;
  187. if (distSq > maxDistSq)
  188. {
  189. done = false;
  190. center[0] += xx * radiusStep;
  191. center[1] += yy * radiusStep;
  192. center[2] += zz * radiusStep;
  193. maxDistSq = flerp(maxDistSq, distSq, _step);
  194. break;
  195. }
  196. }
  197. } while (!done);
  198. _sphere.m_center[0] = center[0];
  199. _sphere.m_center[1] = center[1];
  200. _sphere.m_center[2] = center[2];
  201. _sphere.m_radius = sqrtf(maxDistSq);
  202. }