123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- #ifndef B3_REDUCE_CONTACTS_H
- #define B3_REDUCE_CONTACTS_H
- inline int b3ReduceContacts(const b3Float4* p, int nPoints, const b3Float4& nearNormal, b3Int4* contactIdx)
- {
- if (nPoints == 0)
- return 0;
- if (nPoints <= 4)
- return nPoints;
- if (nPoints > 64)
- nPoints = 64;
- b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
- {
- for (int i = 0; i < nPoints; i++)
- center += p[i];
- center /= (float)nPoints;
- }
- // sample 4 directions
- b3Float4 aVector = p[0] - center;
- b3Float4 u = b3Cross3(nearNormal, aVector);
- b3Float4 v = b3Cross3(nearNormal, u);
- u = b3FastNormalized3(u);
- v = b3FastNormalized3(v);
- //keep point with deepest penetration
- float minW = FLT_MAX;
- int minIndex = -1;
- b3Float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
- // idx, distance
- for (int ie = 0; ie < nPoints; ie++)
- {
- if (p[ie].w < minW)
- {
- minW = p[ie].w;
- minIndex = ie;
- }
- float f;
- b3Float4 r = p[ie] - center;
- f = b3Dot3F4(u, r);
- if (f < maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
- f = b3Dot3F4(-u, r);
- if (f < maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
- f = b3Dot3F4(v, r);
- if (f < maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
- f = b3Dot3F4(-v, r);
- if (f < maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
- }
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
- return 4;
- }
- #endif //B3_REDUCE_CONTACTS_H
|