simplify hulls in dual space

This commit is contained in:
Irlan 2018-05-03 21:46:45 -03:00
parent 10c01c8fcf
commit a55b621489

View File

@ -176,8 +176,102 @@ void b3QHull::Set(const b3Vec3* points, u32 count)
} }
// Create a convex hull. // Create a convex hull.
qhHull primary;
primary.Construct(ps, psCount);
// Simplify the constructed hull.
// Put the origin inside the hull.
b3Vec3 s;
s.SetZero();
for (qhVertex* v = primary.GetVertexList().head; v; v = v->next)
{
s += v->position;
}
s /= float32(primary.GetVertexList().count);
primary.Translate(-s);
// Build the dual hull
u32 dvCount = 0;
qhFace** dfs = (qhFace**)b3Alloc(primary.GetFaceList().count * sizeof(qhFace*));
b3Vec3* dvs = (b3Vec3*)b3Alloc(primary.GetFaceList().count * sizeof(b3Vec3));
for (qhFace* f = primary.GetFaceList().head; f; f = f->next)
{
b3Plane plane = f->plane;
B3_ASSERT(plane.offset > 0.0f);
b3Vec3 v = plane.normal / plane.offset;
bool unique = true;
// There's a magic portion of code lost in the island that would cluster those planes.
// While we can't find it, simply keep the face which has the largest area.
for (u32 j = 0; j < dvCount; ++j)
{
qhFace*& df = dfs[j];
b3Vec3& dv = dvs[j];
const float32 kTol = 0.1f;
if (b3DistanceSquared(v, dv) <= kTol)
{
if (f->area > df->area)
{
df = f;
dv = v;
}
unique = false;
break;
}
}
if (unique)
{
dfs[dvCount] = f;
dvs[dvCount] = v;
++dvCount;
}
}
b3Free(dfs);
qhHull dual;
dual.Construct(dvs, dvCount);
b3Free(dvs);
// Recover the simplified hull in primary space.
u32 pvCount = 0;
b3Vec3* pvs = (b3Vec3*)b3Alloc(dual.GetFaceList().count * sizeof(b3Vec3));
for (qhFace* f = dual.GetFaceList().head; f; f = f->next)
{
b3Plane plane = f->plane;
B3_ASSERT(plane.offset > 0.0f);
b3Vec3 v = plane.normal / plane.offset;
bool unique = true;
for (u32 j = 0; j < pvCount; ++j)
{
if (b3DistanceSquared(v, pvs[j]) <= B3_LINEAR_SLOP * B3_LINEAR_SLOP)
{
unique = false;
break;
}
}
if (unique)
{
pvs[pvCount++] = v;
}
}
qhHull hull; qhHull hull;
hull.Construct(ps, psCount); hull.Construct(pvs, pvCount);
b3Free(pvs);
// Translate the hull back to the origin
hull.Translate(s);
if (hull.GetVertexList().count > B3_MAX_HULL_VERTICES) if (hull.GetVertexList().count > B3_MAX_HULL_VERTICES)
{ {