consistency

This commit is contained in:
Irlan
2018-04-27 02:38:38 -03:00
parent c3b55d3323
commit bd490d7925
3 changed files with 95 additions and 76 deletions

View File

@ -34,49 +34,40 @@ struct qhList
struct qhHalfEdge; struct qhHalfEdge;
struct qhVertex; struct qhVertex;
enum qhFaceMark
{
e_visible,
e_invisible
};
struct qhFace struct qhFace
{ {
enum State
{
e_invisible,
e_visible,
e_unknown,
e_deleted
};
qhFace* freeNext;
qhFace* prev; qhFace* prev;
qhFace* next; qhFace* next;
qhHalfEdge* edge; qhHalfEdge* edge;
qhList<qhVertex> conflictList; qhList<qhVertex> conflictList;
State state;
b3Vec3 center; b3Vec3 center;
b3Plane plane; b3Plane plane;
qhFaceMark mark;
u32 GetVertexCount() const; u32 GetVertexCount() const;
u32 GetEdgeCount() const; u32 GetEdgeCount() const;
qhHalfEdge* FindHalfEdge(const qhVertex* v1, const qhVertex* v2) const; qhHalfEdge* FindHalfEdge(const qhVertex* v1, const qhVertex* v2) const;
void ComputeCenterAndPlane(); void ComputeCenterAndPlane();
//
qhFace* freeNext;
bool active;
}; };
struct qhHalfEdge struct qhHalfEdge
{ {
enum State
{
e_used,
e_deleted
};
State state;
qhHalfEdge* freeNext;
qhVertex* tail; qhVertex* tail;
qhHalfEdge* prev; qhHalfEdge* prev;
@ -84,18 +75,24 @@ struct qhHalfEdge
qhHalfEdge* twin; qhHalfEdge* twin;
qhFace* face; qhFace* face;
//
qhHalfEdge* freeNext;
bool active;
}; };
struct qhVertex struct qhVertex
{ {
qhVertex* freeNext;
qhVertex* prev; qhVertex* prev;
qhVertex* next; qhVertex* next;
b3Vec3 position; b3Vec3 position;
qhFace* conflictFace; qhFace* conflictFace;
//
qhVertex* freeNext;
bool active;
}; };
// A convex hull builder. // A convex hull builder.
@ -128,6 +125,7 @@ public:
private: private:
bool BuildInitialHull(const b3Vec3* vertices, u32 count); bool BuildInitialHull(const b3Vec3* vertices, u32 count);
qhFace* AddFace(qhVertex* v1, qhVertex* v2, qhVertex* v3); qhFace* AddFace(qhVertex* v1, qhVertex* v2, qhVertex* v3);
qhFace* RemoveFace(qhFace* face);
qhVertex* FindEyeVertex() const; qhVertex* FindEyeVertex() const;
void AddVertex(qhVertex* v); void AddVertex(qhVertex* v);

View File

