Reduce the number of contact points of a potential contact manifold This is based on the technique described by Dirk Gregorius in his "Contacts Creation" GDC presentation. This method will reduce the number of contact points to a maximum of 4 points (but it can be less).
| 1481 | // "Contacts Creation" GDC presentation. This method will reduce the number of |
| 1482 | // contact points to a maximum of 4 points (but it can be less). |
| 1483 | void CollisionDetectionSystem::reduceContactPoints(ContactManifoldInfo& manifold, const Transform& shape1ToWorldTransform, |
| 1484 | const Array<ContactPointInfo>& potentialContactPoints) const { |
| 1485 | |
| 1486 | assert(manifold.nbPotentialContactPoints > MAX_CONTACT_POINTS_IN_MANIFOLD); |
| 1487 | |
| 1488 | // The following algorithm only works to reduce to a maximum of 4 contact points |
| 1489 | assert(MAX_CONTACT_POINTS_IN_MANIFOLD == 4); |
| 1490 | |
| 1491 | // Array of the candidate contact points indices in the manifold. Every time that we have found a |
| 1492 | // point we want to keep, we will remove it from this array |
| 1493 | uint candidatePointsIndices[NB_MAX_CONTACT_POINTS_IN_POTENTIAL_MANIFOLD]; |
| 1494 | uint8 nbCandidatePoints = manifold.nbPotentialContactPoints; |
| 1495 | for (uint8 i=0 ; i < manifold.nbPotentialContactPoints; i++) { |
| 1496 | candidatePointsIndices[i] = manifold.potentialContactPointsIndices[i]; |
| 1497 | } |
| 1498 | |
| 1499 | int8 nbReducedPoints = 0; |
| 1500 | |
| 1501 | uint32 pointsToKeepIndices[MAX_CONTACT_POINTS_IN_MANIFOLD]; |
| 1502 | for (int8 i=0; i<MAX_CONTACT_POINTS_IN_MANIFOLD; i++) { |
| 1503 | pointsToKeepIndices[i] = 0; |
| 1504 | } |
| 1505 | |
| 1506 | // Compute the initial contact point we need to keep. |
| 1507 | // The first point we keep is always the point in a given |
| 1508 | // constant direction (in order to always have same contact points |
| 1509 | // between frames for better stability) |
| 1510 | |
| 1511 | const Transform worldToShape1Transform = shape1ToWorldTransform.getInverse(); |
| 1512 | |
| 1513 | // Compute the contact normal of the manifold (we use the first contact point) |
| 1514 | // in the local-space of the first collision shape |
| 1515 | const Vector3 contactNormalShape1Space = worldToShape1Transform.getOrientation() * potentialContactPoints[candidatePointsIndices[0]].normal; |
| 1516 | |
| 1517 | // Compute a search direction |
| 1518 | const Vector3 searchDirection(1, 1, 1); |
| 1519 | decimal maxDotProduct = DECIMAL_SMALLEST; |
| 1520 | uint32 elementIndexToKeep = 0; |
| 1521 | for (uint32 i=0; i < nbCandidatePoints; i++) { |
| 1522 | |
| 1523 | const ContactPointInfo& element = potentialContactPoints[candidatePointsIndices[i]]; |
| 1524 | decimal dotProduct = searchDirection.dot(element.localPoint1); |
| 1525 | if (dotProduct > maxDotProduct) { |
| 1526 | maxDotProduct = dotProduct; |
| 1527 | elementIndexToKeep = i; |
| 1528 | nbReducedPoints = 1; |
| 1529 | } |
| 1530 | } |
| 1531 | pointsToKeepIndices[0] = candidatePointsIndices[elementIndexToKeep]; |
| 1532 | removeItemAtInArray(candidatePointsIndices, elementIndexToKeep, nbCandidatePoints); |
| 1533 | //candidatePointsIndices.removeAt(elementIndexToKeep); |
| 1534 | assert(nbReducedPoints == 1); |
| 1535 | |
| 1536 | // Compute the second contact point we need to keep. |
| 1537 | // The second point we keep is the one farthest away from the first point. |
| 1538 | |
| 1539 | decimal maxDistance = decimal(0.0); |
| 1540 | elementIndexToKeep = 0; |
nothing calls this directly
no test coverage detected