Obb.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/collision/Obb.h>
  6. namespace anki
  7. {
  8. Obb Obb::getCompoundShape(const Obb& b) const
  9. {
  10. check();
  11. b.check();
  12. Obb out;
  13. Array<Vec4, 8> points0;
  14. Array<Vec4, 8> points1;
  15. getExtremePoints(points0);
  16. b.getExtremePoints(points1);
  17. Array<Vec4, 16> points;
  18. for(U i = 0; i < 8; i++)
  19. {
  20. points[i] = points0[i];
  21. points[i + 8] = points1[i];
  22. }
  23. out.setFromPointCloud(reinterpret_cast<const Vec3*>(&points[0]), points.getSize(), sizeof(Vec4), sizeof(points));
  24. return out;
  25. }
  26. void Obb::getExtremePoints(Array<Vec4, 8>& points) const
  27. {
  28. check();
  29. // L: left, R: right, T: top, B: bottom, F: front, B: back
  30. enum : U8
  31. {
  32. RTF,
  33. LTF,
  34. LBF,
  35. RBF,
  36. RTB,
  37. LTB,
  38. LBB,
  39. RBB
  40. };
  41. const Vec3 er3 = m_rotation * m_extend; // extend rotated
  42. const Vec4 er(er3, 0.0f);
  43. points[RTF] = er;
  44. points[LBB] = -er;
  45. const Vec4 xAxis = Vec4(m_rotation.getColumn(0).getNormalized(), 0.0f);
  46. const Vec4 yAxis = Vec4(m_rotation.getColumn(1).getNormalized(), 0.0f);
  47. const Vec4 zAxis = Vec4(m_rotation.getColumn(2).getNormalized(), 0.0f);
  48. // Reflection: x1' = 2n|x1.n| - x1
  49. points[RBB] = 2.0f * er.dot(xAxis) * xAxis - er;
  50. points[LTB] = 2.0f * er.dot(yAxis) * yAxis - er;
  51. points[LBF] = 2.0f * er.dot(zAxis) * zAxis - er;
  52. points[LTF] = 2.0f * points[LBB].dot(-xAxis) * -xAxis - points[LBB];
  53. points[RTB] = 2.0f * points[LTF].dot(yAxis) * yAxis - points[LTF];
  54. points[RBF] = 2.0f * points[LTF].dot(zAxis) * zAxis - points[LTF];
  55. for(Vec4& point : points)
  56. {
  57. point += m_center;
  58. }
  59. }
  60. void Obb::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride, PtrSize buffSize)
  61. {
  62. // Preconditions
  63. ANKI_ASSERT(pointBuffer);
  64. ANKI_ASSERT(pointCount > 1);
  65. ANKI_ASSERT(pointStride >= sizeof(Vec3));
  66. ANKI_ASSERT(buffSize >= pointStride * pointCount);
  67. Vec4 min = Vec4(Vec3(MAX_F32), 0.0);
  68. Vec4 max = Vec4(Vec3(MIN_F32), 0.0);
  69. // Iterate
  70. const U8* ptr = reinterpret_cast<const U8*>(pointBuffer);
  71. while(pointCount-- != 0)
  72. {
  73. ANKI_ASSERT((ptrToNumber(ptr) + sizeof(Vec3) - ptrToNumber(pointBuffer)) <= buffSize);
  74. const Vec3* pos = reinterpret_cast<const Vec3*>(ptr);
  75. max = max.max(pos->xyz0());
  76. min = min.min(pos->xyz0());
  77. ptr += pointStride;
  78. }
  79. // Set the locals
  80. m_center = (max + min) / 2.0;
  81. m_rotation = Mat3x4::getIdentity();
  82. m_extend = max - m_center;
  83. }
  84. Vec4 Obb::computeSupport(const Vec4& dir) const
  85. {
  86. check();
  87. Array<Vec4, 8> points;
  88. getExtremePoints(points);
  89. U best = 0;
  90. F32 bestDot = points[0].dot(dir);
  91. for(U i = 1; i < points.size(); i++)
  92. {
  93. F32 d = points[i].dot(dir);
  94. if(d > bestDot)
  95. {
  96. best = i;
  97. bestDot = d;
  98. }
  99. }
  100. return points[best];
  101. }
  102. } // end namespace anki