FunctionsTestPlane.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include <AnKi/Collision/Functions.h>
  2. #include <AnKi/Collision/ConvexHullShape.h>
  3. #include <AnKi/Collision/Obb.h>
  4. #include <AnKi/Collision/LineSegment.h>
  5. #include <AnKi/Collision/Cone.h>
  6. #include <AnKi/Collision/Sphere.h>
  7. namespace anki {
  8. F32 testPlane(const Plane& plane, const Aabb& aabb)
  9. {
  10. #if ANKI_SIMD_SSE
  11. __m128 gezero = _mm_cmpge_ps(plane.getNormal().getSimd(), _mm_setzero_ps());
  12. Vec4 diagMin;
  13. diagMin.getSimd() = _mm_or_ps(_mm_and_ps(gezero, aabb.getMin().getSimd()), _mm_andnot_ps(gezero, aabb.getMax().getSimd()));
  14. #else
  15. Vec4 diagMin(0.0f), diagMax(0.0f);
  16. // set min/max values for x,y,z direction
  17. for(U i = 0; i < 3; i++)
  18. {
  19. if(plane.getNormal()[i] >= 0.0f)
  20. {
  21. diagMin[i] = aabb.getMin()[i];
  22. diagMax[i] = aabb.getMax()[i];
  23. }
  24. else
  25. {
  26. diagMin[i] = aabb.getMax()[i];
  27. diagMax[i] = aabb.getMin()[i];
  28. }
  29. }
  30. #endif
  31. // minimum on positive side of plane, box on positive side
  32. ANKI_ASSERT(diagMin.w() == 0.0f);
  33. F32 test = testPlane(plane, diagMin);
  34. if(test > 0.0f)
  35. {
  36. return test;
  37. }
  38. #if ANKI_SIMD_SSE
  39. Vec4 diagMax;
  40. diagMax.getSimd() = _mm_or_ps(_mm_and_ps(gezero, aabb.getMax().getSimd()), _mm_andnot_ps(gezero, aabb.getMin().getSimd()));
  41. #endif
  42. ANKI_ASSERT(diagMax.w() == 0.0f);
  43. test = testPlane(plane, diagMax);
  44. if(test >= 0.0f)
  45. {
  46. // min on non-positive side, max on non-negative side, intersection
  47. return 0.0f;
  48. }
  49. else
  50. {
  51. // max on negative side, box on negative side
  52. return test;
  53. }
  54. }
  55. F32 testPlane(const Plane& plane, const Sphere& sphere)
  56. {
  57. const F32 dist = testPlane(plane, sphere.getCenter());
  58. F32 out = dist - sphere.getRadius();
  59. if(out > 0.0f)
  60. {
  61. // Do nothing
  62. }
  63. else
  64. {
  65. out = dist + sphere.getRadius();
  66. if(out < 0.0f)
  67. {
  68. // Do nothing
  69. }
  70. else
  71. {
  72. out = 0.0f;
  73. }
  74. }
  75. return out;
  76. }
  77. F32 testPlane(const Plane& plane, const Obb& obb)
  78. {
  79. Mat3x4 transposedRotation = obb.getRotation();
  80. transposedRotation.transposeRotationPart();
  81. const Vec4 xNormal = (transposedRotation * plane.getNormal()).xyz0();
  82. // maximum extent in direction of plane normal
  83. const Vec4 rv = obb.getExtend() * xNormal;
  84. const Vec4 rvabs = rv.abs();
  85. const F32 r = rvabs.x() + rvabs.y() + rvabs.z();
  86. // signed distance between box center and plane
  87. const F32 d = testPlane(plane, obb.getCenter());
  88. // return signed distance
  89. if(absolute(d) < r)
  90. {
  91. return 0.0f;
  92. }
  93. else if(d < 0.0f)
  94. {
  95. return d + r;
  96. }
  97. else
  98. {
  99. return d - r;
  100. }
  101. }
  102. F32 testPlane(const Plane& plane, const ConvexHullShape& hull)
  103. {
  104. // Compute the invert transformation of the plane instead
  105. const Plane pa = (hull.isTransformIdentity()) ? plane : plane.getTransformed(hull.getInvertTransform());
  106. F32 minDist = kMaxF32;
  107. F32 maxDist = kMinF32;
  108. ConstWeakArray<Vec4> points = hull.getPoints();
  109. for(const Vec4& point : points)
  110. {
  111. const F32 test = testPlane(pa, point);
  112. if(test == 0.0f) [[unlikely]]
  113. {
  114. // Early exit
  115. return 0.0f;
  116. }
  117. minDist = min(minDist, test);
  118. maxDist = max(maxDist, test);
  119. }
  120. if(minDist > 0.0f && maxDist > 0.0f)
  121. {
  122. return minDist;
  123. }
  124. else if(minDist < 0.0f && maxDist < 0.0f)
  125. {
  126. return maxDist;
  127. }
  128. else
  129. {
  130. return 0.0f;
  131. }
  132. }
  133. F32 testPlane(const Plane& plane, const LineSegment& ls)
  134. {
  135. const Vec4& p0 = ls.getOrigin();
  136. Vec4 p1 = ls.getOrigin() + ls.getDirection();
  137. const F32 dist0 = testPlane(plane, p0);
  138. const F32 dist1 = testPlane(plane, p1);
  139. if(dist0 > 0.0f)
  140. {
  141. if(dist1 > 0.0f)
  142. {
  143. return min(dist0, dist1);
  144. }
  145. else
  146. {
  147. return 0.0f;
  148. }
  149. }
  150. else
  151. {
  152. if(dist1 < 0.0f)
  153. {
  154. return max(dist0, dist1);
  155. }
  156. else
  157. {
  158. return 0.0f;
  159. }
  160. }
  161. }
  162. } // end namespace anki