b3FindSeparatingAxis.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #ifndef B3_FIND_SEPARATING_AXIS_H
  2. #define B3_FIND_SEPARATING_AXIS_H
  3. inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
  4. {
  5. min = FLT_MAX;
  6. max = -FLT_MAX;
  7. int numVerts = hull.m_numVertices;
  8. const b3Float4 localDir = b3QuatRotate(orn.inverse(), dir);
  9. b3Scalar offset = b3Dot3F4(pos, dir);
  10. for (int i = 0; i < numVerts; i++)
  11. {
  12. //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
  13. //b3Scalar dp = pt.dot(dir);
  14. //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
  15. b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset + i], localDir);
  16. //b3Assert(dp==dpL);
  17. if (dp < min) min = dp;
  18. if (dp > max) max = dp;
  19. }
  20. if (min > max)
  21. {
  22. b3Scalar tmp = min;
  23. min = max;
  24. max = tmp;
  25. }
  26. min += offset;
  27. max += offset;
  28. }
  29. inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
  30. const b3Float4& posA, const b3Quaternion& ornA,
  31. const b3Float4& posB, const b3Quaternion& ornB,
  32. const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
  33. {
  34. b3Scalar Min0, Max0;
  35. b3Scalar Min1, Max1;
  36. b3ProjectAxis(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
  37. b3ProjectAxis(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
  38. if (Max0 < Min1 || Max1 < Min0)
  39. return false;
  40. b3Scalar d0 = Max0 - Min1;
  41. b3Assert(d0 >= 0.0f);
  42. b3Scalar d1 = Max1 - Min0;
  43. b3Assert(d1 >= 0.0f);
  44. depth = d0 < d1 ? d0 : d1;
  45. return true;
  46. }
  47. inline bool b3FindSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
  48. const b3Float4& posA1,
  49. const b3Quaternion& ornA,
  50. const b3Float4& posB1,
  51. const b3Quaternion& ornB,
  52. const b3AlignedObjectArray<b3Vector3>& verticesA,
  53. const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
  54. const b3AlignedObjectArray<b3GpuFace>& facesA,
  55. const b3AlignedObjectArray<int>& indicesA,
  56. const b3AlignedObjectArray<b3Vector3>& verticesB,
  57. const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
  58. const b3AlignedObjectArray<b3GpuFace>& facesB,
  59. const b3AlignedObjectArray<int>& indicesB,
  60. b3Vector3& sep)
  61. {
  62. B3_PROFILE("findSeparatingAxis");
  63. b3Float4 posA = posA1;
  64. posA.w = 0.f;
  65. b3Float4 posB = posB1;
  66. posB.w = 0.f;
  67. //#ifdef TEST_INTERNAL_OBJECTS
  68. b3Float4 c0local = (b3Float4&)hullA.m_localCenter;
  69. b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
  70. b3Float4 c1local = (b3Float4&)hullB.m_localCenter;
  71. b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
  72. const b3Float4 deltaC2 = c0 - c1;
  73. //#endif
  74. b3Scalar dmin = FLT_MAX;
  75. int curPlaneTests = 0;
  76. int numFacesA = hullA.m_numFaces;
  77. // Test normals from hullA
  78. for (int i = 0; i < numFacesA; i++)
  79. {
  80. const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset + i].m_plane;
  81. b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
  82. if (b3Dot3F4(deltaC2, faceANormalWS) < 0)
  83. faceANormalWS *= -1.f;
  84. curPlaneTests++;
  85. #ifdef TEST_INTERNAL_OBJECTS
  86. gExpectedNbTests++;
  87. if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
  88. continue;
  89. gActualNbTests++;
  90. #endif
  91. b3Scalar d;
  92. if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
  93. return false;
  94. if (d < dmin)
  95. {
  96. dmin = d;
  97. sep = (b3Vector3&)faceANormalWS;
  98. }
  99. }
  100. int numFacesB = hullB.m_numFaces;
  101. // Test normals from hullB
  102. for (int i = 0; i < numFacesB; i++)
  103. {
  104. b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset + i].m_plane;
  105. b3Float4 WorldNormal = b3QuatRotate(ornB, normal);
  106. if (b3Dot3F4(deltaC2, WorldNormal) < 0)
  107. {
  108. WorldNormal *= -1.f;
  109. }
  110. curPlaneTests++;
  111. #ifdef TEST_INTERNAL_OBJECTS
  112. gExpectedNbTests++;
  113. if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
  114. continue;
  115. gActualNbTests++;
  116. #endif
  117. b3Scalar d;
  118. if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
  119. return false;
  120. if (d < dmin)
  121. {
  122. dmin = d;
  123. sep = (b3Vector3&)WorldNormal;
  124. }
  125. }
  126. // b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
  127. int curEdgeEdge = 0;
  128. // Test edges
  129. for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
  130. {
  131. const b3Float4& edge0 = (b3Float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
  132. b3Float4 edge0World = b3QuatRotate(ornA, (b3Float4&)edge0);
  133. for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
  134. {
  135. const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
  136. b3Float4 edge1World = b3QuatRotate(ornB, (b3Float4&)edge1);
  137. b3Float4 crossje = b3Cross3(edge0World, edge1World);
  138. curEdgeEdge++;
  139. if (!b3IsAlmostZero((b3Vector3&)crossje))
  140. {
  141. crossje = b3FastNormalized3(crossje);
  142. if (b3Dot3F4(deltaC2, crossje) < 0)
  143. crossje *= -1.f;
  144. #ifdef TEST_INTERNAL_OBJECTS
  145. gExpectedNbTests++;
  146. if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
  147. continue;
  148. gActualNbTests++;
  149. #endif
  150. b3Scalar dist;
  151. if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
  152. return false;
  153. if (dist < dmin)
  154. {
  155. dmin = dist;
  156. sep = (b3Vector3&)crossje;
  157. }
  158. }
  159. }
  160. }
  161. if ((b3Dot3F4(-deltaC2, (b3Float4&)sep)) > 0.0f)
  162. sep = -sep;
  163. return true;
  164. }
  165. #endif //B3_FIND_SEPARATING_AXIS_H