asmithers wrote:I can build an optimal sphere quickly, but most clothing doesn't really conform to this kind of test well. most cloth is planar majority of the time. AABB too is not optimal in world space.. I think I need to use an arbitary BB. That is Convex hull of 6 planes.
Hi Andi! I probably wouldn't try to compute a convex hull (even if just 6-sided) in real-time. Instead, considering your points are mostly planar, I would try an OBB aligned with the eigenvectors of the covariance matrix of the point cloud (the covariance matrix computed using principal component analysis).
so anyone have some suggestions that would allow me to build this extremely rapidly as I update the constraints ?
An OBB as per above would be O(n) which you really can't do better than, in that you need to verify that all points lie inside the computed bounding volume.
Better OBB-fitting approaches are available but they're (much) more expensive. For example, picking one OBB axis to correspond to the eigenvector with the largest matching eigenvalue and then doing rotating calipers for the remaining two axes is O(n^2).
oh and if anyone wants a nice fast point capsule test, I can post this algorithm too.
How does it compare to:
Code: Select all
// Tests if point p lies inside capsule c
bool TestPtCapsule(Point p, Capsule c)
{
Vector ab = c.b ? c.a;
// Compute t-value for projection of p onto ab
float t = Dot(p ? c.a, ab) / Dot(ab, ab);
// If outside segment, clamp t to the closest endpoint
t = Min(Max(t, 0.0f), 1.0f);
// Compute projected position from the clamped t
Point d = c.a + t * ab;
// Inside capsule if distance is less-equal than capsule radius
Vector pd = d - p;
return Dot(pd, pd) <= c.r * c.r;
}
Or, if you're concerned about the cost of division in the two subcases where it's not needed:
Code: Select all
// Tests if point p lies inside capsule c
bool TestPtCapsule(Point p, Capsule c)
{
Vector ab = c.b ? c.a, ap = p ? c.a, bp = p ? c.b;
float e = Dot(ap, ab), r2 = c.r * c.r;
// Handle cases where p projects outside ab
if (e <= 0.0f)
return Dot(ap, ap) <= r2;
float f = Dot(ab, ab);
if (e >= f)
return Dot(bp, bp) <= r2;
// Handle case where p projects onto ab
return Dot(ap, ap) ? e * e / f <= r2;
}