consistency
This commit is contained in:
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user