@ -162,12 +162,16 @@ inline const qhList<qhFace>& qhHull::GetFaceList() const
inline qhVertex* qhHull::AllocateVertex() inline qhVertex* qhHull::AllocateVertex()
{ {
qhVertex* v = m_freeVertices; qhVertex* v = m_freeVertices;
B3_ASSERT(v->active == false);
v->active = true;
m_freeVertices = v->freeNext; m_freeVertices = v->freeNext;
return v; return v;
} }
inline void qhHull::FreeVertex(qhVertex* v) inline void qhHull::FreeVertex(qhVertex* v)
{ {
//B3_ASSERT(v->active == true);
v->active = false;
v->freeNext = m_freeVertices; v->freeNext = m_freeVertices;
m_freeVertices = v; m_freeVertices = v;
} }
@ -175,14 +179,16 @@ inline void qhHull::FreeVertex(qhVertex* v)
inline qhHalfEdge* qhHull::AllocateEdge() inline qhHalfEdge* qhHull::AllocateEdge()
{ {
qhHalfEdge* e = m_freeEdges; qhHalfEdge* e = m_freeEdges;
e->state = qhHalfEdge::e_used; B3_ASSERT(e->active == false);
e->active = true;
m_freeEdges = e->freeNext; m_freeEdges = e->freeNext;
return e; return e;
} }
inline void qhHull::FreeEdge(qhHalfEdge* e) inline void qhHull::FreeEdge(qhHalfEdge* e)
{ {
e->state = qhHalfEdge::e_deleted; //B3_ASSERT(e->active == true);
e->active = false;
e->freeNext = m_freeEdges; e->freeNext = m_freeEdges;
m_freeEdges = e; m_freeEdges = e;
} }
@ -190,13 +196,16 @@ inline void qhHull::FreeEdge(qhHalfEdge* e)
inline qhFace* qhHull::AllocateFace() inline qhFace* qhHull::AllocateFace()
{ {
qhFace* f = m_freeFaces; qhFace* f = m_freeFaces;
B3_ASSERT(f->active == false);
f->active = true;
m_freeFaces = f->freeNext; m_freeFaces = f->freeNext;
return f; return f;
} }
inline void qhHull::FreeFace(qhFace* f) inline void qhHull::FreeFace(qhFace* f)
{ {
f->state = qhFace::e_deleted; //B3_ASSERT(f->active == true);
f->active = false;
f->freeNext = m_freeFaces; f->freeNext = m_freeFaces;
m_freeFaces = f; m_freeFaces = f;
} }

View File

