2017-08-01 12:30:58 +00:00
/*
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 ;
}
2019-01-03 13:26:51 +00:00
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..
2017-08-01 12:30:58 +00:00
} ;
enum HullFlag
{
2019-01-03 13:26:51 +00:00
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
2017-08-01 12:30:58 +00:00
} ;
class HullDesc
{
public :
HullDesc ( void )
{
2019-01-03 13:26:51 +00:00
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 ;
2017-08-01 12:30:58 +00:00
} ;
HullDesc ( HullFlag flag ,
2019-01-03 13:26:51 +00:00
unsigned int vcount ,
const btVector3 * vertices ,
unsigned int stride = sizeof ( btVector3 ) )
2017-08-01 12:30:58 +00:00
{
2019-01-03 13:26:51 +00:00
mFlags = flag ;
mVcount = vcount ;
mVertices = vertices ;
mVertexStride = stride ;
mNormalEpsilon = btScalar ( 0.001 ) ;
mMaxVertices = 4096 ;
2017-08-01 12:30:58 +00:00
}
bool HasHullFlag ( HullFlag flag ) const
{
2019-01-03 13:26:51 +00:00
if ( mFlags & flag ) return true ;
2017-08-01 12:30:58 +00:00
return false ;
}
void SetHullFlag ( HullFlag flag )
{
2019-01-03 13:26:51 +00:00
mFlags | = flag ;
2017-08-01 12:30:58 +00:00
}
void ClearHullFlag ( HullFlag flag )
{
2019-01-03 13:26:51 +00:00
mFlags & = ~ flag ;
2017-08-01 12:30:58 +00:00
}
2019-01-03 13:26:51 +00:00
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 ;
2017-08-01 12:30:58 +00:00
} ;
enum HullError
{
2019-01-03 13:26:51 +00:00
QE_OK , // success!
QE_FAIL // failed.
2017-08-01 12:30:58 +00:00
} ;
class btPlane
{
2019-01-03 13:26:51 +00:00
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 ) { }
2017-08-01 12:30:58 +00:00
} ;
2019-01-03 13:26:51 +00:00
class ConvexH
2017-08-01 12:30:58 +00:00
{
2019-01-03 13:26:51 +00:00
public :
2017-08-01 12:30:58 +00:00
class HalfEdge
{
2019-01-03 13:26:51 +00:00
public :
2017-08-01 12:30:58 +00:00
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)
2019-01-03 13:26:51 +00:00
HalfEdge ( ) { }
HalfEdge ( short _ea , unsigned char _v , unsigned char _p ) : ea ( _ea ) , v ( _v ) , p ( _p ) { }
2017-08-01 12:30:58 +00:00
} ;
ConvexH ( )
{
}
~ ConvexH ( )
{
}
btAlignedObjectArray < btVector3 > vertices ;
btAlignedObjectArray < HalfEdge > edges ;
2019-01-03 13:26:51 +00:00
btAlignedObjectArray < btPlane > facets ;
ConvexH ( int vertices_size , int edges_size , int facets_size ) ;
2017-08-01 12:30:58 +00:00
} ;
class int4
{
public :
2019-01-03 13:26:51 +00:00
int x , y , z , w ;
2017-08-01 12:30:58 +00:00
int4 ( ) { } ;
2019-01-03 13:26:51 +00:00
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 ] ; }
2017-08-01 12:30:58 +00:00
} ;
class PHullResult
{
public :
PHullResult ( void )
{
mVcount = 0 ;
mIndexCount = 0 ;
mFaceCount = 0 ;
mVertices = 0 ;
}
unsigned int mVcount ;
unsigned int mIndexCount ;
unsigned int mFaceCount ;
2019-01-03 13:26:51 +00:00
btVector3 * mVertices ;
2017-08-01 12:30:58 +00:00
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 ;
2019-01-03 13:26:51 +00:00
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.
2017-08-01 12:30:58 +00:00
private :
2019-01-03 13:26:51 +00:00
bool ComputeHull ( unsigned int vcount , const btVector3 * vertices , PHullResult & result , unsigned int vlimit ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
class btHullTriangle * allocateTriangle ( int a , int b , int c ) ;
void deAllocateTriangle ( btHullTriangle * ) ;
void b2bfix ( btHullTriangle * s , btHullTriangle * t ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
void removeb2b ( btHullTriangle * s , btHullTriangle * t ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
void checkit ( btHullTriangle * t ) ;
2017-08-01 12:30:58 +00:00
btHullTriangle * extrudable ( btScalar epsilon ) ;
2019-01-03 13:26:51 +00:00
int calchull ( btVector3 * verts , int verts_count , TUIntArray & tris_out , int & tris_count , int vlimit ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
int calchullgen ( btVector3 * verts , int verts_count , int vlimit ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
int4 FindSimplex ( btVector3 * verts , int verts_count , btAlignedObjectArray < int > & allow ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
class ConvexH * ConvexHCrop ( ConvexH & convex , const btPlane & slice ) ;
2017-08-01 12:30:58 +00:00
2019-01-03 13:26:51 +00:00
void extrude ( class btHullTriangle * t0 , int v ) ;
2017-08-01 12:30:58 +00:00
ConvexH * test_cube ( ) ;
2019-01-03 13:26:51 +00:00
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
2017-08-01 12:30:58 +00:00
//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.
2019-01-03 13:26:51 +00:00
void BringOutYourDead ( const btVector3 * verts , unsigned int vcount , btVector3 * overts , unsigned int & ocount , unsigned int * indices , unsigned indexcount ) ;
2017-08-01 12:30:58 +00:00
bool CleanupVertices ( unsigned int svcount ,
2019-01-03 13:26:51 +00:00
const btVector3 * svertices ,
unsigned int stride ,
unsigned int & vcount , // output number of vertices
btVector3 * vertices , // location to store the results.
btScalar normalepsilon ,
btVector3 & scale ) ;
2017-08-01 12:30:58 +00:00
} ;
2019-01-03 13:26:51 +00:00
# endif //BT_CD_HULL_H