234 lines
7.1 KiB
C++
234 lines
7.1 KiB
C++
|
|
/*
|
|
Stan Melax Convex Hull Computation
|
|
Copyright (c) 2008 Stan Melax http://www.melax.com/
|
|
|
|
This software is provided 'as-is', without any express or implied warranty.
|
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it freely,
|
|
subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
|
|
|
|
#ifndef BT_CD_HULL_H
|
|
#define BT_CD_HULL_H
|
|
|
|
#include "btVector3.h"
|
|
#include "btAlignedObjectArray.h"
|
|
|
|
typedef btAlignedObjectArray<unsigned int> TUIntArray;
|
|
|
|
class HullResult
|
|
{
|
|
public:
|
|
HullResult(void)
|
|
{
|
|
mPolygons = true;
|
|
mNumOutputVertices = 0;
|
|
mNumFaces = 0;
|
|
mNumIndices = 0;
|
|
}
|
|
bool mPolygons; // true if indices represents polygons, false indices are triangles
|
|
unsigned int mNumOutputVertices; // number of vertices in the output hull
|
|
btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
|
|
unsigned int mNumFaces; // the number of faces produced
|
|
unsigned int mNumIndices; // the total number of indices
|
|
btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
|
|
|
|
// If triangles, then indices are array indexes into the vertex list.
|
|
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
|
};
|
|
|
|
enum HullFlag
|
|
{
|
|
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
|
|
QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
|
|
QF_DEFAULT = QF_TRIANGLES
|
|
};
|
|
|
|
class HullDesc
|
|
{
|
|
public:
|
|
HullDesc(void)
|
|
{
|
|
mFlags = QF_DEFAULT;
|
|
mVcount = 0;
|
|
mVertices = 0;
|
|
mVertexStride = sizeof(btVector3);
|
|
mNormalEpsilon = 0.001f;
|
|
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
|
|
mMaxFaces = 4096;
|
|
};
|
|
|
|
HullDesc(HullFlag flag,
|
|
unsigned int vcount,
|
|
const btVector3* vertices,
|
|
unsigned int stride = sizeof(btVector3))
|
|
{
|
|
mFlags = flag;
|
|
mVcount = vcount;
|
|
mVertices = vertices;
|
|
mVertexStride = stride;
|
|
mNormalEpsilon = btScalar(0.001);
|
|
mMaxVertices = 4096;
|
|
}
|
|
|
|
bool HasHullFlag(HullFlag flag) const
|
|
{
|
|
if (mFlags & flag) return true;
|
|
return false;
|
|
}
|
|
|
|
void SetHullFlag(HullFlag flag)
|
|
{
|
|
mFlags |= flag;
|
|
}
|
|
|
|
void ClearHullFlag(HullFlag flag)
|
|
{
|
|
mFlags &= ~flag;
|
|
}
|
|
|
|
unsigned int mFlags; // flags to use when generating the convex hull.
|
|
unsigned int mVcount; // number of vertices in the input point cloud
|
|
const btVector3* mVertices; // the array of vertices.
|
|
unsigned int mVertexStride; // the stride of each vertex, in bytes.
|
|
btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
|
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
|
|
unsigned int mMaxFaces;
|
|
};
|
|
|
|
enum HullError
|
|
{
|
|
QE_OK, // success!
|
|
QE_FAIL // failed.
|
|
};
|
|
|
|
class btPlane
|
|
{
|
|
public:
|
|
btVector3 normal;
|
|
btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
|
|
btPlane(const btVector3& n, btScalar d) : normal(n), dist(d) {}
|
|
btPlane() : normal(), dist(0) {}
|
|
};
|
|
|
|
class ConvexH
|
|
{
|
|
public:
|
|
class HalfEdge
|
|
{
|
|
public:
|
|
short ea; // the other half of the edge (index into edges list)
|
|
unsigned char v; // the vertex at the start of this edge (index into vertices list)
|
|
unsigned char p; // the facet on which this edge lies (index into facets list)
|
|
HalfEdge() {}
|
|
HalfEdge(short _ea, unsigned char _v, unsigned char _p) : ea(_ea), v(_v), p(_p) {}
|
|
};
|
|
ConvexH()
|
|
{
|
|
}
|
|
~ConvexH()
|
|
{
|
|
}
|
|
btAlignedObjectArray<btVector3> vertices;
|
|
btAlignedObjectArray<HalfEdge> edges;
|
|
btAlignedObjectArray<btPlane> facets;
|
|
ConvexH(int vertices_size, int edges_size, int facets_size);
|
|
};
|
|
|
|
class int4
|
|
{
|
|
public:
|
|
int x, y, z, w;
|
|
int4(){};
|
|
int4(int _x, int _y, int _z, int _w)
|
|
{
|
|
x = _x;
|
|
y = _y;
|
|
z = _z;
|
|
w = _w;
|
|
}
|
|
const int& operator[](int i) const { return (&x)[i]; }
|
|
int& operator[](int i) { return (&x)[i]; }
|
|
};
|
|
|
|
class PHullResult
|
|
{
|
|
public:
|
|
PHullResult(void)
|
|
{
|
|
mVcount = 0;
|
|
mIndexCount = 0;
|
|
mFaceCount = 0;
|
|
mVertices = 0;
|
|
}
|
|
|
|
unsigned int mVcount;
|
|
unsigned int mIndexCount;
|
|
unsigned int mFaceCount;
|
|
btVector3* mVertices;
|
|
TUIntArray m_Indices;
|
|
};
|
|
|
|
///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
|
|
///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
|
|
class HullLibrary
|
|
{
|
|
btAlignedObjectArray<class btHullTriangle*> m_tris;
|
|
|
|
public:
|
|
btAlignedObjectArray<int> m_vertexIndexMapping;
|
|
|
|
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
|
|
HullResult& result); // contains the resulst
|
|
HullError ReleaseResult(HullResult& result); // release memory allocated for this result, we are done with it.
|
|
|
|
private:
|
|
bool ComputeHull(unsigned int vcount, const btVector3* vertices, PHullResult& result, unsigned int vlimit);
|
|
|
|
class btHullTriangle* allocateTriangle(int a, int b, int c);
|
|
void deAllocateTriangle(btHullTriangle*);
|
|
void b2bfix(btHullTriangle* s, btHullTriangle* t);
|
|
|
|
void removeb2b(btHullTriangle* s, btHullTriangle* t);
|
|
|
|
void checkit(btHullTriangle* t);
|
|
|
|
btHullTriangle* extrudable(btScalar epsilon);
|
|
|
|
int calchull(btVector3* verts, int verts_count, TUIntArray& tris_out, int& tris_count, int vlimit);
|
|
|
|
int calchullgen(btVector3* verts, int verts_count, int vlimit);
|
|
|
|
int4 FindSimplex(btVector3* verts, int verts_count, btAlignedObjectArray<int>& allow);
|
|
|
|
class ConvexH* ConvexHCrop(ConvexH& convex, const btPlane& slice);
|
|
|
|
void extrude(class btHullTriangle* t0, int v);
|
|
|
|
ConvexH* test_cube();
|
|
|
|
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
|
|
//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
|
|
//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
|
|
//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
|
|
void BringOutYourDead(const btVector3* verts, unsigned int vcount, btVector3* overts, unsigned int& ocount, unsigned int* indices, unsigned indexcount);
|
|
|
|
bool CleanupVertices(unsigned int svcount,
|
|
const btVector3* svertices,
|
|
unsigned int stride,
|
|
unsigned int& vcount, // output number of vertices
|
|
btVector3* vertices, // location to store the results.
|
|
btScalar normalepsilon,
|
|
btVector3& scale);
|
|
};
|
|
|
|
#endif //BT_CD_HULL_H
|