diff --git a/Extras/ConvexDecomposition/ConvexDecomposition.cpp b/Extras/ConvexDecomposition/ConvexDecomposition.cpp index 601f02186..969dbfcf2 100644 --- a/Extras/ConvexDecomposition/ConvexDecomposition.cpp +++ b/Extras/ConvexDecomposition/ConvexDecomposition.cpp @@ -56,14 +56,10 @@ #define SHOW_MESH 0 #define MAKE_MESH 1 -static unsigned int MAXDEPTH=8; -static float CONCAVE_PERCENT=1.0f; -static float MERGE_PERCENT=2.0f; - using namespace ConvexDecomposition; -typedef std::vector< unsigned int > UintVector; + namespace ConvexDecomposition { @@ -104,7 +100,7 @@ void addTri(VertexLookup vl,UintVector &list,const Vector3d &p1,const Vector3d & } -void doConvexDecomposition(unsigned int vcount, +void calcConvexDecomposition(unsigned int vcount, const float *vertices, unsigned int tcount, const unsigned int *indices, @@ -351,7 +347,7 @@ void doConvexDecomposition(unsigned int vcount, const float *vertices = Vl_getVertices(vfront); unsigned int tcount = ifront.size()/3; - doConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1); + calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1); } @@ -365,7 +361,7 @@ void doConvexDecomposition(unsigned int vcount, const float *vertices = Vl_getVertices(vback); unsigned int tcount = iback.size()/3; - doConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1); + calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1); } @@ -375,398 +371,6 @@ void doConvexDecomposition(unsigned int vcount, } } -class CHull -{ -public: - CHull(const ConvexResult &result) - { - mResult = new ConvexResult(result); - mVolume = computeMeshVolume( result.mHullVertices, result.mHullTcount, result.mHullIndices ); - - mDiagonal = getBoundingRegion( result.mHullVcount, result.mHullVertices, sizeof(float)*3, mMin, mMax ); - - float dx = mMax[0] - mMin[0]; - float dy = mMax[1] - mMin[1]; - float dz = mMax[2] - mMin[2]; - - dx*=0.1f; // inflate 1/10th on each edge - dy*=0.1f; // inflate 1/10th on each edge - dz*=0.1f; // inflate 1/10th on each edge - - mMin[0]-=dx; - mMin[1]-=dy; - mMin[2]-=dz; - - mMax[0]+=dx; - mMax[1]+=dy; - mMax[2]+=dz; - - - } - - ~CHull(void) - { - delete mResult; - } - - bool overlap(const CHull &h) const - { - return overlapAABB(mMin,mMax, h.mMin, h.mMax ); - } - - float mMin[3]; - float mMax[3]; - float mVolume; - float mDiagonal; // long edge.. - ConvexResult *mResult; -}; - -// Usage: std::sort( list.begin(), list.end(), StringSortRef() ); -class CHullSort -{ - public: - - bool operator()(const CHull *a,const CHull *b) const - { - return a->mVolume < b->mVolume; - } -}; - - -typedef std::vector< CHull * > CHullVector; - - -class ConvexBuilder : public ConvexDecompInterface -{ -public: - ConvexBuilder(ConvexDecompInterface *callback) - { - mCallback = callback; - }; - - ~ConvexBuilder(void) - { - CHullVector::iterator i; - for (i=mChulls.begin(); i!=mChulls.end(); ++i) - { - CHull *cr = (*i); - delete cr; - } - } - - bool isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3, - unsigned int ci1,unsigned int ci2,unsigned int ci3) - { - unsigned int dcount = 0; - - assert( i1 != i2 && i1 != i3 && i2 != i3 ); - assert( ci1 != ci2 && ci1 != ci3 && ci2 != ci3 ); - - if ( i1 == ci1 || i1 == ci2 || i1 == ci3 ) dcount++; - if ( i2 == ci1 || i2 == ci2 || i2 == ci3 ) dcount++; - if ( i3 == ci1 || i3 == ci2 || i3 == ci3 ) dcount++; - - return dcount == 3; - } - - void getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices) - { - unsigned int *src = cr.mHullIndices; - - for (unsigned int i=0; ioverlap(*b) ) return 0; // if their AABB's (with a little slop) don't overlap, then return. - - CHull *ret = 0; - - // ok..we are going to combine both meshes into a single mesh - // and then we are going to compute the concavity... - - VertexLookup vc = Vl_createVertexLookup(); - - UintVector indices; - - getMesh( *a->mResult, vc, indices ); - getMesh( *b->mResult, vc, indices ); - - unsigned int vcount = Vl_getVcount(vc); - const float *vertices = Vl_getVertices(vc); - unsigned int tcount = indices.size()/3; - unsigned int *idx = &indices[0]; - - HullResult hresult; - HullLibrary hl; - HullDesc desc; - - desc.SetHullFlag(QF_TRIANGLES); - - desc.mVcount = vcount; - desc.mVertices = vertices; - desc.mVertexStride = sizeof(float)*3; - - HullError hret = hl.CreateConvexHull(desc,hresult); - - if ( hret == QE_OK ) - { - - float combineVolume = computeMeshVolume( hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices ); - float sumVolume = a->mVolume + b->mVolume; - - float percent = (sumVolume*100) / combineVolume; - if ( percent >= (100.0f-MERGE_PERCENT) ) - { - ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices); - ret = new CHull(cr); - } - } - - - Vl_releaseVertexLookup(vc); - - return ret; - } - - bool combineHulls(void) - { - - bool combine = false; - - sortChulls(mChulls); // sort the convex hulls, largest volume to least... - - CHullVector output; // the output hulls... - - - CHullVector::iterator i; - - for (i=mChulls.begin(); i!=mChulls.end() && !combine; ++i) - { - CHull *cr = (*i); - - CHullVector::iterator j; - for (j=mChulls.begin(); j!=mChulls.end(); ++j) - { - CHull *match = (*j); - - if ( cr != match ) // don't try to merge a hull with itself, that be stoopid - { - - CHull *merge = canMerge(cr,match); // if we can merge these two.... - - if ( merge ) - { - - output.push_back(merge); - - - ++i; - while ( i != mChulls.end() ) - { - CHull *cr = (*i); - if ( cr != match ) - { - output.push_back(cr); - } - i++; - } - - delete cr; - delete match; - combine = true; - break; - } - } - } - - if ( combine ) - { - break; - } - else - { - output.push_back(cr); - } - - } - - if ( combine ) - { - mChulls.clear(); - mChulls = output; - output.clear(); - } - - - return combine; - } - - unsigned int process(const DecompDesc &desc) - { - - unsigned int ret = 0; - - MAXDEPTH = desc.mDepth; - CONCAVE_PERCENT = desc.mCpercent; - MERGE_PERCENT = desc.mPpercent; - - - doConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices,this,0,0); - - - while ( combineHulls() ); // keep combinging hulls until I can't combine any more... - - CHullVector::iterator i; - for (i=mChulls.begin(); i!=mChulls.end(); ++i) - { - CHull *cr = (*i); - - // before we hand it back to the application, we need to regenerate the hull based on the - // limits given by the user. - - const ConvexResult &c = *cr->mResult; // the high resolution hull... - - HullResult result; - HullLibrary hl; - HullDesc hdesc; - - hdesc.SetHullFlag(QF_TRIANGLES); - - hdesc.mVcount = c.mHullVcount; - hdesc.mVertices = c.mHullVertices; - hdesc.mVertexStride = sizeof(float)*3; - hdesc.mMaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output - - if ( desc.mSkinWidth > 0 ) - { - hdesc.mSkinWidth = desc.mSkinWidth; - hdesc.SetHullFlag(QF_SKIN_WIDTH); // do skin width computation. - } - - HullError ret = hl.CreateConvexHull(hdesc,result); - - if ( ret == QE_OK ) - { - ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices); - - r.mHullVolume = computeMeshVolume( result.mOutputVertices, result.mNumFaces, result.mIndices ); // the volume of the hull. - - // compute the best fit OBB - computeBestFitOBB( result.mNumOutputVertices, result.mOutputVertices, sizeof(float)*3, r.mOBBSides, r.mOBBTransform ); - - r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] *r.mOBBSides[2]; // compute the OBB volume. - - fm_getTranslation( r.mOBBTransform, r.mOBBCenter ); // get the translation component of the 4x4 matrix. - - fm_matrixToQuat( r.mOBBTransform, r.mOBBOrientation ); // extract the orientation as a quaternion. - - r.mSphereRadius = computeBoundingSphere( result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter ); - r.mSphereVolume = fm_sphereVolume( r.mSphereRadius ); - - - mCallback->ConvexDecompResult(r); - } - - - delete cr; - } - - ret = mChulls.size(); - - mChulls.clear(); - - return ret; - } - - - virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) - { - mCallback->ConvexDebugTri(p1,p2,p3,color); - } - - virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) - { - mCallback->ConvexDebugOBB(sides,matrix,color); - } - virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color) - { - mCallback->ConvexDebugPoint(p,dist,color); - } - - virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) - { - mCallback->ConvexDebugBound(bmin,bmax,color); - } - - virtual void ConvexDecompResult(ConvexResult &result) - { - CHull *ch = new CHull(result); - mChulls.push_back(ch); - } - - void sortChulls(CHullVector &hulls) - { - std::sort( hulls.begin(), hulls.end(), CHullSort() ); - } - -CHullVector mChulls; -ConvexDecompInterface *mCallback; - -}; - -unsigned int performConvexDecomposition(const DecompDesc &desc) -{ - unsigned int ret = 0; - - if ( desc.mCallback ) - { - ConvexBuilder cb(desc.mCallback); - - ret = cb.process(desc); - } - - return ret; -} diff --git a/Extras/ConvexDecomposition/ConvexDecomposition.h b/Extras/ConvexDecomposition/ConvexDecomposition.h index 4c9cea32e..5bfe308f7 100644 --- a/Extras/ConvexDecomposition/ConvexDecomposition.h +++ b/Extras/ConvexDecomposition/ConvexDecomposition.h @@ -3,30 +3,30 @@ #define CONVEX_DECOMPOSITION_H /*---------------------------------------------------------------------- - Copyright (c) 2004 Open Dynamics Framework Group - www.physicstools.org - All rights reserved. +Copyright (c) 2004 Open Dynamics Framework Group +www.physicstools.org +All rights reserved. - Redistribution and use in source and binary forms, with or without modification, are permitted provided - that the following conditions are met: +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. +Redistributions of source code must retain the above copyright notice, this list of conditions +and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. - Neither the name of the Open Dynamics Framework Group nor the names of its contributors may - be used to endorse or promote products derived from this software without specific prior written permission. +Neither the name of the Open Dynamics Framework Group nor the names of its contributors may +be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -----------------------------------------------------------------------*/ // http://codesuppository.blogspot.com @@ -37,156 +37,183 @@ // +#ifdef WIN32 +#include //memcpy +#endif +#include +#include + + + +static unsigned int MAXDEPTH=8; +static float CONCAVE_PERCENT=1.0f; +static float MERGE_PERCENT=2.0f; + +#include +typedef std::vector< unsigned int > UintVector; + + namespace ConvexDecomposition { -class ConvexResult -{ -public: - ConvexResult(void) - { - mHullVcount = 0; - mHullVertices = 0; - mHullTcount = 0; - mHullIndices = 0; - } + class ConvexResult + { + public: + ConvexResult(void) + { + mHullVcount = 0; + mHullVertices = 0; + mHullTcount = 0; + mHullIndices = 0; + } - ConvexResult(unsigned int hvcount,const float *hvertices,unsigned int htcount,const unsigned int *hindices) - { - mHullVcount = hvcount; - if ( mHullVcount ) - { - mHullVertices = new float[mHullVcount*sizeof(float)*3]; - memcpy(mHullVertices, hvertices, sizeof(float)*3*mHullVcount ); - } - else - { - mHullVertices = 0; - } + ConvexResult(unsigned int hvcount,const float *hvertices,unsigned int htcount,const unsigned int *hindices) + { + mHullVcount = hvcount; + if ( mHullVcount ) + { + mHullVertices = new float[mHullVcount*sizeof(float)*3]; + memcpy(mHullVertices, hvertices, sizeof(float)*3*mHullVcount ); + } + else + { + mHullVertices = 0; + } - mHullTcount = htcount; + mHullTcount = htcount; - if ( mHullTcount ) - { - mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; - memcpy(mHullIndices,hindices, sizeof(unsigned int)*mHullTcount*3 ); - } - else - { - mHullIndices = 0; - } + if ( mHullTcount ) + { + mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; + memcpy(mHullIndices,hindices, sizeof(unsigned int)*mHullTcount*3 ); + } + else + { + mHullIndices = 0; + } - } + } - ConvexResult(const ConvexResult &r) - { - mHullVcount = r.mHullVcount; - if ( mHullVcount ) - { - mHullVertices = new float[mHullVcount*sizeof(float)*3]; - memcpy(mHullVertices, r.mHullVertices, sizeof(float)*3*mHullVcount ); - } - else - { - mHullVertices = 0; - } - mHullTcount = r.mHullTcount; - if ( mHullTcount ) - { - mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; - memcpy(mHullIndices, r.mHullIndices, sizeof(unsigned int)*mHullTcount*3 ); - } - else - { - mHullIndices = 0; - } - } + ConvexResult(const ConvexResult &r) + { + mHullVcount = r.mHullVcount; + if ( mHullVcount ) + { + mHullVertices = new float[mHullVcount*sizeof(float)*3]; + memcpy(mHullVertices, r.mHullVertices, sizeof(float)*3*mHullVcount ); + } + else + { + mHullVertices = 0; + } + mHullTcount = r.mHullTcount; + if ( mHullTcount ) + { + mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; + memcpy(mHullIndices, r.mHullIndices, sizeof(unsigned int)*mHullTcount*3 ); + } + else + { + mHullIndices = 0; + } + } - ~ConvexResult(void) - { - delete mHullVertices; - delete mHullIndices; - } + ~ConvexResult(void) + { + delete mHullVertices; + delete mHullIndices; + } -// the convex hull. - unsigned int mHullVcount; - float * mHullVertices; - unsigned int mHullTcount; - unsigned int *mHullIndices; + // the convex hull. + unsigned int mHullVcount; + float * mHullVertices; + unsigned int mHullTcount; + unsigned int *mHullIndices; - float mHullVolume; // the volume of the convex hull. + float mHullVolume; // the volume of the convex hull. - float mOBBSides[3]; // the width, height and breadth of the best fit OBB - float mOBBCenter[3]; // the center of the OBB - float mOBBOrientation[4]; // the quaternion rotation of the OBB. - float mOBBTransform[16]; // the 4x4 transform of the OBB. - float mOBBVolume; // the volume of the OBB + float mOBBSides[3]; // the width, height and breadth of the best fit OBB + float mOBBCenter[3]; // the center of the OBB + float mOBBOrientation[4]; // the quaternion rotation of the OBB. + float mOBBTransform[16]; // the 4x4 transform of the OBB. + float mOBBVolume; // the volume of the OBB - float mSphereRadius; // radius and center of best fit sphere - float mSphereCenter[3]; - float mSphereVolume; // volume of the best fit sphere + float mSphereRadius; // radius and center of best fit sphere + float mSphereCenter[3]; + float mSphereVolume; // volume of the best fit sphere + }; + + class ConvexDecompInterface + { + public: + + virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) { }; + virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color) { }; + virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) { }; + virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) { }; + + virtual void ConvexDecompResult(ConvexResult &result) = 0; + + + + }; + + // just to avoid passing a zillion parameters to the method the + // options are packed into this descriptor. + class DecompDesc + { + public: + DecompDesc(void) + { + mVcount = 0; + mVertices = 0; + mTcount = 0; + mIndices = 0; + mDepth = 5; + mCpercent = 5; + mPpercent = 5; + mMaxVertices = 32; + mSkinWidth = 0; + mCallback = 0; + } + + // describes the input triangle. + unsigned int mVcount; // the number of vertices in the source mesh. + const float *mVertices; // start of the vertex position array. Assumes a stride of 3 floats. + unsigned int mTcount; // the number of triangles in the source mesh. + unsigned int *mIndices; // the indexed triangle list array (zero index based) + + // options + unsigned int mDepth; // depth to split, a maximum of 10, generally not over 7. + float mCpercent; // the concavity threshold percentage. 0=20 is reasonable. + float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable. + + // hull output limits. + unsigned int mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less. + float mSkinWidth; // a skin width to apply to the output hulls. + + ConvexDecompInterface *mCallback; // the interface to receive back the results. + + }; + + // perform approximate convex decomposition on a mesh. + unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced. + + + void calcConvexDecomposition(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float masterVolume, + unsigned int depth); + + }; -class ConvexDecompInterface -{ -public: - - virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) { }; - virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color) { }; - virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) { }; - virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) { }; - - virtual void ConvexDecompResult(ConvexResult &result) = 0; - - - -}; - -// just to avoid passing a zillion parameters to the method the -// options are packed into this descriptor. -class DecompDesc -{ -public: - DecompDesc(void) - { - mVcount = 0; - mVertices = 0; - mTcount = 0; - mIndices = 0; - mDepth = 5; - mCpercent = 5; - mPpercent = 5; - mMaxVertices = 32; - mSkinWidth = 0; - mCallback = 0; - } - -// describes the input triangle. - unsigned int mVcount; // the number of vertices in the source mesh. - const float *mVertices; // start of the vertex position array. Assumes a stride of 3 floats. - unsigned int mTcount; // the number of triangles in the source mesh. - unsigned int *mIndices; // the indexed triangle list array (zero index based) - -// options - unsigned int mDepth; // depth to split, a maximum of 10, generally not over 7. - float mCpercent; // the concavity threshold percentage. 0=20 is reasonable. - float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable. - -// hull output limits. - unsigned int mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less. - float mSkinWidth; // a skin width to apply to the output hulls. - - ConvexDecompInterface *mCallback; // the interface to receive back the results. - -}; - -// perform approximate convex decomposition on a mesh. -unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced. - -}; #endif