allow toggling convex hull simplification at run-time in order to expected convex hull creation work
This commit is contained in:
parent
df304a5bb8
commit
569a555bde
@ -44,7 +44,9 @@ struct b3QHull : public b3Hull
|
|||||||
|
|
||||||
// Create a convex hull from an array of points.
|
// Create a convex hull from an array of points.
|
||||||
// If the creation has failed then this convex hull is not modified.
|
// If the creation has failed then this convex hull is not modified.
|
||||||
void Set(const b3Vec3* points, u32 count);
|
// Use the flag simplify to tell the convex hull creation code to simplify the convex hull after
|
||||||
|
// construction.
|
||||||
|
void Set(const b3Vec3* points, u32 count, bool simplify = true);
|
||||||
|
|
||||||
// Set this hull as a cylinder located at the origin.
|
// Set this hull as a cylinder located at the origin.
|
||||||
void SetAsCylinder(float32 radius = 1.0f, float32 height = 1.0f);
|
void SetAsCylinder(float32 radius = 1.0f, float32 height = 1.0f);
|
||||||
|
@ -21,10 +21,6 @@
|
|||||||
|
|
||||||
#define B3_NULL_HULL_FEATURE 0xFF
|
#define B3_NULL_HULL_FEATURE 0xFF
|
||||||
|
|
||||||
// Enables or disables convex hull simplification.
|
|
||||||
// This can speed up collision detection and stability significantly.
|
|
||||||
#define B3_SIMPLIFY_HULL 1
|
|
||||||
|
|
||||||
// Used to map pointers to indices
|
// Used to map pointers to indices
|
||||||
// If more performance is required then a use hash-map
|
// If more performance is required then a use hash-map
|
||||||
template<class T, u32 N>
|
template<class T, u32 N>
|
||||||
@ -142,13 +138,13 @@ static b3Vec3 b3ComputeCentroid(b3QHull* hull)
|
|||||||
return centroid;
|
return centroid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3QHull::Set(const b3Vec3* points, u32 count)
|
void b3QHull::Set(const b3Vec3* points, u32 count, bool simplify)
|
||||||
{
|
{
|
||||||
B3_ASSERT(count >= 4);
|
B3_ASSERT(count >= 4);
|
||||||
|
|
||||||
// Copy points into local buffer, perform welding.
|
// Copy points into local buffer, perform welding.
|
||||||
u32 psCount = 0;
|
u32 psCount = 0;
|
||||||
b3Vec3* ps = (b3Vec3*) b3Alloc(count * sizeof(b3Vec3));
|
b3Vec3* ps = (b3Vec3*)b3Alloc(count * sizeof(b3Vec3));
|
||||||
for (u32 i = 0; i < count; ++i)
|
for (u32 i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
b3Vec3 p = points[i];
|
b3Vec3 p = points[i];
|
||||||
@ -176,131 +172,129 @@ void b3QHull::Set(const b3Vec3* points, u32 count)
|
|||||||
b3Free(ps);
|
b3Free(ps);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a convex hull.
|
// Create a convex hull.
|
||||||
|
qhHull hull;
|
||||||
|
|
||||||
#if B3_SIMPLIFY_HULL == 1
|
if (simplify == true)
|
||||||
|
|
||||||
qhHull primary;
|
|
||||||
primary.Construct(ps, psCount);
|
|
||||||
b3Free(ps);
|
|
||||||
|
|
||||||
// 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;
|
qhHull primary;
|
||||||
}
|
primary.Construct(ps, psCount);
|
||||||
s /= float32(primary.GetVertexList().count);
|
b3Free(ps);
|
||||||
|
|
||||||
primary.Translate(-s);
|
// Simplify the constructed hull.
|
||||||
|
|
||||||
// Build the dual hull
|
// Put the origin inside the hull.
|
||||||
u32 dvCount = 0;
|
b3Vec3 s;
|
||||||
qhFace** dfs = (qhFace**)b3Alloc(primary.GetFaceList().count * sizeof(qhFace*));
|
s.SetZero();
|
||||||
b3Vec3* dvs = (b3Vec3*)b3Alloc(primary.GetFaceList().count * sizeof(b3Vec3));
|
for (qhVertex* v = primary.GetVertexList().head; v; v = v->next)
|
||||||
|
|
||||||
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;
|
|
||||||
b3Vec3 vn = plane.normal;
|
|
||||||
|
|
||||||
bool unique = true;
|
|
||||||
|
|
||||||
for (u32 j = 0; j < dvCount; ++j)
|
|
||||||
{
|
{
|
||||||
qhFace*& df = dfs[j];
|
s += v->position;
|
||||||
b3Vec3& dv = dvs[j];
|
}
|
||||||
b3Vec3 dvn = b3Normalize(dv);
|
s /= float32(primary.GetVertexList().count);
|
||||||
|
|
||||||
// ~45 degrees
|
primary.Translate(-s);
|
||||||
const float32 kTol = 0.7f;
|
|
||||||
|
// Build the dual hull
|
||||||
if (b3Dot(vn, dvn) > kTol)
|
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;
|
||||||
|
b3Vec3 vn = plane.normal;
|
||||||
|
|
||||||
|
bool unique = true;
|
||||||
|
|
||||||
|
for (u32 j = 0; j < dvCount; ++j)
|
||||||
{
|
{
|
||||||
if (f->area > df->area)
|
qhFace*& df = dfs[j];
|
||||||
|
b3Vec3& dv = dvs[j];
|
||||||
|
b3Vec3 dvn = b3Normalize(dv);
|
||||||
|
|
||||||
|
// ~45 degrees
|
||||||
|
const float32 kTol = 0.7f;
|
||||||
|
|
||||||
|
if (b3Dot(vn, dvn) > kTol)
|
||||||
{
|
{
|
||||||
df = f;
|
if (f->area > df->area)
|
||||||
dv = v;
|
{
|
||||||
|
df = f;
|
||||||
|
dv = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (unique)
|
if (unique)
|
||||||
{
|
|
||||||
dfs[dvCount] = f;
|
|
||||||
dvs[dvCount] = v;
|
|
||||||
++dvCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Free(dfs);
|
|
||||||
|
|
||||||
if (dvCount < 4)
|
|
||||||
{
|
|
||||||
b3Free(dvs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
dfs[dvCount] = f;
|
||||||
break;
|
dvs[dvCount] = v;
|
||||||
|
++dvCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unique)
|
b3Free(dfs);
|
||||||
|
|
||||||
|
if (dvCount < 4)
|
||||||
{
|
{
|
||||||
pvs[pvCount++] = v;
|
b3Free(dvs);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pvCount < 4)
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvCount < 4)
|
||||||
|
{
|
||||||
|
b3Free(pvs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hull.Construct(pvs, pvCount);
|
||||||
b3Free(pvs);
|
b3Free(pvs);
|
||||||
return;
|
|
||||||
|
// Translate the hull back to the origin
|
||||||
|
hull.Translate(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hull.Construct(ps, psCount);
|
||||||
|
b3Free(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
qhHull hull;
|
|
||||||
hull.Construct(pvs, pvCount);
|
|
||||||
b3Free(pvs);
|
|
||||||
|
|
||||||
// Translate the hull back to the origin
|
|
||||||
hull.Translate(s);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
qhHull hull;
|
|
||||||
hull.Construct(ps, psCount);
|
|
||||||
b3Free(ps);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (hull.GetVertexList().count > B3_MAX_HULL_VERTICES)
|
if (hull.GetVertexList().count > B3_MAX_HULL_VERTICES)
|
||||||
{
|
{
|
||||||
// Vertex excess
|
// Vertex excess
|
||||||
@ -464,7 +458,7 @@ void b3QHull::SetAsCylinder(float32 radius, float32 height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set
|
// Set
|
||||||
Set(vs, count);
|
Set(vs, count, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3QHull::SetAsCone(float32 radius, float32 height)
|
void b3QHull::SetAsCone(float32 radius, float32 height)
|
||||||
@ -499,5 +493,5 @@ void b3QHull::SetAsCone(float32 radius, float32 height)
|
|||||||
vs[count++].Set(0.0f, height, 0.0f);
|
vs[count++].Set(0.0f, height, 0.0f);
|
||||||
|
|
||||||
// Set
|
// Set
|
||||||
Set(vs, count);
|
Set(vs, count, false);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user