2
0

b3ContactConvexConvexSAT.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #ifndef B3_CONTACT_CONVEX_CONVEX_SAT_H
  2. #define B3_CONTACT_CONVEX_CONVEX_SAT_H
  3. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
  4. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h"
  5. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h"
  6. #define B3_MAX_VERTS 1024
  7. inline b3Float4 b3Lerp3(const b3Float4& a, const b3Float4& b, float t)
  8. {
  9. return b3MakeVector3(a.x + (b.x - a.x) * t,
  10. a.y + (b.y - a.y) * t,
  11. a.z + (b.z - a.z) * t,
  12. 0.f);
  13. }
  14. // Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
  15. inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS, float planeEqWS, b3Float4* ppVtxOut)
  16. {
  17. int ve;
  18. float ds, de;
  19. int numVertsOut = 0;
  20. if (numVertsIn < 2)
  21. return 0;
  22. b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
  23. b3Float4 endVertex = pVtxIn[0];
  24. ds = b3Dot3F4(planeNormalWS, firstVertex) + planeEqWS;
  25. for (ve = 0; ve < numVertsIn; ve++)
  26. {
  27. endVertex = pVtxIn[ve];
  28. de = b3Dot3F4(planeNormalWS, endVertex) + planeEqWS;
  29. if (ds < 0)
  30. {
  31. if (de < 0)
  32. {
  33. // Start < 0, end < 0, so output endVertex
  34. ppVtxOut[numVertsOut++] = endVertex;
  35. }
  36. else
  37. {
  38. // Start < 0, end >= 0, so output intersection
  39. ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
  40. }
  41. }
  42. else
  43. {
  44. if (de < 0)
  45. {
  46. // Start >= 0, end < 0 so output intersection and end
  47. ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
  48. ppVtxOut[numVertsOut++] = endVertex;
  49. }
  50. }
  51. firstVertex = endVertex;
  52. ds = de;
  53. }
  54. return numVertsOut;
  55. }
  56. inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
  57. const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
  58. b3Float4* worldVertsB2, int capacityWorldVertsB2,
  59. const float minDist, float maxDist,
  60. const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
  61. //const b3Float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
  62. b3Float4* contactsOut,
  63. int contactCapacity)
  64. {
  65. int numContactsOut = 0;
  66. b3Float4* pVtxIn = worldVertsB1;
  67. b3Float4* pVtxOut = worldVertsB2;
  68. int numVertsIn = numWorldVertsB1;
  69. int numVertsOut = 0;
  70. int closestFaceA = -1;
  71. {
  72. float dmin = FLT_MAX;
  73. for (int face = 0; face < hullA->m_numFaces; face++)
  74. {
  75. const b3Float4 Normal = b3MakeVector3(
  76. facesA[hullA->m_faceOffset + face].m_plane.x,
  77. facesA[hullA->m_faceOffset + face].m_plane.y,
  78. facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
  79. const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
  80. float d = b3Dot3F4(faceANormalWS, separatingNormal);
  81. if (d < dmin)
  82. {
  83. dmin = d;
  84. closestFaceA = face;
  85. }
  86. }
  87. }
  88. if (closestFaceA < 0)
  89. return numContactsOut;
  90. b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
  91. // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
  92. //int numContacts = numWorldVertsB1;
  93. int numVerticesA = polyA.m_numIndices;
  94. for (int e0 = 0; e0 < numVerticesA; e0++)
  95. {
  96. const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
  97. const b3Float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
  98. const b3Float4 edge0 = a - b;
  99. const b3Float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
  100. b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
  101. b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
  102. b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0, worldPlaneAnormal1);
  103. b3Float4 worldA1 = b3TransformPoint(a, posA, ornA);
  104. float planeEqWS1 = -b3Dot3F4(worldA1, planeNormalWS1);
  105. b3Float4 planeNormalWS = planeNormalWS1;
  106. float planeEqWS = planeEqWS1;
  107. //clip face
  108. //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
  109. numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
  110. //btSwap(pVtxIn,pVtxOut);
  111. b3Float4* tmp = pVtxOut;
  112. pVtxOut = pVtxIn;
  113. pVtxIn = tmp;
  114. numVertsIn = numVertsOut;
  115. numVertsOut = 0;
  116. }
  117. // only keep points that are behind the witness face
  118. {
  119. b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
  120. float localPlaneEq = polyA.m_plane.w;
  121. b3Float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
  122. float planeEqWS = localPlaneEq - b3Dot3F4(planeNormalWS, posA);
  123. for (int i = 0; i < numVertsIn; i++)
  124. {
  125. float depth = b3Dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
  126. if (depth <= minDist)
  127. {
  128. depth = minDist;
  129. }
  130. if (numContactsOut < contactCapacity)
  131. {
  132. if (depth <= maxDist)
  133. {
  134. b3Float4 pointInWorld = pVtxIn[i];
  135. //resultOut.addContactPoint(separatingNormal,point,depth);
  136. contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
  137. //printf("depth=%f\n",depth);
  138. }
  139. }
  140. else
  141. {
  142. b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
  143. }
  144. }
  145. }
  146. return numContactsOut;
  147. }
  148. inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
  149. const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
  150. const b3Float4& posA, const b3Quaternion& ornA, const b3Float4& posB, const b3Quaternion& ornB,
  151. b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
  152. const float minDist, float maxDist,
  153. const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
  154. const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
  155. b3Float4* contactsOut,
  156. int contactCapacity)
  157. {
  158. int numContactsOut = 0;
  159. int numWorldVertsB1 = 0;
  160. B3_PROFILE("clipHullAgainstHull");
  161. //float curMaxDist=maxDist;
  162. int closestFaceB = -1;
  163. float dmax = -FLT_MAX;
  164. {
  165. //B3_PROFILE("closestFaceB");
  166. if (hullB.m_numFaces != 1)
  167. {
  168. //printf("wtf\n");
  169. }
  170. static bool once = true;
  171. //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
  172. for (int face = 0; face < hullB.m_numFaces; face++)
  173. {
  174. #ifdef BT_DEBUG_SAT_FACE
  175. if (once)
  176. printf("face %d\n", face);
  177. const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
  178. if (once)
  179. {
  180. for (int i = 0; i < faceB->m_numIndices; i++)
  181. {
  182. b3Float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
  183. printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
  184. }
  185. }
  186. #endif //BT_DEBUG_SAT_FACE \
  187. //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
  188. {
  189. const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
  190. facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
  191. const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
  192. #ifdef BT_DEBUG_SAT_FACE
  193. if (once)
  194. printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
  195. #endif
  196. float d = b3Dot3F4(WorldNormal, separatingNormal);
  197. if (d > dmax)
  198. {
  199. dmax = d;
  200. closestFaceB = face;
  201. }
  202. }
  203. }
  204. once = false;
  205. }
  206. b3Assert(closestFaceB >= 0);
  207. {
  208. //B3_PROFILE("worldVertsB1");
  209. const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
  210. const int numVertices = polyB.m_numIndices;
  211. for (int e0 = 0; e0 < numVertices; e0++)
  212. {
  213. const b3Float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
  214. worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
  215. }
  216. }
  217. if (closestFaceB >= 0)
  218. {
  219. //B3_PROFILE("clipFaceAgainstHull");
  220. numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
  221. posA, ornA,
  222. worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
  223. verticesA, facesA, indicesA,
  224. contactsOut, contactCapacity);
  225. }
  226. return numContactsOut;
  227. }
  228. inline int b3ClipHullHullSingle(
  229. int bodyIndexA, int bodyIndexB,
  230. const b3Float4& posA,
  231. const b3Quaternion& ornA,
  232. const b3Float4& posB,
  233. const b3Quaternion& ornB,
  234. int collidableIndexA, int collidableIndexB,
  235. const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
  236. b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
  237. int& nContacts,
  238. const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
  239. const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
  240. const b3AlignedObjectArray<b3Vector3>& verticesA,
  241. const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
  242. const b3AlignedObjectArray<b3GpuFace>& facesA,
  243. const b3AlignedObjectArray<int>& indicesA,
  244. const b3AlignedObjectArray<b3Vector3>& verticesB,
  245. const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
  246. const b3AlignedObjectArray<b3GpuFace>& facesB,
  247. const b3AlignedObjectArray<int>& indicesB,
  248. const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
  249. const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
  250. const b3Vector3& sepNormalWorldSpace,
  251. int maxContactCapacity)
  252. {
  253. int contactIndex = -1;
  254. b3ConvexPolyhedronData hullA, hullB;
  255. b3Collidable colA = hostCollidablesA[collidableIndexA];
  256. hullA = hostConvexDataA[colA.m_shapeIndex];
  257. //printf("numvertsA = %d\n",hullA.m_numVertices);
  258. b3Collidable colB = hostCollidablesB[collidableIndexB];
  259. hullB = hostConvexDataB[colB.m_shapeIndex];
  260. //printf("numvertsB = %d\n",hullB.m_numVertices);
  261. b3Float4 contactsOut[B3_MAX_VERTS];
  262. int localContactCapacity = B3_MAX_VERTS;
  263. #ifdef _WIN32
  264. b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
  265. b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
  266. #endif
  267. {
  268. b3Float4 worldVertsB1[B3_MAX_VERTS];
  269. b3Float4 worldVertsB2[B3_MAX_VERTS];
  270. int capacityWorldVerts = B3_MAX_VERTS;
  271. b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
  272. int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
  273. int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
  274. b3Scalar minDist = -1;
  275. b3Scalar maxDist = 0.;
  276. b3Transform trA, trB;
  277. {
  278. //B3_PROFILE("b3TransformPoint computation");
  279. //trA.setIdentity();
  280. trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
  281. trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
  282. //trB.setIdentity();
  283. trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
  284. trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
  285. }
  286. b3Quaternion trAorn = trA.getRotation();
  287. b3Quaternion trBorn = trB.getRotation();
  288. int numContactsOut = b3ClipHullAgainstHull(hostNormal,
  289. hostConvexDataA.at(shapeA),
  290. hostConvexDataB.at(shapeB),
  291. (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
  292. (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
  293. worldVertsB1, worldVertsB2, capacityWorldVerts,
  294. minDist, maxDist,
  295. verticesA, facesA, indicesA,
  296. verticesB, facesB, indicesB,
  297. contactsOut, localContactCapacity);
  298. if (numContactsOut > 0)
  299. {
  300. B3_PROFILE("overlap");
  301. b3Float4 normalOnSurfaceB = (b3Float4&)hostNormal;
  302. // b3Float4 centerOut;
  303. b3Int4 contactIdx;
  304. contactIdx.x = 0;
  305. contactIdx.y = 1;
  306. contactIdx.z = 2;
  307. contactIdx.w = 3;
  308. int numPoints = 0;
  309. {
  310. B3_PROFILE("extractManifold");
  311. numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
  312. }
  313. b3Assert(numPoints);
  314. if (nContacts < maxContactCapacity)
  315. {
  316. contactIndex = nContacts;
  317. globalContactOut->expand();
  318. b3Contact4Data& contact = globalContactOut->at(nContacts);
  319. contact.m_batchIdx = 0; //i;
  320. contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
  321. contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
  322. contact.m_frictionCoeffCmp = 45874;
  323. contact.m_restituitionCoeffCmp = 0;
  324. // float distance = 0.f;
  325. for (int p = 0; p < numPoints; p++)
  326. {
  327. contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]]; //check if it is actually on B
  328. contact.m_worldNormalOnB = normalOnSurfaceB;
  329. }
  330. //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
  331. contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
  332. nContacts++;
  333. }
  334. else
  335. {
  336. b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
  337. }
  338. }
  339. }
  340. return contactIndex;
  341. }
  342. inline int b3ContactConvexConvexSAT(
  343. int pairIndex,
  344. int bodyIndexA, int bodyIndexB,
  345. int collidableIndexA, int collidableIndexB,
  346. const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
  347. const b3AlignedObjectArray<b3Collidable>& collidables,
  348. const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
  349. const b3AlignedObjectArray<b3Float4>& convexVertices,
  350. const b3AlignedObjectArray<b3Float4>& uniqueEdges,
  351. const b3AlignedObjectArray<int>& convexIndices,
  352. const b3AlignedObjectArray<b3GpuFace>& faces,
  353. b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
  354. int& nGlobalContactsOut,
  355. int maxContactCapacity)
  356. {
  357. int contactIndex = -1;
  358. b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
  359. b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
  360. b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
  361. b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
  362. b3ConvexPolyhedronData hullA, hullB;
  363. b3Float4 sepNormalWorldSpace;
  364. b3Collidable colA = collidables[collidableIndexA];
  365. hullA = convexShapes[colA.m_shapeIndex];
  366. //printf("numvertsA = %d\n",hullA.m_numVertices);
  367. b3Collidable colB = collidables[collidableIndexB];
  368. hullB = convexShapes[colB.m_shapeIndex];
  369. //printf("numvertsB = %d\n",hullB.m_numVertices);
  370. #ifdef _WIN32
  371. b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
  372. b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
  373. #endif
  374. bool foundSepAxis = b3FindSeparatingAxis(hullA, hullB,
  375. posA,
  376. ornA,
  377. posB,
  378. ornB,
  379. convexVertices, uniqueEdges, faces, convexIndices,
  380. convexVertices, uniqueEdges, faces, convexIndices,
  381. sepNormalWorldSpace);
  382. if (foundSepAxis)
  383. {
  384. contactIndex = b3ClipHullHullSingle(
  385. bodyIndexA, bodyIndexB,
  386. posA, ornA,
  387. posB, ornB,
  388. collidableIndexA, collidableIndexB,
  389. &rigidBodies,
  390. &globalContactsOut,
  391. nGlobalContactsOut,
  392. convexShapes,
  393. convexShapes,
  394. convexVertices,
  395. uniqueEdges,
  396. faces,
  397. convexIndices,
  398. convexVertices,
  399. uniqueEdges,
  400. faces,
  401. convexIndices,
  402. collidables,
  403. collidables,
  404. sepNormalWorldSpace,
  405. maxContactCapacity);
  406. }
  407. return contactIndex;
  408. }
  409. #endif //B3_CONTACT_CONVEX_CONVEX_SAT_H