Obb.cpp 2.8 KB

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