erase dep, constexpr, cleanup

This commit is contained in:
Irlan 2018-04-20 19:22:20 -03:00
parent 43f59409de
commit 63f034535e
3 changed files with 74 additions and 62 deletions

View File

@ -58,8 +58,8 @@ struct qhFace
b3Vec3 center; b3Vec3 center;
b3Plane plane; b3Plane plane;
u32 VertexCount() const; u32 GetVertexCount() const;
u32 EdgeCount() const; u32 GetEdgeCount() const;
qhHalfEdge* FindTwin(const qhVertex* tail, const qhVertex* head) const; qhHalfEdge* FindTwin(const qhVertex* tail, const qhVertex* head) const;
void ComputeCenterAndPlane(); void ComputeCenterAndPlane();
}; };
@ -89,12 +89,8 @@ struct qhVertex
qhFace* conflictFace; qhFace* conflictFace;
}; };
// Given a number of points return the required memory size in bytes for constructing the // A convex hull builder.
// convex hull of those points. Use this function before allocating the memory buffer passed // Given a list of points constructs its convex hull.
// as argument to Construct.
u32 qhGetMemorySize(u32 V);
// A convex hull builder. Given a list of points constructs its convex hull.
// The output convex hull might contain polygonal faces and not only triangles. // The output convex hull might contain polygonal faces and not only triangles.
// Coplanar face merging is necessary for stable physics simulation. // Coplanar face merging is necessary for stable physics simulation.
class qhHull class qhHull
@ -102,18 +98,23 @@ class qhHull
public: public:
qhHull(); qhHull();
~qhHull(); ~qhHull();
// Entry point of qhHull. // Construct this hull given a memory buffer and an array of points.
// Construct this hull given a memory buffer and a list of points. // Use qhGetBufferCapacity to get the buffer capacity from the point array size.
// Use qhGetMemorySize to see how many free bytes should be available in the buffer. void Construct(void* buffer, const b3Vec3* vertices, u32 vertexCount);
void Construct(void* memory, const b3Array<b3Vec3>& vertices);
// Get the list of faces in this hull.
const qhList<qhFace>& GetFaceList() const;
// Get the number of iterations this algorithm ran. // Get the number of iterations this algorithm ran.
u32 GetIterations() const; u32 GetIterations() const;
// Get the list of faces in this convex hull.
const qhList<qhFace>& GetFaceList() const;
// Get the number of unique edges in this convex hull.
// u32 GetEdgeCount() const;
// Get the number of unique vertices in this convex hull.
// u32 GetVertexCount() const;
// Validate this hull. // Validate this hull.
void Validate() const; void Validate() const;
void Validate(const qhFace* face) const; void Validate(const qhFace* face) const;
@ -122,7 +123,7 @@ public:
// Draw this hull. // Draw this hull.
void Draw() const; void Draw() const;
private: private:
bool BuildInitialHull(const b3Array<b3Vec3>& vertices); bool BuildInitialHull(const b3Vec3* vertices, u32 count);
qhVertex* NextVertex(); qhVertex* NextVertex();
@ -146,13 +147,13 @@ private:
// Coplanarity tolerance // Coplanarity tolerance
float32 m_tolerance; float32 m_tolerance;
// Number of Quickhull iterations
u32 m_iteration;
// List of faces // List of faces
qhList<qhFace> m_faceList; qhList<qhFace> m_faceList;
// Number of Quickhull iterations
u32 m_iteration;
// Memory // Memory
qhVertex* AllocateVertex(); qhVertex* AllocateVertex();
void FreeVertex(qhVertex* p); void FreeVertex(qhVertex* p);

View File

