consistency
This commit is contained in:
		| @@ -34,18 +34,14 @@ 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; | ||||||
|  |  | ||||||
| @@ -53,30 +49,25 @@ struct qhFace | |||||||
|  |  | ||||||
| 	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,27 +497,11 @@ 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]; | ||||||
| @@ -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(); | ||||||
| @@ -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; | ||||||
| @@ -730,8 +738,8 @@ void qhHull::MergeFaces() | |||||||
| 	{ | 	{ | ||||||
| 		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