@ -352,17 +352,17 @@ void qhHull::AddVertex(qhVertex* eye)
void qhHull::FindHorizon(qhVertex* eye) void qhHull::FindHorizon(qhVertex* eye)
{ {
// Classify faces // Mark faces
for (qhFace* face = m_faceList.head; face != NULL; face = face->next) for (qhFace* face = m_faceList.head; face != NULL; face = face->next)
{ {
float32 d = b3Distance(eye->position, face->plane); float32 d = b3Distance(eye->position, face->plane);
if (d > m_tolerance) if (d > m_tolerance)
{ {
face->state = qhFace::e_visible; face->mark = qhFaceMark::e_visible;
} }
else else
{ {
face->state = qhFace::e_invisible; face->mark = qhFaceMark::e_invisible;
} }
} }
@ -370,7 +370,7 @@ void qhHull::FindHorizon(qhVertex* eye)
m_horizonCount = 0; m_horizonCount = 0;
for (qhFace* face = m_faceList.head; face != NULL; face = face->next) for (qhFace* face = m_faceList.head; face != NULL; face = face->next)
{ {
if (face->state == qhFace::e_invisible) if (face->mark == qhFaceMark::e_invisible)
{ {
continue; continue;
} }
@ -382,7 +382,7 @@ void qhHull::FindHorizon(qhVertex* eye)
qhHalfEdge* twin = edge->twin; qhHalfEdge* twin = edge->twin;
qhFace* other = twin->face; qhFace* other = twin->face;
if (other->state == qhFace::e_invisible) if (other->mark == qhFaceMark::e_invisible)
{ {
m_horizon[m_horizonCount++] = edge; m_horizon[m_horizonCount++] = edge;
} }
@ -453,16 +453,14 @@ void qhHull::AddNewFaces(qhVertex* eye)
while (f) while (f)
{ {
// Invisible faces are maintained. // Invisible faces are maintained.
if (f->state == qhFace::e_invisible) if (f->mark == qhFaceMark::e_invisible)
{ {
f = f->next; f = f->next;
continue; continue;
} }
// Remove the face // Move the orphaned vertices into the new faces
// Also remove internal points
// Assign orphaned vertices to the new faces
// Also discard internal points
qhVertex* v = f->conflictList.head; qhVertex* v = f->conflictList.head;
while (v) while (v)
{ {
@ -499,37 +497,21 @@ void qhHull::AddNewFaces(qhVertex* eye)
} }
} }
// Remove face half-edges // Remove the face
qhHalfEdge* e = f->edge; f = RemoveFace(f);
do
{
if (e->twin)
{
e->twin = NULL;
}
qhHalfEdge* e0 = e;
e = e->next;
FreeEdge(e0);
} while (e != f->edge);
// Remove face
qhFace* f0 = f;
f = m_faceList.Remove(f);
FreeFace(f0);
} }
// Connect the created faces with the remaining faces in the hull // Add the new faces to the hull
for (u32 i = 0; i < m_newFaceCount; ++i) for (u32 i = 0; i < m_newFaceCount; ++i)
{ {
qhFace* face = m_newFaces[i]; qhFace* face = m_newFaces[i];
qhHalfEdge* begin = face->edge; qhHalfEdge* begin = face->edge;
qhHalfEdge* edge = begin; qhHalfEdge* edge = begin;
do do
{ {
qhVertex* v1 = edge->tail; qhVertex* v1 = edge->tail;
qhHalfEdge* next = edge->next; qhHalfEdge* next = edge->next;
qhVertex* v2 = next->tail; qhVertex* v2 = next->tail;
@ -602,13 +584,40 @@ qhFace* qhHull::AddFace(qhVertex* v1, qhVertex* v2, qhVertex* v3)
face->edge = e1; face->edge = e1;
face->center = (v1->position + v2->position + v3->position) / 3.0f; face->center = (v1->position + v2->position + v3->position) / 3.0f;
face->plane = b3Plane(v1->position, v2->position, v3->position); face->plane = b3Plane(v1->position, v2->position, v3->position);
face->state = qhFace::e_invisible;
m_faceList.PushFront(face); m_faceList.PushFront(face);
return face; return face;
} }
qhFace* qhHull::RemoveFace(qhFace* face)
{
// Remove half-edges
qhHalfEdge* e = face->edge;
do
{
qhHalfEdge* twin = e->twin;
// Remove half-edge and its twin if twin face does not exist
if (twin->face == NULL || twin->face == e->face)
{
e->twin = NULL;
FreeEdge(twin);
qhHalfEdge* e0 = e;
e = e->next;
FreeEdge(e0);
}
} while (e != face->edge);
// Remove face
qhFace* nextFace = m_faceList.Remove(face);
FreeFace(face);
return nextFace;
}
qhFace* qhHull::AddNewFace(qhVertex* v1, qhVertex* v2, qhVertex* v3) qhFace* qhHull::AddNewFace(qhVertex* v1, qhVertex* v2, qhVertex* v3)
{ {
qhFace* face = AllocateFace(); qhFace* face = AllocateFace();
@ -626,7 +635,7 @@ qhFace* qhHull::AddNewFace(qhVertex* v1, qhVertex* v2, qhVertex* v3)
qhHalfEdge* e3 = AllocateEdge(); qhHalfEdge* e3 = AllocateEdge();
e3->face = face; e3->face = face;
e3->twin = NULL; e3->twin = NULL;
e3->tail = v3; e3->tail = v3;
e1->prev = e3; e1->prev = e3;
e1->next = e2; e1->next = e2;
@ -640,7 +649,6 @@ qhFace* qhHull::AddNewFace(qhVertex* v1, qhVertex* v2, qhVertex* v3)
face->edge = e1; face->edge = e1;
face->center = (v1->position + v2->position + v3->position) / 3.0f; face->center = (v1->position + v2->position + v3->position) / 3.0f;
face->plane = b3Plane(v1->position, v2->position, v3->position); face->plane = b3Plane(v1->position, v2->position, v3->position);
face->state = qhFace::e_invisible;
face->prev = NULL; face->prev = NULL;
face->next = NULL; face->next = NULL;
@ -729,9 +737,9 @@ void qhHull::MergeFaces()
for (u32 i = 0; i < m_newFaceCount; ++i) for (u32 i = 0; i < m_newFaceCount; ++i)
{ {
qhFace* face = m_newFaces[i]; qhFace* face = m_newFaces[i];
// Was the face merged? // Was the face deleted due to merging?
if (face->state == qhFace::e_deleted) if (face->active == false)
{ {
continue; continue;
} }
@ -743,9 +751,13 @@ void qhHull::MergeFaces()
void qhHull::Validate(const qhHalfEdge* edge) const void qhHull::Validate(const qhHalfEdge* edge) const
{ {
B3_ASSERT(edge->active == true);
const qhHalfEdge* twin = edge->twin; const qhHalfEdge* twin = edge->twin;
B3_ASSERT(twin->twin == edge); B3_ASSERT(twin->twin == edge);
//B3_ASSERT(edge->tail->active == true);
b3Vec3 A = edge->tail->position; b3Vec3 A = edge->tail->position;
b3Vec3 B = twin->tail->position; b3Vec3 B = twin->tail->position;
B3_ASSERT(b3DistanceSquared(A, B) > B3_EPSILON * B3_EPSILON); B3_ASSERT(b3DistanceSquared(A, B) > B3_EPSILON * B3_EPSILON);
@ -766,8 +778,6 @@ void qhHull::Validate(const qhFace* face) const
const qhHalfEdge* edge = begin; const qhHalfEdge* edge = begin;
do do
{ {
B3_ASSERT(edge->state != qhHalfEdge::e_deleted);
B3_ASSERT(edge->face == face); B3_ASSERT(edge->face == face);
qhHalfEdge* twin = edge->twin; qhHalfEdge* twin = edge->twin;
@ -784,23 +794,24 @@ void qhHull::Validate() const
{ {
for (qhFace* face = m_faceList.head; face != NULL; face = face->next) for (qhFace* face = m_faceList.head; face != NULL; face = face->next)
{ {
B3_ASSERT(face->state != face->e_deleted); B3_ASSERT(face->active == true);
for (qhVertex* vertex = face->conflictList.head; vertex != NULL; vertex = vertex->next)
{
B3_ASSERT(vertex->active == true);
}
Validate(face); Validate(face);
} }
} }
void qhHull::Draw() const void qhHull::Draw() const
{ {
b3StackArray<b3Vec3, 256> polygon; for (qhFace* face = m_faceList.head; face != NULL; face = face->next)
qhFace* face = m_faceList.head;
while (face)
{ {
b3StackArray<b3Vec3, 256> polygon;
polygon.Resize(0); polygon.Resize(0);
b3Vec3 c = face->center;
b3Vec3 n = face->plane.normal;
const qhHalfEdge* begin = face->edge; const qhHalfEdge* begin = face->edge;
const qhHalfEdge* edge = begin; const qhHalfEdge* edge = begin;
do do
@ -809,6 +820,9 @@ void qhHull::Draw() const
edge = edge->next; edge = edge->next;
} while (edge != begin); } while (edge != begin);
b3Vec3 c = face->center;
b3Vec3 n = face->plane.normal;
b3Draw_draw->DrawSolidPolygon(n, polygon.Begin(), polygon.Count(), b3Color(1.0f, 1.0f, 1.0f, 0.5f)); b3Draw_draw->DrawSolidPolygon(n, polygon.Begin(), polygon.Count(), b3Color(1.0f, 1.0f, 1.0f, 0.5f));
qhVertex* v = face->conflictList.head; qhVertex* v = face->conflictList.head;
@ -820,7 +834,5 @@ void qhHull::Draw() const
} }
b3Draw_draw->DrawSegment(c, c + n, b3Color(1.0f, 1.0f, 1.0f)); b3Draw_draw->DrawSegment(c, c + n, b3Color(1.0f, 1.0f, 1.0f));
face = face->next;
} }
} }