@ -1,5 +1,7 @@
// qhHull.h // qhHull.h
// Lists
template<class T> template<class T>
inline void qhList<T>::PushFront(T* link) inline void qhList<T>::PushFront(T* link)
{ {
@ -38,7 +40,9 @@ inline T* qhList<T>::Remove(T* link)
return next; return next;
} }
inline u32 qhFace::VertexCount() const // qhFace
inline u32 qhFace::GetVertexCount() const
{ {
u32 count = 0; u32 count = 0;
qhHalfEdge* e = edge; qhHalfEdge* e = edge;
@ -50,7 +54,7 @@ inline u32 qhFace::VertexCount() const
return count; return count;
} }
inline u32 qhFace::EdgeCount() const inline u32 qhFace::GetEdgeCount() const
{ {
u32 count = 0; u32 count = 0;
qhHalfEdge* e = edge; qhHalfEdge* e = edge;
@ -81,7 +85,7 @@ inline qhHalfEdge* qhFace::FindTwin(const qhVertex* tail, const qhVertex* head)
return NULL; return NULL;
} }
inline b3Vec3 b3Newell(const b3Vec3& a, const b3Vec3& b) static inline b3Vec3 b3Newell(const b3Vec3& a, const b3Vec3& b)
{ {
return b3Vec3((a.y - b.y) * (a.z + b.z), (a.z - b.z) * (a.x + b.x), (a.x - b.x) * (a.y + b.y)); return b3Vec3((a.y - b.y) * (a.z + b.z), (a.z - b.z) * (a.x + b.x), (a.x - b.x) * (a.y + b.y));
} }
@ -116,29 +120,21 @@ inline void qhFace::ComputeCenterAndPlane()
center = c; center = c;
} }
inline qhHalfEdge* qhHull::FindTwin(const qhVertex* tail, const qhVertex* head) const // qhHull
{
qhFace* face = m_faceList.head;
while (face)
{
qhHalfEdge* e = face->FindTwin(tail, head);
if (e)
{
return e;
}
face = face->next;
}
return NULL;
}
inline u32 qhGetMemorySize(u32 V) // Given a number of points return the required memory size in
// bytes for constructing the convex hull of those points.
// This function uses constant expression (C++11). Therefore, you can evaluate
// its value at compile-time. That is particularly usefull when you want to
// create a stack buffer from a constant number of vertices.
// Due to the constexpr specifier, this function is automatically inlined.
constexpr u32 qhGetBufferCapacity(u32 pointCount)
{ {
u32 V = pointCount;
u32 E = 3 * V - 6; u32 E = 3 * V - 6;
u32 HE = 2 * E; u32 HE = 2 * E;
u32 F = 2 * V - 4; u32 F = 2 * V - 4;
// V - E + F = 2
HE *= 2; HE *= 2;
F *= 2; F *= 2;
@ -149,16 +145,16 @@ inline u32 qhGetMemorySize(u32 V)
return size; return size;
} }
inline const qhList<qhFace>& qhHull::GetFaceList() const
{
return m_faceList;
}
inline u32 qhHull::GetIterations() const inline u32 qhHull::GetIterations() const
{ {
return m_iteration; return m_iteration;
} }
inline const qhList<qhFace>& qhHull::GetFaceList() const
{
return m_faceList;
}
inline qhVertex* qhHull::AllocateVertex() inline qhVertex* qhHull::AllocateVertex()
{ {
qhVertex* v = m_freeVertices; qhVertex* v = m_freeVertices;
@ -197,4 +193,19 @@ inline void qhHull::FreeFace(qhFace* f)
f->state = qhFace::e_deleted; f->state = qhFace::e_deleted;
f->freeNext = m_freeFaces; f->freeNext = m_freeFaces;
m_freeFaces = f; m_freeFaces = f;
}
inline qhHalfEdge* qhHull::FindTwin(const qhVertex* tail, const qhVertex* head) const
{
qhFace* face = m_faceList.head;
while (face)
{
qhHalfEdge* e = face->FindTwin(tail, head);
if (e)
{
return e;
}
face = face->next;
}
return NULL;
} }

View File

