2
0

btInternalEdgeUtility.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. #include "btInternalEdgeUtility.h"
  2. #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
  3. #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
  4. #include "BulletCollision/CollisionShapes/btTriangleShape.h"
  5. #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
  6. #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
  7. #include "LinearMath/btIDebugDraw.h"
  8. #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
  9. //#define DEBUG_INTERNAL_EDGE
  10. #ifdef DEBUG_INTERNAL_EDGE
  11. #include <stdio.h>
  12. #endif //DEBUG_INTERNAL_EDGE
  13. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  14. static btIDebugDraw* gDebugDrawer = 0;
  15. void btSetDebugDrawer(btIDebugDraw* debugDrawer)
  16. {
  17. gDebugDrawer = debugDrawer;
  18. }
  19. static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
  20. {
  21. if (gDebugDrawer)
  22. gDebugDrawer->drawLine(from, to, color);
  23. }
  24. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  25. static int btGetHash(int partId, int triangleIndex)
  26. {
  27. int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
  28. return hash;
  29. }
  30. static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
  31. {
  32. const btVector3 refAxis0 = edgeA;
  33. const btVector3 refAxis1 = normalA;
  34. const btVector3 swingAxis = normalB;
  35. btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
  36. return angle;
  37. }
  38. struct btConnectivityProcessor : public btTriangleCallback
  39. {
  40. int m_partIdA;
  41. int m_triangleIndexA;
  42. btVector3* m_triangleVerticesA;
  43. btTriangleInfoMap* m_triangleInfoMap;
  44. virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
  45. {
  46. //skip self-collisions
  47. if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
  48. return;
  49. //skip duplicates (disabled for now)
  50. //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
  51. // return;
  52. //search for shared vertices and edges
  53. int numshared = 0;
  54. int sharedVertsA[3] = {-1, -1, -1};
  55. int sharedVertsB[3] = {-1, -1, -1};
  56. ///skip degenerate triangles
  57. btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
  58. if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
  59. return;
  60. btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
  61. ///skip degenerate triangles
  62. if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
  63. return;
  64. #if 0
  65. printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n",
  66. m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
  67. m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
  68. m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
  69. printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
  70. printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n",
  71. triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
  72. triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
  73. triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
  74. #endif
  75. for (int i = 0; i < 3; i++)
  76. {
  77. for (int j = 0; j < 3; j++)
  78. {
  79. if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
  80. {
  81. sharedVertsA[numshared] = i;
  82. sharedVertsB[numshared] = j;
  83. numshared++;
  84. ///degenerate case
  85. if (numshared >= 3)
  86. return;
  87. }
  88. }
  89. ///degenerate case
  90. if (numshared >= 3)
  91. return;
  92. }
  93. switch (numshared)
  94. {
  95. case 0:
  96. {
  97. break;
  98. }
  99. case 1:
  100. {
  101. //shared vertex
  102. break;
  103. }
  104. case 2:
  105. {
  106. //shared edge
  107. //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
  108. if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
  109. {
  110. sharedVertsA[0] = 2;
  111. sharedVertsA[1] = 0;
  112. int tmp = sharedVertsB[1];
  113. sharedVertsB[1] = sharedVertsB[0];
  114. sharedVertsB[0] = tmp;
  115. }
  116. int hash = btGetHash(m_partIdA, m_triangleIndexA);
  117. btTriangleInfo* info = m_triangleInfoMap->find(hash);
  118. if (!info)
  119. {
  120. btTriangleInfo tmp;
  121. m_triangleInfoMap->insert(hash, tmp);
  122. info = m_triangleInfoMap->find(hash);
  123. }
  124. int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
  125. int otherIndexA = 3 - sumvertsA;
  126. btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
  127. btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
  128. int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
  129. btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
  130. //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
  131. btVector3 normalA;
  132. btVector3 normalB;
  133. tA.calcNormal(normalA);
  134. tB.calcNormal(normalB);
  135. edge.normalize();
  136. btVector3 edgeCrossA = edge.cross(normalA).normalize();
  137. {
  138. btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
  139. if (edgeCrossA.dot(tmp) < 0)
  140. {
  141. edgeCrossA *= -1;
  142. }
  143. }
  144. btVector3 edgeCrossB = edge.cross(normalB).normalize();
  145. {
  146. btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
  147. if (edgeCrossB.dot(tmp) < 0)
  148. {
  149. edgeCrossB *= -1;
  150. }
  151. }
  152. btScalar angle2 = 0;
  153. btScalar ang4 = 0.f;
  154. btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
  155. btScalar len2 = calculatedEdge.length2();
  156. btScalar correctedAngle(0);
  157. //btVector3 calculatedNormalB = normalA;
  158. bool isConvex = false;
  159. if (len2 < m_triangleInfoMap->m_planarEpsilon)
  160. {
  161. angle2 = 0.f;
  162. ang4 = 0.f;
  163. }
  164. else
  165. {
  166. calculatedEdge.normalize();
  167. btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
  168. calculatedNormalA.normalize();
  169. angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
  170. ang4 = SIMD_PI - angle2;
  171. btScalar dotA = normalA.dot(edgeCrossB);
  172. ///@todo: check if we need some epsilon, due to floating point imprecision
  173. isConvex = (dotA < 0.);
  174. correctedAngle = isConvex ? ang4 : -ang4;
  175. }
  176. //alternatively use
  177. //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
  178. switch (sumvertsA)
  179. {
  180. case 1:
  181. {
  182. btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
  183. btQuaternion orn(edge, -correctedAngle);
  184. btVector3 computedNormalB = quatRotate(orn, normalA);
  185. btScalar bla = computedNormalB.dot(normalB);
  186. if (bla < 0)
  187. {
  188. computedNormalB *= -1;
  189. info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
  190. }
  191. #ifdef DEBUG_INTERNAL_EDGE
  192. if ((computedNormalB - normalB).length() > 0.0001)
  193. {
  194. printf("warning: normals not identical\n");
  195. }
  196. #endif //DEBUG_INTERNAL_EDGE
  197. info->m_edgeV0V1Angle = -correctedAngle;
  198. if (isConvex)
  199. info->m_flags |= TRI_INFO_V0V1_CONVEX;
  200. break;
  201. }
  202. case 2:
  203. {
  204. btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
  205. btQuaternion orn(edge, -correctedAngle);
  206. btVector3 computedNormalB = quatRotate(orn, normalA);
  207. if (computedNormalB.dot(normalB) < 0)
  208. {
  209. computedNormalB *= -1;
  210. info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
  211. }
  212. #ifdef DEBUG_INTERNAL_EDGE
  213. if ((computedNormalB - normalB).length() > 0.0001)
  214. {
  215. printf("warning: normals not identical\n");
  216. }
  217. #endif //DEBUG_INTERNAL_EDGE
  218. info->m_edgeV2V0Angle = -correctedAngle;
  219. if (isConvex)
  220. info->m_flags |= TRI_INFO_V2V0_CONVEX;
  221. break;
  222. }
  223. case 3:
  224. {
  225. btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
  226. btQuaternion orn(edge, -correctedAngle);
  227. btVector3 computedNormalB = quatRotate(orn, normalA);
  228. if (computedNormalB.dot(normalB) < 0)
  229. {
  230. info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
  231. computedNormalB *= -1;
  232. }
  233. #ifdef DEBUG_INTERNAL_EDGE
  234. if ((computedNormalB - normalB).length() > 0.0001)
  235. {
  236. printf("warning: normals not identical\n");
  237. }
  238. #endif //DEBUG_INTERNAL_EDGE
  239. info->m_edgeV1V2Angle = -correctedAngle;
  240. if (isConvex)
  241. info->m_flags |= TRI_INFO_V1V2_CONVEX;
  242. break;
  243. }
  244. }
  245. break;
  246. }
  247. default:
  248. {
  249. // printf("warning: duplicate triangle\n");
  250. }
  251. }
  252. }
  253. };
  254. /////////////////////////////////////////////////////////
  255. /////////////////////////////////////////////////////////
  256. void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
  257. {
  258. //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
  259. if (trimeshShape->getTriangleInfoMap())
  260. return;
  261. trimeshShape->setTriangleInfoMap(triangleInfoMap);
  262. btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
  263. const btVector3& meshScaling = meshInterface->getScaling();
  264. for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
  265. {
  266. const unsigned char* vertexbase = 0;
  267. int numverts = 0;
  268. PHY_ScalarType type = PHY_INTEGER;
  269. int stride = 0;
  270. const unsigned char* indexbase = 0;
  271. int indexstride = 0;
  272. int numfaces = 0;
  273. PHY_ScalarType indicestype = PHY_INTEGER;
  274. //PHY_ScalarType indexType=0;
  275. btVector3 triangleVerts[3];
  276. meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
  277. btVector3 aabbMin, aabbMax;
  278. for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
  279. {
  280. unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
  281. for (int j = 2; j >= 0; j--)
  282. {
  283. int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
  284. if (type == PHY_FLOAT)
  285. {
  286. float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
  287. triangleVerts[j] = btVector3(
  288. graphicsbase[0] * meshScaling.getX(),
  289. graphicsbase[1] * meshScaling.getY(),
  290. graphicsbase[2] * meshScaling.getZ());
  291. }
  292. else
  293. {
  294. double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
  295. triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
  296. }
  297. }
  298. aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
  299. aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
  300. aabbMin.setMin(triangleVerts[0]);
  301. aabbMax.setMax(triangleVerts[0]);
  302. aabbMin.setMin(triangleVerts[1]);
  303. aabbMax.setMax(triangleVerts[1]);
  304. aabbMin.setMin(triangleVerts[2]);
  305. aabbMax.setMax(triangleVerts[2]);
  306. btConnectivityProcessor connectivityProcessor;
  307. connectivityProcessor.m_partIdA = partId;
  308. connectivityProcessor.m_triangleIndexA = triangleIndex;
  309. connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
  310. connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
  311. trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
  312. }
  313. }
  314. }
  315. // Given a point and a line segment (defined by two points), compute the closest point
  316. // in the line. Cap the point at the endpoints of the line segment.
  317. void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
  318. {
  319. btVector3 lineDelta = line1 - line0;
  320. // Handle degenerate lines
  321. if (lineDelta.fuzzyZero())
  322. {
  323. nearestPoint = line0;
  324. }
  325. else
  326. {
  327. btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
  328. // Clamp the point to conform to the segment's endpoints
  329. if (delta < 0)
  330. delta = 0;
  331. else if (delta > 1)
  332. delta = 1;
  333. nearestPoint = line0 + lineDelta * delta;
  334. }
  335. }
  336. bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
  337. {
  338. btVector3 tri_normal = tri_normal_org;
  339. //we only have a local triangle normal, not a local contact normal -> only normal in world space...
  340. //either compute the current angle all in local space, or all in world space
  341. btVector3 edgeCross = edge.cross(tri_normal).normalize();
  342. btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
  343. if (correctedEdgeAngle < 0)
  344. {
  345. if (curAngle < correctedEdgeAngle)
  346. {
  347. btScalar diffAngle = correctedEdgeAngle - curAngle;
  348. btQuaternion rotation(edge, diffAngle);
  349. clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
  350. return true;
  351. }
  352. }
  353. if (correctedEdgeAngle >= 0)
  354. {
  355. if (curAngle > correctedEdgeAngle)
  356. {
  357. btScalar diffAngle = correctedEdgeAngle - curAngle;
  358. btQuaternion rotation(edge, diffAngle);
  359. clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
  360. return true;
  361. }
  362. }
  363. return false;
  364. }
  365. /// Changes a btManifoldPoint collision normal to the normal from the mesh.
  366. void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
  367. {
  368. //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
  369. if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
  370. return;
  371. btBvhTriangleMeshShape* trimesh = 0;
  372. if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
  373. {
  374. trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
  375. }
  376. else
  377. {
  378. if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
  379. {
  380. trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
  381. }
  382. }
  383. if (trimesh == 0)
  384. return;
  385. btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
  386. if (!triangleInfoMapPtr)
  387. return;
  388. int hash = btGetHash(partId0, index0);
  389. btTriangleInfo* info = triangleInfoMapPtr->find(hash);
  390. if (!info)
  391. return;
  392. btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
  393. const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
  394. btVector3 v0, v1, v2;
  395. tri_shape->getVertex(0, v0);
  396. tri_shape->getVertex(1, v1);
  397. tri_shape->getVertex(2, v2);
  398. //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
  399. btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
  400. btVector3 tri_normal;
  401. tri_shape->calcNormal(tri_normal);
  402. //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
  403. btVector3 nearest;
  404. btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
  405. btVector3 contact = cp.m_localPointB;
  406. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  407. const btTransform& tr = colObj0->getWorldTransform();
  408. btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
  409. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  410. bool isNearEdge = false;
  411. int numConcaveEdgeHits = 0;
  412. int numConvexEdgeHits = 0;
  413. btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
  414. localContactNormalOnB.normalize(); //is this necessary?
  415. // Get closest edge
  416. int bestedge = -1;
  417. btScalar disttobestedge = BT_LARGE_FLOAT;
  418. //
  419. // Edge 0 -> 1
  420. if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  421. {
  422. btVector3 nearest;
  423. btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
  424. btScalar len = (contact - nearest).length();
  425. //
  426. if (len < disttobestedge)
  427. {
  428. bestedge = 0;
  429. disttobestedge = len;
  430. }
  431. }
  432. // Edge 1 -> 2
  433. if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  434. {
  435. btVector3 nearest;
  436. btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
  437. btScalar len = (contact - nearest).length();
  438. //
  439. if (len < disttobestedge)
  440. {
  441. bestedge = 1;
  442. disttobestedge = len;
  443. }
  444. }
  445. // Edge 2 -> 0
  446. if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  447. {
  448. btVector3 nearest;
  449. btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
  450. btScalar len = (contact - nearest).length();
  451. //
  452. if (len < disttobestedge)
  453. {
  454. bestedge = 2;
  455. disttobestedge = len;
  456. }
  457. }
  458. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  459. btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
  460. btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
  461. #endif
  462. if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  463. {
  464. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  465. btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
  466. #endif
  467. btScalar len = (contact - nearest).length();
  468. if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
  469. if (bestedge == 0)
  470. {
  471. btVector3 edge(v0 - v1);
  472. isNearEdge = true;
  473. if (info->m_edgeV0V1Angle == btScalar(0))
  474. {
  475. numConcaveEdgeHits++;
  476. }
  477. else
  478. {
  479. bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
  480. btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
  481. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  482. btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
  483. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  484. btVector3 nA = swapFactor * tri_normal;
  485. btQuaternion orn(edge, info->m_edgeV0V1Angle);
  486. btVector3 computedNormalB = quatRotate(orn, tri_normal);
  487. if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
  488. computedNormalB *= -1;
  489. btVector3 nB = swapFactor * computedNormalB;
  490. btScalar NdotA = localContactNormalOnB.dot(nA);
  491. btScalar NdotB = localContactNormalOnB.dot(nB);
  492. bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
  493. #ifdef DEBUG_INTERNAL_EDGE
  494. {
  495. btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
  496. }
  497. #endif //DEBUG_INTERNAL_EDGE
  498. if (backFacingNormal)
  499. {
  500. numConcaveEdgeHits++;
  501. }
  502. else
  503. {
  504. numConvexEdgeHits++;
  505. btVector3 clampedLocalNormal;
  506. bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
  507. if (isClamped)
  508. {
  509. if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
  510. {
  511. btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
  512. // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
  513. cp.m_normalWorldOnB = newNormal;
  514. // Reproject collision point along normal. (what about cp.m_distance1?)
  515. cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
  516. cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
  517. }
  518. }
  519. }
  520. }
  521. }
  522. }
  523. btNearestPointInLineSegment(contact, v1, v2, nearest);
  524. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  525. btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
  526. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  527. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  528. btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
  529. #endif
  530. if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  531. {
  532. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  533. btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
  534. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  535. btScalar len = (contact - nearest).length();
  536. if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
  537. if (bestedge == 1)
  538. {
  539. isNearEdge = true;
  540. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  541. btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
  542. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  543. btVector3 edge(v1 - v2);
  544. isNearEdge = true;
  545. if (info->m_edgeV1V2Angle == btScalar(0))
  546. {
  547. numConcaveEdgeHits++;
  548. }
  549. else
  550. {
  551. bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
  552. btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
  553. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  554. btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
  555. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  556. btVector3 nA = swapFactor * tri_normal;
  557. btQuaternion orn(edge, info->m_edgeV1V2Angle);
  558. btVector3 computedNormalB = quatRotate(orn, tri_normal);
  559. if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
  560. computedNormalB *= -1;
  561. btVector3 nB = swapFactor * computedNormalB;
  562. #ifdef DEBUG_INTERNAL_EDGE
  563. {
  564. btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
  565. }
  566. #endif //DEBUG_INTERNAL_EDGE
  567. btScalar NdotA = localContactNormalOnB.dot(nA);
  568. btScalar NdotB = localContactNormalOnB.dot(nB);
  569. bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
  570. if (backFacingNormal)
  571. {
  572. numConcaveEdgeHits++;
  573. }
  574. else
  575. {
  576. numConvexEdgeHits++;
  577. btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
  578. btVector3 clampedLocalNormal;
  579. bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
  580. if (isClamped)
  581. {
  582. if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
  583. {
  584. btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
  585. // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
  586. cp.m_normalWorldOnB = newNormal;
  587. // Reproject collision point along normal.
  588. cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
  589. cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
  590. }
  591. }
  592. }
  593. }
  594. }
  595. }
  596. btNearestPointInLineSegment(contact, v2, v0, nearest);
  597. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  598. btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
  599. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  600. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  601. btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
  602. #endif
  603. if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
  604. {
  605. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  606. btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
  607. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  608. btScalar len = (contact - nearest).length();
  609. if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
  610. if (bestedge == 2)
  611. {
  612. isNearEdge = true;
  613. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  614. btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
  615. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  616. btVector3 edge(v2 - v0);
  617. if (info->m_edgeV2V0Angle == btScalar(0))
  618. {
  619. numConcaveEdgeHits++;
  620. }
  621. else
  622. {
  623. bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
  624. btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
  625. #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
  626. btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
  627. #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
  628. btVector3 nA = swapFactor * tri_normal;
  629. btQuaternion orn(edge, info->m_edgeV2V0Angle);
  630. btVector3 computedNormalB = quatRotate(orn, tri_normal);
  631. if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
  632. computedNormalB *= -1;
  633. btVector3 nB = swapFactor * computedNormalB;
  634. #ifdef DEBUG_INTERNAL_EDGE
  635. {
  636. btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
  637. }
  638. #endif //DEBUG_INTERNAL_EDGE
  639. btScalar NdotA = localContactNormalOnB.dot(nA);
  640. btScalar NdotB = localContactNormalOnB.dot(nB);
  641. bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
  642. if (backFacingNormal)
  643. {
  644. numConcaveEdgeHits++;
  645. }
  646. else
  647. {
  648. numConvexEdgeHits++;
  649. // printf("hitting convex edge\n");
  650. btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
  651. btVector3 clampedLocalNormal;
  652. bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
  653. if (isClamped)
  654. {
  655. if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
  656. {
  657. btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
  658. // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
  659. cp.m_normalWorldOnB = newNormal;
  660. // Reproject collision point along normal.
  661. cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
  662. cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
  663. }
  664. }
  665. }
  666. }
  667. }
  668. }
  669. #ifdef DEBUG_INTERNAL_EDGE
  670. {
  671. btVector3 color(0, 1, 1);
  672. btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
  673. }
  674. #endif //DEBUG_INTERNAL_EDGE
  675. if (isNearEdge)
  676. {
  677. if (numConcaveEdgeHits > 0)
  678. {
  679. if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
  680. {
  681. //fix tri_normal so it pointing the same direction as the current local contact normal
  682. if (tri_normal.dot(localContactNormalOnB) < 0)
  683. {
  684. tri_normal *= -1;
  685. }
  686. cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
  687. }
  688. else
  689. {
  690. btVector3 newNormal = tri_normal * frontFacing;
  691. //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
  692. btScalar d = newNormal.dot(localContactNormalOnB);
  693. if (d < 0)
  694. {
  695. return;
  696. }
  697. //modify the normal to be the triangle normal (or backfacing normal)
  698. cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
  699. }
  700. // Reproject collision point along normal.
  701. cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
  702. cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
  703. }
  704. }
  705. }