@ -20,7 +20,7 @@
#include <bounce/common/template/stack.h> #include <bounce/common/template/stack.h>
#include <bounce/common/draw.h> #include <bounce/common/draw.h>
static float32 qhFindAABB(u32 iMin[3], u32 iMax[3], const b3Array<b3Vec3>& vertices) static float32 qhFindAABB(u32 iMin[3], u32 iMax[3], const b3Vec3* vertices, u32 count)
{ {
b3Vec3 min(B3_MAX_FLOAT, B3_MAX_FLOAT, B3_MAX_FLOAT); b3Vec3 min(B3_MAX_FLOAT, B3_MAX_FLOAT, B3_MAX_FLOAT);
iMin[0] = 0; iMin[0] = 0;
@ -32,21 +32,21 @@ static float32 qhFindAABB(u32 iMin[3], u32 iMax[3], const b3Array<b3Vec3>& verti
iMax[1] = 0; iMax[1] = 0;
iMax[2] = 0; iMax[2] = 0;
for (u32 i = 0; i < vertices.Count(); ++i) for (u32 i = 0; i < count; ++i)
{ {
b3Vec3 p = vertices[i]; b3Vec3 v = vertices[i];
for (u32 j = 0; j < 3; ++j) for (u32 j = 0; j < 3; ++j)
{ {
if (p[j] < min[j]) if (v[j] < min[j])
{ {
min[j] = p[j]; min[j] = v[j];
iMin[j] = i; iMin[j] = i;
} }
if (p[j] > max[j]) if (v[j] > max[j])
{ {
max[j] = p[j]; max[j] = v[j];
iMax[j] = i; iMax[j] = i;
} }
} }
@ -63,11 +63,11 @@ qhHull::~qhHull()
{ {
} }
void qhHull::Construct(void* memory, const b3Array<b3Vec3>& vs) void qhHull::Construct(void* memory, const b3Vec3* vs, u32 count)
{ {
// Euler's formula // Euler's formula
// V - E + F = 2 // V - E + F = 2
u32 V = vs.Count(); u32 V = count;
u32 E = 3 * V - 6; u32 E = 3 * V - 6;
u32 HE = 2 * E; u32 HE = 2 * E;
u32 F = 2 * V - 4; u32 F = 2 * V - 4;
@ -103,7 +103,7 @@ void qhHull::Construct(void* memory, const b3Array<b3Vec3>& vs)
m_faceList.count = 0; m_faceList.count = 0;
m_iteration = 0; m_iteration = 0;
if (!BuildInitialHull(vs)) if (!BuildInitialHull(vs, count))
{ {
return; return;
} }
@ -119,9 +119,9 @@ void qhHull::Construct(void* memory, const b3Array<b3Vec3>& vs)
} }
} }
bool qhHull::BuildInitialHull(const b3Array<b3Vec3>& vertices) bool qhHull::BuildInitialHull(const b3Vec3* vertices, u32 vertexCount)
{ {
if (vertices.Count() < 4) if (vertexCount < 4)
{ {
B3_ASSERT(false); B3_ASSERT(false);
return false; return false;
@ -134,7 +134,7 @@ bool qhHull::BuildInitialHull(const b3Array<b3Vec3>& vertices)
// canonical axes. // canonical axes.
// Store tolerance for coplanarity checks. // Store tolerance for coplanarity checks.
u32 aabbMin[3], aabbMax[3]; u32 aabbMin[3], aabbMax[3];
m_tolerance = qhFindAABB(aabbMin, aabbMax, vertices); m_tolerance = qhFindAABB(aabbMin, aabbMax, vertices, vertexCount);
// Find the longest segment. // Find the longest segment.
float32 d0 = 0.0f; float32 d0 = 0.0f;
@ -173,7 +173,7 @@ bool qhHull::BuildInitialHull(const b3Array<b3Vec3>& vertices)
// Find the triangle which has the largest area. // Find the triangle which has the largest area.
float32 a0 = 0.0f; float32 a0 = 0.0f;
for (u32 i = 0; i < vertices.Count(); ++i) for (u32 i = 0; i < vertexCount; ++i)
{ {
if (i == i1 || i == i2) if (i == i1 || i == i2)
{ {
@ -214,7 +214,7 @@ bool qhHull::BuildInitialHull(const b3Array<b3Vec3>& vertices)
// Find the furthest point from the triangle plane. // Find the furthest point from the triangle plane.
float32 d0 = 0.0f; float32 d0 = 0.0f;
for (u32 i = 0; i < vertices.Count(); ++i) for (u32 i = 0; i < vertexCount; ++i)
{ {
if (i == i1 || i == i2 || i == i3) if (i == i1 || i == i2 || i == i3)
{ {
@ -280,7 +280,7 @@ bool qhHull::BuildInitialHull(const b3Array<b3Vec3>& vertices)
// Add remaining points to the hull. // Add remaining points to the hull.
// Assign closest face plane to each of them. // Assign closest face plane to each of them.
for (u32 i = 0; i < vertices.Count(); ++i) for (u32 i = 0; i < vertexCount; ++i)
{ {
if (i == i1 || i == i2 || i == i3 || i == i4) if (i == i1 || i == i2 || i == i3 || i == i4)
{ {