Code-style consistency improvement:

Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
erwincoumans
2018-09-23 14:17:31 -07:00
parent b73b05e9fb
commit ab8f16961e
1773 changed files with 1081087 additions and 474249 deletions

View File

@@ -8,34 +8,32 @@
#include "fitsphere.h"
#include "bestfitobb.h"
unsigned int MAXDEPTH = 8 ;
float CONCAVE_PERCENT = 1.0f ;
float MERGE_PERCENT = 2.0f ;
unsigned int MAXDEPTH = 8;
float CONCAVE_PERCENT = 1.0f;
float MERGE_PERCENT = 2.0f;
CHull::CHull(const ConvexDecomposition::ConvexResult &result)
{
mResult = new ConvexDecomposition::ConvexResult(result);
mVolume = computeMeshVolume( result.mHullVertices, result.mHullTcount, result.mHullIndices );
mVolume = computeMeshVolume(result.mHullVertices, result.mHullTcount, result.mHullIndices);
mDiagonal = getBoundingRegion( result.mHullVcount, result.mHullVertices, sizeof(float)*3, mMin, mMax );
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;
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::~CHull(void)
@@ -45,12 +43,9 @@ CHull::~CHull(void)
bool CHull::overlap(const CHull &h) const
{
return overlapAABB(mMin,mMax, h.mMin, h.mMax );
return overlapAABB(mMin, mMax, h.mMin, h.mMax);
}
ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback)
{
mCallback = callback;
@@ -59,45 +54,45 @@ ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback)
ConvexBuilder::~ConvexBuilder(void)
{
int i;
for (i=0;i<mChulls.size();i++)
for (i = 0; i < mChulls.size(); i++)
{
CHull *cr = mChulls[i];
delete cr;
}
}
bool ConvexBuilder::isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3,
unsigned int ci1,unsigned int ci2,unsigned int ci3)
bool ConvexBuilder::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 );
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++;
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 ConvexBuilder::getMesh(const ConvexDecomposition::ConvexResult &cr,VertexLookup vc,UintVector &indices)
void ConvexBuilder::getMesh(const ConvexDecomposition::ConvexResult &cr, VertexLookup vc, UintVector &indices)
{
unsigned int *src = cr.mHullIndices;
for (unsigned int i=0; i<cr.mHullTcount; i++)
for (unsigned int i = 0; i < cr.mHullTcount; i++)
{
unsigned int i1 = *src++;
unsigned int i2 = *src++;
unsigned int i3 = *src++;
const float *p1 = &cr.mHullVertices[i1*3];
const float *p2 = &cr.mHullVertices[i2*3];
const float *p3 = &cr.mHullVertices[i3*3];
const float *p1 = &cr.mHullVertices[i1 * 3];
const float *p2 = &cr.mHullVertices[i2 * 3];
const float *p3 = &cr.mHullVertices[i3 * 3];
i1 = Vl_getIndex(vc,p1);
i2 = Vl_getIndex(vc,p2);
i3 = Vl_getIndex(vc,p3);
i1 = Vl_getIndex(vc, p1);
i2 = Vl_getIndex(vc, p2);
i3 = Vl_getIndex(vc, p3);
#if 0
bool duplicate = false;
@@ -122,14 +117,12 @@ void ConvexBuilder::getMesh(const ConvexDecomposition::ConvexResult &cr,VertexLo
indices.push_back(i3);
}
#endif
}
}
CHull * ConvexBuilder::canMerge(CHull *a,CHull *b)
CHull *ConvexBuilder::canMerge(CHull *a, CHull *b)
{
if ( !a->overlap(*b) ) return 0; // if their AABB's (with a little slop) don't overlap, then return.
if (!a->overlap(*b)) return 0; // if their AABB's (with a little slop) don't overlap, then return.
CHull *ret = 0;
@@ -140,47 +133,45 @@ CHull * ConvexBuilder::canMerge(CHull *a,CHull *b)
UintVector indices;
getMesh( *a->mResult, vc, indices );
getMesh( *b->mResult, vc, 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 tcount = indices.size() / 3;
//don't do anything if hull is empty
if (!tcount)
{
Vl_releaseVertexLookup (vc);
Vl_releaseVertexLookup(vc);
return 0;
}
ConvexDecomposition::HullResult hresult;
ConvexDecomposition::HullLibrary hl;
ConvexDecomposition::HullDesc desc;
ConvexDecomposition::HullDesc desc;
desc.SetHullFlag(ConvexDecomposition::QF_TRIANGLES);
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float)*3;
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float) * 3;
ConvexDecomposition::HullError hret = hl.CreateConvexHull(desc,hresult);
ConvexDecomposition::HullError hret = hl.CreateConvexHull(desc, hresult);
if ( hret == ConvexDecomposition::QE_OK )
if (hret == ConvexDecomposition::QE_OK)
{
float combineVolume = computeMeshVolume(hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
float sumVolume = a->mVolume + b->mVolume;
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) )
float percent = (sumVolume * 100) / combineVolume;
if (percent >= (100.0f - MERGE_PERCENT))
{
ConvexDecomposition::ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
ret = new CHull(cr);
}
}
Vl_releaseVertexLookup(vc);
return ret;
@@ -188,41 +179,36 @@ CHull * ConvexBuilder::canMerge(CHull *a,CHull *b)
bool ConvexBuilder::combineHulls(void)
{
bool combine = false;
sortChulls(mChulls); // sort the convex hulls, largest volume to least...
CHullVector output; // the output hulls...
sortChulls(mChulls); // sort the convex hulls, largest volume to least...
CHullVector output; // the output hulls...
int i;
for (i=0;i<mChulls.size() && !combine; ++i)
for (i = 0; i < mChulls.size() && !combine; ++i)
{
CHull *cr = mChulls[i];
int j;
for (j=0;j<mChulls.size();j++)
for (j = 0; j < mChulls.size(); j++)
{
CHull *match = mChulls[j];
if ( cr != match ) // don't try to merge a hull with itself, that be stoopid
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....
CHull *merge = canMerge(cr,match); // if we can merge these two....
if ( merge )
if (merge)
{
output.push_back(merge);
++i;
while ( i != mChulls.size() )
while (i != mChulls.size())
{
CHull *cr = mChulls[i];
if ( cr != match )
if (cr != match)
{
output.push_back(cr);
}
@@ -237,7 +223,7 @@ bool ConvexBuilder::combineHulls(void)
}
}
if ( combine )
if (combine)
{
break;
}
@@ -245,88 +231,82 @@ bool ConvexBuilder::combineHulls(void)
{
output.push_back(cr);
}
}
if ( combine )
if (combine)
{
mChulls.clear();
mChulls.copyFromArray(output);
output.clear();
}
return combine;
}
unsigned int ConvexBuilder::process(const ConvexDecomposition::DecompDesc &desc)
{
unsigned int ret = 0;
MAXDEPTH = desc.mDepth;
MAXDEPTH = desc.mDepth;
CONCAVE_PERCENT = desc.mCpercent;
MERGE_PERCENT = desc.mPpercent;
MERGE_PERCENT = desc.mPpercent;
calcConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices, this, 0, 0);
calcConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices,this,0,0);
while ( combineHulls() ); // keep combinging hulls until I can't combine any more...
while (combineHulls())
; // keep combinging hulls until I can't combine any more...
int i;
for (i=0;i<mChulls.size();i++)
for (i = 0; i < mChulls.size(); i++)
{
CHull *cr = mChulls[i];
// before we hand it back to the application, we need to regenerate the hull based on the
// limits given by the user.
const ConvexDecomposition::ConvexResult &c = *cr->mResult; // the high resolution hull...
const ConvexDecomposition::ConvexResult &c = *cr->mResult; // the high resolution hull...
ConvexDecomposition::HullResult result;
ConvexDecomposition::HullLibrary hl;
ConvexDecomposition::HullDesc hdesc;
ConvexDecomposition::HullDesc hdesc;
hdesc.SetHullFlag(ConvexDecomposition::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
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 )
if (desc.mSkinWidth)
{
hdesc.mSkinWidth = desc.mSkinWidth;
hdesc.SetHullFlag(ConvexDecomposition::QF_SKIN_WIDTH); // do skin width computation.
hdesc.SetHullFlag(ConvexDecomposition::QF_SKIN_WIDTH); // do skin width computation.
}
ConvexDecomposition::HullError ret = hl.CreateConvexHull(hdesc,result);
ConvexDecomposition::HullError ret = hl.CreateConvexHull(hdesc, result);
if ( ret == ConvexDecomposition::QE_OK )
if (ret == ConvexDecomposition::QE_OK)
{
ConvexDecomposition::ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
r.mHullVolume = computeMeshVolume( result.mOutputVertices, result.mNumFaces, result.mIndices ); // the volume of the hull.
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 );
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.
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_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 );
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);
}
hl.ReleaseResult (result);
hl.ReleaseResult(result);
delete cr;
}
@@ -338,24 +318,23 @@ unsigned int ConvexBuilder::process(const ConvexDecomposition::DecompDesc &desc)
return ret;
}
void ConvexBuilder::ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color)
void ConvexBuilder::ConvexDebugTri(const float *p1, const float *p2, const float *p3, unsigned int color)
{
mCallback->ConvexDebugTri(p1,p2,p3,color);
mCallback->ConvexDebugTri(p1, p2, p3, color);
}
void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color)
void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix, unsigned int color)
{
mCallback->ConvexDebugOBB(sides,matrix,color);
mCallback->ConvexDebugOBB(sides, matrix, color);
}
void ConvexBuilder::ConvexDebugPoint(const float *p,float dist,unsigned int color)
void ConvexBuilder::ConvexDebugPoint(const float *p, float dist, unsigned int color)
{
mCallback->ConvexDebugPoint(p,dist,color);
mCallback->ConvexDebugPoint(p, dist, color);
}
void ConvexBuilder::ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color)
void ConvexBuilder::ConvexDebugBound(const float *bmin, const float *bmax, unsigned int color)
{
mCallback->ConvexDebugBound(bmin,bmax,color);
mCallback->ConvexDebugBound(bmin, bmax, color);
}
void ConvexBuilder::ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
@@ -369,5 +348,3 @@ void ConvexBuilder::sortChulls(CHullVector &hulls)
hulls.quickSort(CHullSort());
//hulls.heapSort(CHullSort());
}

View File

@@ -35,12 +35,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// http://www.amillionpixels.us
//
#include "ConvexDecomposition.h"
#include "vlookup.h"
#include "LinearMath/btAlignedObjectArray.h"
class CHull
{
public:
@@ -50,28 +48,24 @@ public:
bool overlap(const CHull &h) const;
float mMin[3];
float mMax[3];
float mVolume;
float mDiagonal; // long edge..
ConvexDecomposition::ConvexResult *mResult;
float mMin[3];
float mMax[3];
float mVolume;
float mDiagonal; // long edge..
ConvexDecomposition::ConvexResult *mResult;
};
// Usage: std::sort( list.begin(), list.end(), StringSortRef() );
class CHullSort
{
public:
inline bool operator()(const CHull *a,const CHull *b) const
inline bool operator()(const CHull *a, const CHull *b) const
{
return a->mVolume < b->mVolume;
}
};
typedef btAlignedObjectArray< CHull * > CHullVector;
typedef btAlignedObjectArray<CHull *> CHullVector;
class ConvexBuilder : public ConvexDecomposition::ConvexDecompInterface
{
@@ -80,31 +74,30 @@ public:
virtual ~ConvexBuilder(void);
bool isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3,
unsigned int ci1,unsigned int ci2,unsigned int ci3);
bool isDuplicate(unsigned int i1, unsigned int i2, unsigned int i3,
unsigned int ci1, unsigned int ci2, unsigned int ci3);
void getMesh(const ConvexDecomposition::ConvexResult &cr,VertexLookup vc,UintVector &indices);
void getMesh(const ConvexDecomposition::ConvexResult &cr, VertexLookup vc, UintVector &indices);
CHull * canMerge(CHull *a,CHull *b);
CHull *canMerge(CHull *a, CHull *b);
bool combineHulls(void);
unsigned int process(const ConvexDecomposition::DecompDesc &desc);
virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color);
virtual void ConvexDebugTri(const float *p1, const float *p2, const float *p3, unsigned int color);
virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color);
virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color);
virtual void ConvexDebugOBB(const float *sides, const float *matrix, 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 ConvexDebugBound(const float *bmin, const float *bmax, unsigned int color);
virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result);
void sortChulls(CHullVector &hulls);
CHullVector mChulls;
CHullVector mChulls;
ConvexDecompInterface *mCallback;
};
#endif //CONVEX_BUILDER_H
#endif //CONVEX_BUILDER_H

View File

@@ -5,7 +5,6 @@
#include <string.h>
#include <assert.h>
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -56,320 +55,292 @@
#define SHOW_MESH 0
#define MAKE_MESH 1
using namespace ConvexDecomposition;
namespace ConvexDecomposition
{
class FaceTri
{
public:
FaceTri(void) { };
FaceTri(const float *vertices,unsigned int i1,unsigned int i2,unsigned int i3)
{
mP1.Set( &vertices[i1*3] );
mP2.Set( &vertices[i2*3] );
mP3.Set( &vertices[i3*3] );
}
Vector3d mP1;
Vector3d mP2;
Vector3d mP3;
Vector3d mNormal;
FaceTri(void){};
FaceTri(const float *vertices, unsigned int i1, unsigned int i2, unsigned int i3)
{
mP1.Set(&vertices[i1 * 3]);
mP2.Set(&vertices[i2 * 3]);
mP3.Set(&vertices[i3 * 3]);
}
Vector3d mP1;
Vector3d mP2;
Vector3d mP3;
Vector3d mNormal;
};
void addTri(VertexLookup vl,UintVector &list,const Vector3d &p1,const Vector3d &p2,const Vector3d &p3)
void addTri(VertexLookup vl, UintVector &list, const Vector3d &p1, const Vector3d &p2, const Vector3d &p3)
{
unsigned int i1 = Vl_getIndex(vl, p1.Ptr() );
unsigned int i2 = Vl_getIndex(vl, p2.Ptr() );
unsigned int i3 = Vl_getIndex(vl, p3.Ptr() );
unsigned int i1 = Vl_getIndex(vl, p1.Ptr());
unsigned int i2 = Vl_getIndex(vl, p2.Ptr());
unsigned int i3 = Vl_getIndex(vl, p3.Ptr());
// do *not* process degenerate triangles!
// do *not* process degenerate triangles!
if ( i1 != i2 && i1 != i3 && i2 != i3 )
{
list.push_back(i1);
list.push_back(i2);
list.push_back(i3);
}
if (i1 != i2 && i1 != i3 && i2 != i3)
{
list.push_back(i1);
list.push_back(i2);
list.push_back(i3);
}
}
void calcConvexDecomposition(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float masterVolume,
unsigned int depth)
void calcConvexDecomposition(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float masterVolume,
unsigned int depth)
{
float plane[4];
float plane[4];
bool split = false;
if ( depth < MAXDEPTH )
{
bool split = false;
if (depth < MAXDEPTH)
{
float volume;
float c = computeConcavity( vcount, vertices, tcount, indices, callback, plane, volume );
float c = computeConcavity(vcount, vertices, tcount, indices, callback, plane, volume);
if ( depth == 0 )
{
masterVolume = volume;
}
float percent = (c*100.0f)/masterVolume;
if ( percent > CONCAVE_PERCENT ) // if great than 5% of the total volume is concave, go ahead and keep splitting.
if (depth == 0)
{
split = true;
}
masterVolume = volume;
}
}
float percent = (c * 100.0f) / masterVolume;
if ( depth >= MAXDEPTH || !split )
{
if (percent > CONCAVE_PERCENT) // if great than 5% of the total volume is concave, go ahead and keep splitting.
{
split = true;
}
}
if (depth >= MAXDEPTH || !split)
{
#if 1
HullResult result;
HullLibrary hl;
HullDesc desc;
HullResult result;
HullLibrary hl;
HullDesc desc;
desc.SetHullFlag(QF_TRIANGLES);
desc.SetHullFlag(QF_TRIANGLES);
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float)*3;
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float) * 3;
HullError ret = hl.CreateConvexHull(desc,result);
if ( ret == QE_OK )
{
HullError ret = hl.CreateConvexHull(desc, result);
if (ret == QE_OK)
{
ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
callback->ConvexDecompResult(r);
}
}
#else
static unsigned int colors[8] =
{
0xFF0000,
0x00FF00,
0x0000FF,
0xFFFF00,
0x00FFFF,
0xFF00FF,
0xFFFFFF,
0xFF8040
};
{
0xFF0000,
0x00FF00,
0x0000FF,
0xFFFF00,
0x00FFFF,
0xFF00FF,
0xFFFFFF,
0xFF8040};
static int count = 0;
count++;
if ( count == 8 ) count = 0;
if (count == 8) count = 0;
assert( count >= 0 && count < 8 );
assert(count >= 0 && count < 8);
unsigned int color = colors[count];
const unsigned int *source = indices;
for (unsigned int i=0; i<tcount; i++)
{
unsigned int i1 = *source++;
unsigned int i2 = *source++;
unsigned int i3 = *source++;
FaceTri t(vertices, i1, i2, i3 );
callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color );
}
#endif
hl.ReleaseResult (result);
return;
}
UintVector ifront;
UintVector iback;
VertexLookup vfront = Vl_createVertexLookup();
VertexLookup vback = Vl_createVertexLookup();
bool showmesh = false;
#if SHOW_MESH
showmesh = true;
#endif
if ( 0 )
{
showmesh = true;
for (float x=-1; x<1; x+=0.10f)
{
for (float y=0; y<1; y+=0.10f)
{
for (float z=-1; z<1; z+=0.04f)
{
float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
Vector3d p(x,y,z);
if ( d >= 0 )
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00);
else
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000);
}
}
}
}
if ( 1 )
{
// ok..now we are going to 'split' all of the input triangles against this plane!
const unsigned int *source = indices;
for (unsigned int i=0; i<tcount; i++)
for (unsigned int i = 0; i < tcount; i++)
{
unsigned int i1 = *source++;
unsigned int i2 = *source++;
unsigned int i3 = *source++;
FaceTri t(vertices, i1, i2, i3 );
FaceTri t(vertices, i1, i2, i3);
callback->ConvexDebugTri(t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color);
}
#endif
hl.ReleaseResult(result);
return;
}
UintVector ifront;
UintVector iback;
VertexLookup vfront = Vl_createVertexLookup();
VertexLookup vback = Vl_createVertexLookup();
bool showmesh = false;
#if SHOW_MESH
showmesh = true;
#endif
if (0)
{
showmesh = true;
for (float x = -1; x < 1; x += 0.10f)
{
for (float y = 0; y < 1; y += 0.10f)
{
for (float z = -1; z < 1; z += 0.04f)
{
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
Vector3d p(x, y, z);
if (d >= 0)
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00);
else
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000);
}
}
}
}
if (1)
{
// ok..now we are going to 'split' all of the input triangles against this plane!
const unsigned int *source = indices;
for (unsigned int i = 0; i < tcount; i++)
{
unsigned int i1 = *source++;
unsigned int i2 = *source++;
unsigned int i3 = *source++;
FaceTri t(vertices, i1, i2, i3);
Vector3d front[4];
Vector3d back[4];
unsigned int fcount=0;
unsigned int bcount=0;
unsigned int fcount = 0;
unsigned int bcount = 0;
PlaneTriResult result;
result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
result = planeTriIntersection(plane, t.mP1.Ptr(), sizeof(Vector3d), 0.00001f, front[0].Ptr(), fcount, back[0].Ptr(), bcount);
if( fcount > 4 || bcount > 4 )
if (fcount > 4 || bcount > 4)
{
result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
result = planeTriIntersection(plane, t.mP1.Ptr(), sizeof(Vector3d), 0.00001f, front[0].Ptr(), fcount, back[0].Ptr(), bcount);
}
switch ( result )
switch (result)
{
case PTR_FRONT:
assert( fcount == 3 );
assert(fcount == 3);
if ( showmesh )
callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00 );
if (showmesh)
callback->ConvexDebugTri(front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00);
#if MAKE_MESH
#if MAKE_MESH
addTri( vfront, ifront, front[0], front[1], front[2] );
addTri(vfront, ifront, front[0], front[1], front[2]);
#endif
#endif
break;
case PTR_BACK:
assert( bcount == 3 );
assert(bcount == 3);
if ( showmesh )
callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00 );
if (showmesh)
callback->ConvexDebugTri(back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00);
#if MAKE_MESH
#if MAKE_MESH
addTri( vback, iback, back[0], back[1], back[2] );
addTri(vback, iback, back[0], back[1], back[2]);
#endif
#endif
break;
case PTR_SPLIT:
assert( fcount >= 3 && fcount <= 4);
assert( bcount >= 3 && bcount <= 4);
assert(fcount >= 3 && fcount <= 4);
assert(bcount >= 3 && bcount <= 4);
#if MAKE_MESH
#if MAKE_MESH
addTri( vfront, ifront, front[0], front[1], front[2] );
addTri( vback, iback, back[0], back[1], back[2] );
addTri(vfront, ifront, front[0], front[1], front[2]);
addTri(vback, iback, back[0], back[1], back[2]);
if (fcount == 4)
{
addTri(vfront, ifront, front[0], front[2], front[3]);
}
if ( fcount == 4 )
{
addTri( vfront, ifront, front[0], front[2], front[3] );
}
if (bcount == 4)
{
addTri(vback, iback, back[0], back[2], back[3]);
}
if ( bcount == 4 )
{
addTri( vback, iback, back[0], back[2], back[3] );
}
#endif
#endif
if (showmesh)
{
callback->ConvexDebugTri(front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000);
callback->ConvexDebugTri(back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000);
if ( showmesh )
{
callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000 );
callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000 );
if ( fcount == 4 )
{
callback->ConvexDebugTri( front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000 );
}
if ( bcount == 4 )
{
callback->ConvexDebugTri( back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000 );
}
}
if (fcount == 4)
{
callback->ConvexDebugTri(front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000);
}
if (bcount == 4)
{
callback->ConvexDebugTri(back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000);
}
}
break;
}
}
// ok... here we recursively call
if ( ifront.size() )
{
unsigned int vcount = Vl_getVcount(vfront);
const float *vertices = Vl_getVertices(vfront);
unsigned int tcount = ifront.size()/3;
// ok... here we recursively call
if (ifront.size())
{
unsigned int vcount = Vl_getVcount(vfront);
const float *vertices = Vl_getVertices(vfront);
unsigned int tcount = ifront.size() / 3;
calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1);
calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth + 1);
}
}
ifront.clear();
ifront.clear();
Vl_releaseVertexLookup(vfront);
Vl_releaseVertexLookup(vfront);
if (iback.size())
{
unsigned int vcount = Vl_getVcount(vback);
const float *vertices = Vl_getVertices(vback);
unsigned int tcount = iback.size() / 3;
if ( iback.size() )
{
unsigned int vcount = Vl_getVcount(vback);
const float *vertices = Vl_getVertices(vback);
unsigned int tcount = iback.size()/3;
calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1);
}
iback.clear();
Vl_releaseVertexLookup(vback);
calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth + 1);
}
iback.clear();
Vl_releaseVertexLookup(vback);
}
}
}
} // namespace ConvexDecomposition

View File

@@ -36,185 +36,167 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// http://www.amillionpixels.us
//
#ifdef _WIN32
#include <memory.h> //memcpy
#include <memory.h> //memcpy
#endif
#include <string.h>
#include <stdio.h>
#include "LinearMath/btAlignedObjectArray.h"
extern unsigned int MAXDEPTH;
extern float CONCAVE_PERCENT;
extern float MERGE_PERCENT;
extern unsigned int MAXDEPTH ;
extern float CONCAVE_PERCENT ;
extern float MERGE_PERCENT ;
typedef btAlignedObjectArray< unsigned int > UintVector;
typedef btAlignedObjectArray<unsigned int> UintVector;
namespace ConvexDecomposition
{
class ConvexResult
class ConvexResult
{
public:
ConvexResult(void)
{
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
{
mHullVcount = 0;
mHullVertices = 0;
mHullTcount = 0;
}
mHullTcount = htcount;
if (mHullTcount)
{
mHullIndices = new unsigned int[sizeof(unsigned int) * mHullTcount * 3];
memcpy(mHullIndices, hindices, sizeof(unsigned int) * mHullTcount * 3);
}
else
{
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;
}
mHullTcount = htcount;
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(void)
{
delete [] mHullVertices;
delete [] mHullIndices;
}
// the convex hull.
unsigned int mHullVcount;
float * mHullVertices;
unsigned int mHullTcount;
unsigned int *mHullIndices;
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 mSphereRadius; // radius and center of best fit sphere
float mSphereCenter[3];
float mSphereVolume; // volume of the best fit sphere
};
class ConvexDecompInterface
ConvexResult(const ConvexResult &r)
{
public:
virtual ~ConvexDecompInterface() {};
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)
mHullVcount = r.mHullVcount;
if (mHullVcount)
{
mVcount = 0;
mVertices = 0;
mTcount = 0;
mIndices = 0;
mDepth = 5;
mCpercent = 5;
mPpercent = 5;
mMaxVertices = 32;
mSkinWidth = 0;
mCallback = 0;
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;
}
}
// 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)
~ConvexResult(void)
{
delete[] mHullVertices;
delete[] mHullIndices;
}
// 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.
// the convex hull.
unsigned int mHullVcount;
float *mHullVertices;
unsigned int mHullTcount;
unsigned int *mHullIndices;
// 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.
float mHullVolume; // the volume of the convex hull.
ConvexDecompInterface *mCallback; // the interface to receive back the results.
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
};
// perform approximate convex decomposition on a mesh.
unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced.
class ConvexDecompInterface
{
public:
virtual ~ConvexDecompInterface(){};
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;
};
void calcConvexDecomposition(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float masterVolume,
unsigned int depth);
// 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);
} // namespace ConvexDecomposition
#endif

View File

@@ -52,369 +52,358 @@
namespace BestFit
{
class Vec3
{
public:
Vec3(void) { };
Vec3(float _x,float _y,float _z) { x = _x; y = _y; z = _z; };
Vec3(void){};
Vec3(float _x, float _y, float _z)
{
x = _x;
y = _y;
z = _z;
};
float dot(const Vec3 &v)
{
return x * v.x + y * v.y + z * v.z; // the dot product
}
float dot(const Vec3 &v)
{
return x*v.x + y*v.y + z*v.z; // the dot product
}
float x;
float y;
float z;
float x;
float y;
float z;
};
class Eigen
{
public:
void DecrSortEigenStuff(void)
{
Tridiagonal(); //diagonalize the matrix.
QLAlgorithm(); //
DecreasingSort();
GuaranteeRotation();
}
void Tridiagonal(void)
{
float fM00 = mElement[0][0];
float fM01 = mElement[0][1];
float fM02 = mElement[0][2];
float fM11 = mElement[1][1];
float fM12 = mElement[1][2];
float fM22 = mElement[2][2];
void DecrSortEigenStuff(void)
{
Tridiagonal(); //diagonalize the matrix.
QLAlgorithm(); //
DecreasingSort();
GuaranteeRotation();
}
m_afDiag[0] = fM00;
m_afSubd[2] = 0;
if (fM02 != (float)0.0)
{
float fLength = sqrtf(fM01 * fM01 + fM02 * fM02);
float fInvLength = ((float)1.0) / fLength;
fM01 *= fInvLength;
fM02 *= fInvLength;
float fQ = ((float)2.0) * fM01 * fM12 + fM02 * (fM22 - fM11);
m_afDiag[1] = fM11 + fM02 * fQ;
m_afDiag[2] = fM22 - fM02 * fQ;
m_afSubd[0] = fLength;
m_afSubd[1] = fM12 - fM01 * fQ;
mElement[0][0] = (float)1.0;
mElement[0][1] = (float)0.0;
mElement[0][2] = (float)0.0;
mElement[1][0] = (float)0.0;
mElement[1][1] = fM01;
mElement[1][2] = fM02;
mElement[2][0] = (float)0.0;
mElement[2][1] = fM02;
mElement[2][2] = -fM01;
m_bIsRotation = false;
}
else
{
m_afDiag[1] = fM11;
m_afDiag[2] = fM22;
m_afSubd[0] = fM01;
m_afSubd[1] = fM12;
mElement[0][0] = (float)1.0;
mElement[0][1] = (float)0.0;
mElement[0][2] = (float)0.0;
mElement[1][0] = (float)0.0;
mElement[1][1] = (float)1.0;
mElement[1][2] = (float)0.0;
mElement[2][0] = (float)0.0;
mElement[2][1] = (float)0.0;
mElement[2][2] = (float)1.0;
m_bIsRotation = true;
}
}
void Tridiagonal(void)
{
float fM00 = mElement[0][0];
float fM01 = mElement[0][1];
float fM02 = mElement[0][2];
float fM11 = mElement[1][1];
float fM12 = mElement[1][2];
float fM22 = mElement[2][2];
bool QLAlgorithm(void)
{
const int iMaxIter = 32;
m_afDiag[0] = fM00;
m_afSubd[2] = 0;
if (fM02 != (float)0.0)
{
float fLength = sqrtf(fM01*fM01+fM02*fM02);
float fInvLength = ((float)1.0)/fLength;
fM01 *= fInvLength;
fM02 *= fInvLength;
float fQ = ((float)2.0)*fM01*fM12+fM02*(fM22-fM11);
m_afDiag[1] = fM11+fM02*fQ;
m_afDiag[2] = fM22-fM02*fQ;
m_afSubd[0] = fLength;
m_afSubd[1] = fM12-fM01*fQ;
mElement[0][0] = (float)1.0;
mElement[0][1] = (float)0.0;
mElement[0][2] = (float)0.0;
mElement[1][0] = (float)0.0;
mElement[1][1] = fM01;
mElement[1][2] = fM02;
mElement[2][0] = (float)0.0;
mElement[2][1] = fM02;
mElement[2][2] = -fM01;
m_bIsRotation = false;
}
else
{
m_afDiag[1] = fM11;
m_afDiag[2] = fM22;
m_afSubd[0] = fM01;
m_afSubd[1] = fM12;
mElement[0][0] = (float)1.0;
mElement[0][1] = (float)0.0;
mElement[0][2] = (float)0.0;
mElement[1][0] = (float)0.0;
mElement[1][1] = (float)1.0;
mElement[1][2] = (float)0.0;
mElement[2][0] = (float)0.0;
mElement[2][1] = (float)0.0;
mElement[2][2] = (float)1.0;
m_bIsRotation = true;
}
}
for (int i0 = 0; i0 < 3; i0++)
{
int i1;
for (i1 = 0; i1 < iMaxIter; i1++)
{
int i2;
for (i2 = i0; i2 <= (3 - 2); i2++)
{
float fTmp = fabsf(m_afDiag[i2]) + fabsf(m_afDiag[i2 + 1]);
if (fabsf(m_afSubd[i2]) + fTmp == fTmp)
break;
}
if (i2 == i0)
{
break;
}
bool QLAlgorithm(void)
{
const int iMaxIter = 32;
float fG = (m_afDiag[i0 + 1] - m_afDiag[i0]) / (((float)2.0) * m_afSubd[i0]);
float fR = sqrtf(fG * fG + (float)1.0);
if (fG < (float)0.0)
{
fG = m_afDiag[i2] - m_afDiag[i0] + m_afSubd[i0] / (fG - fR);
}
else
{
fG = m_afDiag[i2] - m_afDiag[i0] + m_afSubd[i0] / (fG + fR);
}
float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0;
for (int i3 = i2 - 1; i3 >= i0; i3--)
{
float fF = fSin * m_afSubd[i3];
float fB = fCos * m_afSubd[i3];
if (fabsf(fF) >= fabsf(fG))
{
fCos = fG / fF;
fR = sqrtf(fCos * fCos + (float)1.0);
m_afSubd[i3 + 1] = fF * fR;
fSin = ((float)1.0) / fR;
fCos *= fSin;
}
else
{
fSin = fF / fG;
fR = sqrtf(fSin * fSin + (float)1.0);
m_afSubd[i3 + 1] = fG * fR;
fCos = ((float)1.0) / fR;
fSin *= fCos;
}
fG = m_afDiag[i3 + 1] - fP;
fR = (m_afDiag[i3] - fG) * fSin + ((float)2.0) * fB * fCos;
fP = fSin * fR;
m_afDiag[i3 + 1] = fG + fP;
fG = fCos * fR - fB;
for (int i4 = 0; i4 < 3; i4++)
{
fF = mElement[i4][i3 + 1];
mElement[i4][i3 + 1] = fSin * mElement[i4][i3] + fCos * fF;
mElement[i4][i3] = fCos * mElement[i4][i3] - fSin * fF;
}
}
m_afDiag[i0] -= fP;
m_afSubd[i0] = fG;
m_afSubd[i2] = (float)0.0;
}
if (i1 == iMaxIter)
{
return false;
}
}
return true;
}
for (int i0 = 0; i0 <3; i0++)
{
int i1;
for (i1 = 0; i1 < iMaxIter; i1++)
{
int i2;
for (i2 = i0; i2 <= (3-2); i2++)
{
float fTmp = fabsf(m_afDiag[i2]) + fabsf(m_afDiag[i2+1]);
if ( fabsf(m_afSubd[i2]) + fTmp == fTmp )
break;
}
if (i2 == i0)
{
break;
}
void DecreasingSort(void)
{
//sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
for (int i0 = 0, i1; i0 <= 3 - 2; i0++)
{
// locate maximum eigenvalue
i1 = i0;
float fMax = m_afDiag[i1];
int i2;
for (i2 = i0 + 1; i2 < 3; i2++)
{
if (m_afDiag[i2] > fMax)
{
i1 = i2;
fMax = m_afDiag[i1];
}
}
float fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((float)2.0) * m_afSubd[i0]);
float fR = sqrtf(fG*fG+(float)1.0);
if (fG < (float)0.0)
{
fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
}
else
{
fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
}
float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0;
for (int i3 = i2-1; i3 >= i0; i3--)
{
float fF = fSin*m_afSubd[i3];
float fB = fCos*m_afSubd[i3];
if (fabsf(fF) >= fabsf(fG))
{
fCos = fG/fF;
fR = sqrtf(fCos*fCos+(float)1.0);
m_afSubd[i3+1] = fF*fR;
fSin = ((float)1.0)/fR;
fCos *= fSin;
}
else
{
fSin = fF/fG;
fR = sqrtf(fSin*fSin+(float)1.0);
m_afSubd[i3+1] = fG*fR;
fCos = ((float)1.0)/fR;
fSin *= fCos;
}
fG = m_afDiag[i3+1]-fP;
fR = (m_afDiag[i3]-fG)*fSin+((float)2.0)*fB*fCos;
fP = fSin*fR;
m_afDiag[i3+1] = fG+fP;
fG = fCos*fR-fB;
for (int i4 = 0; i4 < 3; i4++)
{
fF = mElement[i4][i3+1];
mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
}
}
m_afDiag[i0] -= fP;
m_afSubd[i0] = fG;
m_afSubd[i2] = (float)0.0;
}
if (i1 == iMaxIter)
{
return false;
}
}
return true;
}
if (i1 != i0)
{
// swap eigenvalues
m_afDiag[i1] = m_afDiag[i0];
m_afDiag[i0] = fMax;
// swap eigenvectors
for (i2 = 0; i2 < 3; i2++)
{
float fTmp = mElement[i2][i0];
mElement[i2][i0] = mElement[i2][i1];
mElement[i2][i1] = fTmp;
m_bIsRotation = !m_bIsRotation;
}
}
}
}
void DecreasingSort(void)
{
//sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
for (int i0 = 0, i1; i0 <= 3-2; i0++)
{
// locate maximum eigenvalue
i1 = i0;
float fMax = m_afDiag[i1];
int i2;
for (i2 = i0+1; i2 < 3; i2++)
{
if (m_afDiag[i2] > fMax)
{
i1 = i2;
fMax = m_afDiag[i1];
}
}
void GuaranteeRotation(void)
{
if (!m_bIsRotation)
{
// change sign on the first column
for (int iRow = 0; iRow < 3; iRow++)
{
mElement[iRow][0] = -mElement[iRow][0];
}
}
}
if (i1 != i0)
{
// swap eigenvalues
m_afDiag[i1] = m_afDiag[i0];
m_afDiag[i0] = fMax;
// swap eigenvectors
for (i2 = 0; i2 < 3; i2++)
{
float fTmp = mElement[i2][i0];
mElement[i2][i0] = mElement[i2][i1];
mElement[i2][i1] = fTmp;
m_bIsRotation = !m_bIsRotation;
}
}
}
}
void GuaranteeRotation(void)
{
if (!m_bIsRotation)
{
// change sign on the first column
for (int iRow = 0; iRow <3; iRow++)
{
mElement[iRow][0] = -mElement[iRow][0];
}
}
}
float mElement[3][3];
float m_afDiag[3];
float m_afSubd[3];
bool m_bIsRotation;
float mElement[3][3];
float m_afDiag[3];
float m_afSubd[3];
bool m_bIsRotation;
};
}
} // namespace BestFit
using namespace BestFit;
bool getBestFitPlane(unsigned int vcount,
const float *points,
unsigned int vstride,
const float *weights,
unsigned int wstride,
float *plane)
const float *points,
unsigned int vstride,
const float *weights,
unsigned int wstride,
float *plane)
{
bool ret = false;
bool ret = false;
Vec3 kOrigin(0,0,0);
Vec3 kOrigin(0, 0, 0);
float wtotal = 0;
float wtotal = 0;
if ( 1 )
{
const char *source = (const char *) points;
const char *wsource = (const char *) weights;
if (1)
{
const char *source = (const char *)points;
const char *wsource = (const char *)weights;
for (unsigned int i=0; i<vcount; i++)
{
for (unsigned int i = 0; i < vcount; i++)
{
const float *p = (const float *)source;
const float *p = (const float *) source;
float w = 1;
float w = 1;
if (wsource)
{
const float *ws = (const float *)wsource;
w = *ws; //
wsource += wstride;
}
if ( wsource )
{
const float *ws = (const float *) wsource;
w = *ws; //
wsource+=wstride;
}
kOrigin.x += p[0] * w;
kOrigin.y += p[1] * w;
kOrigin.z += p[2] * w;
kOrigin.x+=p[0]*w;
kOrigin.y+=p[1]*w;
kOrigin.z+=p[2]*w;
wtotal += w;
wtotal+=w;
source += vstride;
}
}
source+=vstride;
}
}
float recip = 1.0f / wtotal; // reciprocol of total weighting
float recip = 1.0f / wtotal; // reciprocol of total weighting
kOrigin.x *= recip;
kOrigin.y *= recip;
kOrigin.z *= recip;
kOrigin.x*=recip;
kOrigin.y*=recip;
kOrigin.z*=recip;
float fSumXX = 0;
float fSumXY = 0;
float fSumXZ = 0;
float fSumYY = 0;
float fSumYZ = 0;
float fSumZZ = 0;
float fSumXX=0;
float fSumXY=0;
float fSumXZ=0;
if (1)
{
const char *source = (const char *)points;
const char *wsource = (const char *)weights;
float fSumYY=0;
float fSumYZ=0;
float fSumZZ=0;
for (unsigned int i = 0; i < vcount; i++)
{
const float *p = (const float *)source;
float w = 1;
if ( 1 )
{
const char *source = (const char *) points;
const char *wsource = (const char *) weights;
if (wsource)
{
const float *ws = (const float *)wsource;
w = *ws; //
wsource += wstride;
}
for (unsigned int i=0; i<vcount; i++)
{
Vec3 kDiff;
const float *p = (const float *) source;
kDiff.x = w * (p[0] - kOrigin.x); // apply vertex weighting!
kDiff.y = w * (p[1] - kOrigin.y);
kDiff.z = w * (p[2] - kOrigin.z);
float w = 1;
fSumXX += kDiff.x * kDiff.x; // sume of the squares of the differences.
fSumXY += kDiff.x * kDiff.y; // sume of the squares of the differences.
fSumXZ += kDiff.x * kDiff.z; // sume of the squares of the differences.
if ( wsource )
{
const float *ws = (const float *) wsource;
w = *ws; //
wsource+=wstride;
}
fSumYY += kDiff.y * kDiff.y;
fSumYZ += kDiff.y * kDiff.z;
fSumZZ += kDiff.z * kDiff.z;
Vec3 kDiff;
source += vstride;
}
}
kDiff.x = w*(p[0] - kOrigin.x); // apply vertex weighting!
kDiff.y = w*(p[1] - kOrigin.y);
kDiff.z = w*(p[2] - kOrigin.z);
fSumXX *= recip;
fSumXY *= recip;
fSumXZ *= recip;
fSumYY *= recip;
fSumYZ *= recip;
fSumZZ *= recip;
fSumXX+= kDiff.x * kDiff.x; // sume of the squares of the differences.
fSumXY+= kDiff.x * kDiff.y; // sume of the squares of the differences.
fSumXZ+= kDiff.x * kDiff.z; // sume of the squares of the differences.
// setup the eigensolver
Eigen kES;
fSumYY+= kDiff.y * kDiff.y;
fSumYZ+= kDiff.y * kDiff.z;
fSumZZ+= kDiff.z * kDiff.z;
kES.mElement[0][0] = fSumXX;
kES.mElement[0][1] = fSumXY;
kES.mElement[0][2] = fSumXZ;
kES.mElement[1][0] = fSumXY;
kES.mElement[1][1] = fSumYY;
kES.mElement[1][2] = fSumYZ;
source+=vstride;
}
}
kES.mElement[2][0] = fSumXZ;
kES.mElement[2][1] = fSumYZ;
kES.mElement[2][2] = fSumZZ;
fSumXX *= recip;
fSumXY *= recip;
fSumXZ *= recip;
fSumYY *= recip;
fSumYZ *= recip;
fSumZZ *= recip;
// compute eigenstuff, smallest eigenvalue is in last position
kES.DecrSortEigenStuff();
// setup the eigensolver
Eigen kES;
Vec3 kNormal;
kES.mElement[0][0] = fSumXX;
kES.mElement[0][1] = fSumXY;
kES.mElement[0][2] = fSumXZ;
kNormal.x = kES.mElement[0][2];
kNormal.y = kES.mElement[1][2];
kNormal.z = kES.mElement[2][2];
kES.mElement[1][0] = fSumXY;
kES.mElement[1][1] = fSumYY;
kES.mElement[1][2] = fSumYZ;
// the minimum energy
plane[0] = kNormal.x;
plane[1] = kNormal.y;
plane[2] = kNormal.z;
kES.mElement[2][0] = fSumXZ;
kES.mElement[2][1] = fSumYZ;
kES.mElement[2][2] = fSumZZ;
plane[3] = 0 - kNormal.dot(kOrigin);
// compute eigenstuff, smallest eigenvalue is in last position
kES.DecrSortEigenStuff();
Vec3 kNormal;
kNormal.x = kES.mElement[0][2];
kNormal.y = kES.mElement[1][2];
kNormal.z = kES.mElement[2][2];
// the minimum energy
plane[0] = kNormal.x;
plane[1] = kNormal.y;
plane[2] = kNormal.z;
plane[3] = 0 - kNormal.dot(kOrigin);
return ret;
return ret;
}
float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax) // returns the diagonal distance
float getBoundingRegion(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax) // returns the diagonal distance
{
const unsigned char *source = (const unsigned char *) points;
const unsigned char *source = (const unsigned char *)points;
bmin[0] = points[0];
bmin[1] = points[1];
@@ -424,43 +413,36 @@ float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pst
bmax[1] = points[1];
bmax[2] = points[2];
for (unsigned int i = 1; i < vcount; i++)
{
source += pstride;
const float *p = (const float *)source;
for (unsigned int i=1; i<vcount; i++)
{
source+=pstride;
const float *p = (const float *) source;
if (p[0] < bmin[0]) bmin[0] = p[0];
if (p[1] < bmin[1]) bmin[1] = p[1];
if (p[2] < bmin[2]) bmin[2] = p[2];
if ( p[0] < bmin[0] ) bmin[0] = p[0];
if ( p[1] < bmin[1] ) bmin[1] = p[1];
if ( p[2] < bmin[2] ) bmin[2] = p[2];
if (p[0] > bmax[0]) bmax[0] = p[0];
if (p[1] > bmax[1]) bmax[1] = p[1];
if (p[2] > bmax[2]) bmax[2] = p[2];
}
if ( p[0] > bmax[0] ) bmax[0] = p[0];
if ( p[1] > bmax[1] ) bmax[1] = p[1];
if ( p[2] > bmax[2] ) bmax[2] = p[2];
}
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
return sqrtf( dx*dx + dy*dy + dz*dz );
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
return sqrtf(dx * dx + dy * dy + dz * dz);
}
bool overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2) // return true if the two AABB's overlap.
bool overlapAABB(const float *bmin1, const float *bmax1, const float *bmin2, const float *bmax2) // return true if the two AABB's overlap.
{
if ( bmax2[0] < bmin1[0] ) return false; // if the maximum is less than our minimum on any axis
if ( bmax2[1] < bmin1[1] ) return false;
if ( bmax2[2] < bmin1[2] ) return false;
if (bmax2[0] < bmin1[0]) return false; // if the maximum is less than our minimum on any axis
if (bmax2[1] < bmin1[1]) return false;
if (bmax2[2] < bmin1[2]) return false;
if ( bmin2[0] > bmax1[0] ) return false; // if the minimum is greater than our maximum on any axis
if ( bmin2[1] > bmax1[1] ) return false; // if the minimum is greater than our maximum on any axis
if ( bmin2[2] > bmax1[2] ) return false; // if the minimum is greater than our maximum on any axis
if (bmin2[0] > bmax1[0]) return false; // if the minimum is greater than our maximum on any axis
if (bmin2[1] > bmax1[1]) return false; // if the minimum is greater than our maximum on any axis
if (bmin2[2] > bmax1[2]) return false; // if the minimum is greater than our maximum on any axis
return true; // the extents overlap
return true; // the extents overlap
}

View File

@@ -36,7 +36,6 @@
// http://www.amillionpixels.us
//
// This routine was released in 'snippet' form
// by John W. Ratcliff mailto:jratcliff@infiniplex.net
// on March 22, 2006.
@@ -51,15 +50,14 @@
// computes the best fit plane to a collection of data points.
// returns the plane equation as A,B,C,D format. (Ax+By+Cz+D)
bool getBestFitPlane(unsigned int vcount, // number of input data points
const float *points, // starting address of points array.
unsigned int vstride, // stride between input points.
const float *weights, // *optional point weighting values.
unsigned int wstride, // weight stride for each vertex.
float *plane);
bool getBestFitPlane(unsigned int vcount, // number of input data points
const float *points, // starting address of points array.
unsigned int vstride, // stride between input points.
const float *weights, // *optional point weighting values.
unsigned int wstride, // weight stride for each vertex.
float *plane);
float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax); // returns the diagonal distance
bool overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2); // return true if the two AABB's overlap.
float getBoundingRegion(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax); // returns the diagonal distance
bool overlapAABB(const float *bmin1, const float *bmax1, const float *bmin2, const float *bmax2); // return true if the two AABB's overlap.
#endif

View File

@@ -44,130 +44,123 @@
#include "float_math.h"
// computes the OBB for this set of points relative to this transform matrix.
void computeOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,const float *matrix)
void computeOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, const float *matrix)
{
const char *src = (const char *) points;
const char *src = (const char *)points;
float bmin[3] = { 1e9, 1e9, 1e9 };
float bmax[3] = { -1e9, -1e9, -1e9 };
float bmin[3] = {1e9, 1e9, 1e9};
float bmax[3] = {-1e9, -1e9, -1e9};
for (unsigned int i=0; i<vcount; i++)
{
const float *p = (const float *) src;
float t[3];
for (unsigned int i = 0; i < vcount; i++)
{
const float *p = (const float *)src;
float t[3];
fm_inverseRT(matrix, p, t ); // inverse rotate translate
fm_inverseRT(matrix, p, t); // inverse rotate translate
if ( t[0] < bmin[0] ) bmin[0] = t[0];
if ( t[1] < bmin[1] ) bmin[1] = t[1];
if ( t[2] < bmin[2] ) bmin[2] = t[2];
if (t[0] < bmin[0]) bmin[0] = t[0];
if (t[1] < bmin[1]) bmin[1] = t[1];
if (t[2] < bmin[2]) bmin[2] = t[2];
if ( t[0] > bmax[0] ) bmax[0] = t[0];
if ( t[1] > bmax[1] ) bmax[1] = t[1];
if ( t[2] > bmax[2] ) bmax[2] = t[2];
if (t[0] > bmax[0]) bmax[0] = t[0];
if (t[1] > bmax[1]) bmax[1] = t[1];
if (t[2] > bmax[2]) bmax[2] = t[2];
src+=pstride;
}
src += pstride;
}
sides[0] = bmax[0];
sides[1] = bmax[1];
sides[2] = bmax[2];
sides[0] = bmax[0];
sides[1] = bmax[1];
sides[2] = bmax[2];
if ( fabsf(bmin[0]) > sides[0] ) sides[0] = fabsf(bmin[0]);
if ( fabsf(bmin[1]) > sides[1] ) sides[1] = fabsf(bmin[1]);
if ( fabsf(bmin[2]) > sides[2] ) sides[2] = fabsf(bmin[2]);
sides[0]*=2.0f;
sides[1]*=2.0f;
sides[2]*=2.0f;
if (fabsf(bmin[0]) > sides[0]) sides[0] = fabsf(bmin[0]);
if (fabsf(bmin[1]) > sides[1]) sides[1] = fabsf(bmin[1]);
if (fabsf(bmin[2]) > sides[2]) sides[2] = fabsf(bmin[2]);
sides[0] *= 2.0f;
sides[1] *= 2.0f;
sides[2] *= 2.0f;
}
void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix)
void computeBestFitOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, float *matrix)
{
float bmin[3];
float bmax[3];
float bmin[3];
float bmax[3];
fm_getAABB(vcount, points, pstride, bmin, bmax);
fm_getAABB(vcount,points,pstride,bmin,bmax);
float center[3];
float center[3];
center[0] = (bmax[0] - bmin[0]) * 0.5f + bmin[0];
center[1] = (bmax[1] - bmin[1]) * 0.5f + bmin[1];
center[2] = (bmax[2] - bmin[2]) * 0.5f + bmin[2];
center[0] = (bmax[0]-bmin[0])*0.5f + bmin[0];
center[1] = (bmax[1]-bmin[1])*0.5f + bmin[1];
center[2] = (bmax[2]-bmin[2])*0.5f + bmin[2];
float ax = 0;
float ay = 0;
float az = 0;
float ax = 0;
float ay = 0;
float az = 0;
float sweep = 45.0f; // 180 degree sweep on all three axes.
float steps = 8.0f; // 16 steps on each axis.
float sweep = 45.0f; // 180 degree sweep on all three axes.
float steps = 8.0f; // 16 steps on each axis.
float bestVolume = 1e9;
float angle[3] = {0.f, 0.f, 0.f};
float bestVolume = 1e9;
float angle[3]={0.f,0.f,0.f};
while (sweep >= 1)
{
bool found = false;
while ( sweep >= 1 )
{
float stepsize = sweep / steps;
bool found = false;
for (float x = ax - sweep; x <= ax + sweep; x += stepsize)
{
for (float y = ay - sweep; y <= ay + sweep; y += stepsize)
{
for (float z = az - sweep; z <= az + sweep; z += stepsize)
{
float pmatrix[16];
float stepsize = sweep / steps;
fm_eulerMatrix(x * FM_DEG_TO_RAD, y * FM_DEG_TO_RAD, z * FM_DEG_TO_RAD, pmatrix);
for (float x=ax-sweep; x<=ax+sweep; x+=stepsize)
{
for (float y=ay-sweep; y<=ay+sweep; y+=stepsize)
{
for (float z=az-sweep; z<=az+sweep; z+=stepsize)
{
float pmatrix[16];
pmatrix[3 * 4 + 0] = center[0];
pmatrix[3 * 4 + 1] = center[1];
pmatrix[3 * 4 + 2] = center[2];
fm_eulerMatrix( x*FM_DEG_TO_RAD, y*FM_DEG_TO_RAD, z*FM_DEG_TO_RAD, pmatrix );
float psides[3];
pmatrix[3*4+0] = center[0];
pmatrix[3*4+1] = center[1];
pmatrix[3*4+2] = center[2];
computeOBB(vcount, points, pstride, psides, pmatrix);
float psides[3];
float volume = psides[0] * psides[1] * psides[2]; // the volume of the cube
computeOBB( vcount, points, pstride, psides, pmatrix );
if (volume <= bestVolume)
{
bestVolume = volume;
float volume = psides[0]*psides[1]*psides[2]; // the volume of the cube
sides[0] = psides[0];
sides[1] = psides[1];
sides[2] = psides[2];
if ( volume <= bestVolume )
{
bestVolume = volume;
angle[0] = ax;
angle[1] = ay;
angle[2] = az;
sides[0] = psides[0];
sides[1] = psides[1];
sides[2] = psides[2];
memcpy(matrix, pmatrix, sizeof(float) * 16);
found = true; // yes, we found an improvement.
}
}
}
}
angle[0] = ax;
angle[1] = ay;
angle[2] = az;
memcpy(matrix,pmatrix,sizeof(float)*16);
found = true; // yes, we found an improvement.
}
}
}
}
if ( found )
{
ax = angle[0];
ay = angle[1];
az = angle[2];
sweep*=0.5f; // sweep 1/2 the distance as the last time.
}
else
{
break; // no improvement, so just
}
}
if (found)
{
ax = angle[0];
ay = angle[1];
az = angle[2];
sweep *= 0.5f; // sweep 1/2 the distance as the last time.
}
else
{
break; // no improvement, so just
}
}
}

View File

@@ -36,8 +36,6 @@
// http://www.amillionpixels.us
//
void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix);
void computeBestFitOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, float *matrix);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,6 @@
namespace ConvexDecomposition
{
class HullResult
{
public:
@@ -44,110 +43,106 @@ public:
mNumIndices = 0;
mIndices = 0;
}
bool mPolygons; // true if indices represents polygons, false indices are triangles
unsigned int mNumOutputVertices; // number of vertices in the output hull
float *mOutputVertices; // array of vertices, 3 floats each x,y,z
unsigned int mNumFaces; // the number of faces produced
unsigned int mNumIndices; // the total number of indices
unsigned int *mIndices; // pointer to indices.
bool mPolygons; // true if indices represents polygons, false indices are triangles
unsigned int mNumOutputVertices; // number of vertices in the output hull
float *mOutputVertices; // array of vertices, 3 floats each x,y,z
unsigned int mNumFaces; // the number of faces produced
unsigned int mNumIndices; // the total number of indices
unsigned int *mIndices; // 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..
// 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_SKIN_WIDTH = (1<<2), // extrude hull based on this skin width
QF_DEFAULT = 0
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
QF_SKIN_WIDTH = (1 << 2), // extrude hull based on this skin width
QF_DEFAULT = 0
};
class HullDesc
{
public:
HullDesc(void)
{
mFlags = QF_DEFAULT;
mVcount = 0;
mVertices = 0;
mVertexStride = sizeof(float)*3;
mNormalEpsilon = 0.001f;
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
mMaxFaces = 4096;
mSkinWidth = 0.01f; // default is one centimeter
mFlags = QF_DEFAULT;
mVcount = 0;
mVertices = 0;
mVertexStride = sizeof(float) * 3;
mNormalEpsilon = 0.001f;
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
mMaxFaces = 4096;
mSkinWidth = 0.01f; // default is one centimeter
};
HullDesc(HullFlag flag,
unsigned int vcount,
const float *vertices,
unsigned int stride)
unsigned int vcount,
const float *vertices,
unsigned int stride)
{
mFlags = flag;
mVcount = vcount;
mVertices = vertices;
mVertexStride = stride;
mNormalEpsilon = 0.001f;
mMaxVertices = 4096;
mSkinWidth = 0.01f; // default is one centimeter
mFlags = flag;
mVcount = vcount;
mVertices = vertices;
mVertexStride = stride;
mNormalEpsilon = 0.001f;
mMaxVertices = 4096;
mSkinWidth = 0.01f; // default is one centimeter
}
bool HasHullFlag(HullFlag flag) const
{
if ( mFlags & flag ) return true;
if (mFlags & flag) return true;
return false;
}
void SetHullFlag(HullFlag flag)
{
mFlags|=flag;
mFlags |= flag;
}
void ClearHullFlag(HullFlag flag)
{
mFlags&=~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 float *mVertices; // the array of vertices.
unsigned int mVertexStride; // the stride of each vertex, in bytes.
float mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
float mSkinWidth;
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
unsigned int mMaxFaces;
unsigned int mFlags; // flags to use when generating the convex hull.
unsigned int mVcount; // number of vertices in the input point cloud
const float *mVertices; // the array of vertices.
unsigned int mVertexStride; // the stride of each vertex, in bytes.
float mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
float mSkinWidth;
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
unsigned int mMaxFaces;
};
enum HullError
{
QE_OK, // success!
QE_FAIL // failed.
QE_OK, // success!
QE_FAIL // failed.
};
class HullLibrary
{
public:
HullError CreateConvexHull(const HullDesc &desc, // describes the input request
HullResult &result); // contains the resulst
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.
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
private:
void BringOutYourDead(const float *verts, unsigned int vcount, float *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount);
void BringOutYourDead(const float *verts,unsigned int vcount, float *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount);
bool CleanupVertices(unsigned int svcount,
const float *svertices,
unsigned int stride,
unsigned int &vcount, // output number of vertices
float *vertices, // location to store the results.
float normalepsilon,
float *scale);
bool CleanupVertices(unsigned int svcount,
const float *svertices,
unsigned int stride,
unsigned int &vcount, // output number of vertices
float *vertices, // location to store the results.
float normalepsilon,
float *scale);
};
}
} // namespace ConvexDecomposition
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,7 @@
#ifndef CD_WAVEFRONT_OBJ_H
#define CD_WAVEFRONT_OBJ_H
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -38,25 +36,22 @@
// http://www.amillionpixels.us
//
namespace ConvexDecomposition
{
class WavefrontObj
{
public:
WavefrontObj(void);
~WavefrontObj(void);
WavefrontObj(void);
~WavefrontObj(void);
unsigned int loadObj(const char *fname); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
unsigned int loadObj(const char *fname); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
int mVertexCount;
int mTriCount;
int *mIndices;
float *mVertices;
int mVertexCount;
int mTriCount;
int *mIndices;
float *mVertices;
};
}
} // namespace ConvexDecomposition
#endif

View File

@@ -49,165 +49,156 @@
#include "splitplane.h"
#include "ConvexDecomposition.h"
#define WSCALE 4
#define CONCAVE_THRESH 0.05f
namespace ConvexDecomposition
{
unsigned int getDebugColor(void)
{
static unsigned int colors[8] =
{
0xFF0000,
0x00FF00,
0x0000FF,
0xFFFF00,
0x00FFFF,
0xFF00FF,
0xFFFFFF,
0xFF8040
};
{
0xFF0000,
0x00FF00,
0x0000FF,
0xFFFF00,
0x00FFFF,
0xFF00FF,
0xFFFFFF,
0xFF8040};
static int count = 0;
count++;
if ( count == 8 ) count = 0;
if (count == 8) count = 0;
assert( count >= 0 && count < 8 );
assert(count >= 0 && count < 8);
unsigned int color = colors[count];
return color;
return color;
}
class Wpoint
{
public:
Wpoint(const Vector3d &p,float w)
{
mPoint = p;
mWeight = w;
}
Wpoint(const Vector3d &p, float w)
{
mPoint = p;
mWeight = w;
}
Vector3d mPoint;
float mWeight;
Vector3d mPoint;
float mWeight;
};
typedef std::vector< Wpoint > WpointVector;
typedef std::vector<Wpoint> WpointVector;
static inline float DistToPt(const float *p,const float *plane)
static inline float DistToPt(const float *p, const float *plane)
{
float x = p[0];
float y = p[1];
float z = p[2];
float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
return d;
}
static void intersect(const float *p1,const float *p2,float *split,const float *plane)
static void intersect(const float *p1, const float *p2, float *split, const float *plane)
{
float dp1 = DistToPt(p1, plane);
float dp1 = DistToPt(p1,plane);
float dir[3];
float dir[3];
dir[0] = p2[0] - p1[0];
dir[1] = p2[1] - p1[1];
dir[2] = p2[2] - p1[2];
dir[0] = p2[0] - p1[0];
dir[1] = p2[1] - p1[1];
dir[2] = p2[2] - p1[2];
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
float dot2 = dp1 - plane[3];
float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2];
float dot2 = dp1 - plane[3];
float t = -(plane[3] + dot2) / dot1;
float t = -(plane[3] + dot2 ) / dot1;
split[0] = (dir[0]*t)+p1[0];
split[1] = (dir[1]*t)+p1[1];
split[2] = (dir[2]*t)+p1[2];
split[0] = (dir[0] * t) + p1[0];
split[1] = (dir[1] * t) + p1[1];
split[2] = (dir[2] * t) + p1[2];
}
class CTri
{
public:
CTri(void) { };
CTri(void){};
CTri(const float *p1,const float *p2,const float *p3,unsigned int i1,unsigned int i2,unsigned int i3)
{
mProcessed = 0;
mI1 = i1;
mI2 = i2;
mI3 = i3;
CTri(const float *p1, const float *p2, const float *p3, unsigned int i1, unsigned int i2, unsigned int i3)
{
mProcessed = 0;
mI1 = i1;
mI2 = i2;
mI3 = i3;
mP1.Set(p1);
mP2.Set(p2);
mP3.Set(p3);
mP1.Set(p1);
mP2.Set(p2);
mP3.Set(p3);
mPlaneD = mNormal.ComputePlane(mP1,mP2,mP3);
mPlaneD = mNormal.ComputePlane(mP1, mP2, mP3);
}
float Facing(const CTri &t)
{
float Facing(const CTri &t)
{
float d = mNormal.Dot(t.mNormal);
return d;
}
}
// clip this line segment against this triangle.
bool clip(const Vector3d &start,Vector3d &end) const
{
Vector3d sect;
bool hit = lineIntersectsTriangle(start.Ptr(), end.Ptr(), mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), sect.Ptr() );
if ( hit )
{
end = sect;
}
return hit;
}
bool Concave(const Vector3d &p,float &distance,Vector3d &n) const
// clip this line segment against this triangle.
bool clip(const Vector3d &start, Vector3d &end) const
{
n.NearestPointInTriangle(p,mP1,mP2,mP3);
Vector3d sect;
bool hit = lineIntersectsTriangle(start.Ptr(), end.Ptr(), mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), sect.Ptr());
if (hit)
{
end = sect;
}
return hit;
}
bool Concave(const Vector3d &p, float &distance, Vector3d &n) const
{
n.NearestPointInTriangle(p, mP1, mP2, mP3);
distance = p.Distance(n);
return true;
}
void addTri(unsigned int *indices,unsigned int i1,unsigned int i2,unsigned int i3,unsigned int &tcount) const
void addTri(unsigned int *indices, unsigned int i1, unsigned int i2, unsigned int i3, unsigned int &tcount) const
{
indices[tcount*3+0] = i1;
indices[tcount*3+1] = i2;
indices[tcount*3+2] = i3;
indices[tcount * 3 + 0] = i1;
indices[tcount * 3 + 1] = i2;
indices[tcount * 3 + 2] = i3;
tcount++;
}
float getVolume(ConvexDecompInterface *callback) const
{
unsigned int indices[8*3];
unsigned int indices[8 * 3];
unsigned int tcount = 0;
unsigned int tcount = 0;
addTri(indices, 0, 1, 2, tcount);
addTri(indices, 3, 4, 5, tcount);
addTri(indices,0,1,2,tcount);
addTri(indices,3,4,5,tcount);
addTri(indices, 0, 3, 4, tcount);
addTri(indices, 0, 4, 1, tcount);
addTri(indices,0,3,4,tcount);
addTri(indices,0,4,1,tcount);
addTri(indices, 1, 4, 5, tcount);
addTri(indices, 1, 5, 2, tcount);
addTri(indices,1,4,5,tcount);
addTri(indices,1,5,2,tcount);
addTri(indices, 0, 3, 5, tcount);
addTri(indices, 0, 5, 2, tcount);
addTri(indices,0,3,5,tcount);
addTri(indices,0,5,2,tcount);
const float *vertices = mP1.Ptr();
const float *vertices = mP1.Ptr();
if ( callback )
if (callback)
{
unsigned int color = getDebugColor();
@@ -228,139 +219,134 @@ public:
callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00);
#else
for (unsigned int i=0; i<tcount; i++)
for (unsigned int i = 0; i < tcount; i++)
{
unsigned int i1 = indices[i*3+0];
unsigned int i2 = indices[i*3+1];
unsigned int i3 = indices[i*3+2];
unsigned int i1 = indices[i * 3 + 0];
unsigned int i2 = indices[i * 3 + 1];
unsigned int i3 = indices[i * 3 + 2];
const float *p1 = &vertices[ i1*3 ];
const float *p2 = &vertices[ i2*3 ];
const float *p3 = &vertices[ i3*3 ];
callback->ConvexDebugTri(p1,p2,p3,color);
const float *p1 = &vertices[i1 * 3];
const float *p2 = &vertices[i2 * 3];
const float *p3 = &vertices[i3 * 3];
callback->ConvexDebugTri(p1, p2, p3, color);
}
#endif
}
float v = computeMeshVolume(mP1.Ptr(), tcount, indices );
float v = computeMeshVolume(mP1.Ptr(), tcount, indices);
return v;
}
float raySect(const Vector3d &p,const Vector3d &dir,Vector3d &sect) const
float raySect(const Vector3d &p, const Vector3d &dir, Vector3d &sect) const
{
float plane[4];
plane[0] = mNormal.x;
plane[1] = mNormal.y;
plane[2] = mNormal.z;
plane[3] = mPlaneD;
plane[0] = mNormal.x;
plane[1] = mNormal.y;
plane[2] = mNormal.z;
plane[3] = mPlaneD;
Vector3d dest = p+dir*100000;
Vector3d dest = p + dir * 100000;
intersect( p.Ptr(), dest.Ptr(), sect.Ptr(), plane );
return sect.Distance(p); // return the intersection distance.
intersect(p.Ptr(), dest.Ptr(), sect.Ptr(), plane);
return sect.Distance(p); // return the intersection distance.
}
float planeDistance(const Vector3d &p) const
{
float planeDistance(const Vector3d &p) const
{
float plane[4];
plane[0] = mNormal.x;
plane[1] = mNormal.y;
plane[2] = mNormal.z;
plane[3] = mPlaneD;
plane[0] = mNormal.x;
plane[1] = mNormal.y;
plane[2] = mNormal.z;
plane[3] = mPlaneD;
return DistToPt( p.Ptr(), plane );
}
return DistToPt(p.Ptr(), plane);
}
bool samePlane(const CTri &t) const
{
const float THRESH = 0.001f;
float dd = fabsf( t.mPlaneD - mPlaneD );
if ( dd > THRESH ) return false;
dd = fabsf( t.mNormal.x - mNormal.x );
if ( dd > THRESH ) return false;
dd = fabsf( t.mNormal.y - mNormal.y );
if ( dd > THRESH ) return false;
dd = fabsf( t.mNormal.z - mNormal.z );
if ( dd > THRESH ) return false;
return true;
float dd = fabsf(t.mPlaneD - mPlaneD);
if (dd > THRESH) return false;
dd = fabsf(t.mNormal.x - mNormal.x);
if (dd > THRESH) return false;
dd = fabsf(t.mNormal.y - mNormal.y);
if (dd > THRESH) return false;
dd = fabsf(t.mNormal.z - mNormal.z);
if (dd > THRESH) return false;
return true;
}
bool hasIndex(unsigned int i) const
{
if ( i == mI1 || i == mI2 || i == mI3 ) return true;
if (i == mI1 || i == mI2 || i == mI3) return true;
return false;
}
bool sharesEdge(const CTri &t) const
{
bool ret = false;
unsigned int count = 0;
bool sharesEdge(const CTri &t) const
{
bool ret = false;
unsigned int count = 0;
if ( t.hasIndex(mI1) ) count++;
if ( t.hasIndex(mI2) ) count++;
if ( t.hasIndex(mI3) ) count++;
if (t.hasIndex(mI1)) count++;
if (t.hasIndex(mI2)) count++;
if (t.hasIndex(mI3)) count++;
if ( count >= 2 ) ret = true;
if (count >= 2) ret = true;
return ret;
}
return ret;
}
void debug(unsigned int color,ConvexDecompInterface *callback)
{
callback->ConvexDebugTri( mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), color );
callback->ConvexDebugTri( mP1.Ptr(), mP1.Ptr(), mNear1.Ptr(), 0xFF0000 );
callback->ConvexDebugTri( mP2.Ptr(), mP2.Ptr(), mNear2.Ptr(), 0xFF0000 );
callback->ConvexDebugTri( mP2.Ptr(), mP3.Ptr(), mNear3.Ptr(), 0xFF0000 );
callback->ConvexDebugPoint( mNear1.Ptr(), 0.01f, 0xFF0000 );
callback->ConvexDebugPoint( mNear2.Ptr(), 0.01f, 0xFF0000 );
callback->ConvexDebugPoint( mNear3.Ptr(), 0.01f, 0xFF0000 );
}
void debug(unsigned int color, ConvexDecompInterface *callback)
{
callback->ConvexDebugTri(mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), color);
callback->ConvexDebugTri(mP1.Ptr(), mP1.Ptr(), mNear1.Ptr(), 0xFF0000);
callback->ConvexDebugTri(mP2.Ptr(), mP2.Ptr(), mNear2.Ptr(), 0xFF0000);
callback->ConvexDebugTri(mP2.Ptr(), mP3.Ptr(), mNear3.Ptr(), 0xFF0000);
callback->ConvexDebugPoint(mNear1.Ptr(), 0.01f, 0xFF0000);
callback->ConvexDebugPoint(mNear2.Ptr(), 0.01f, 0xFF0000);
callback->ConvexDebugPoint(mNear3.Ptr(), 0.01f, 0xFF0000);
}
float area(void)
{
float a = mConcavity*mP1.Area(mP2,mP3);
return a;
}
float area(void)
{
float a = mConcavity * mP1.Area(mP2, mP3);
return a;
}
void addWeighted(WpointVector &list,ConvexDecompInterface *callback)
{
Wpoint p1(mP1,mC1);
Wpoint p2(mP2,mC2);
Wpoint p3(mP3,mC3);
void addWeighted(WpointVector &list, ConvexDecompInterface *callback)
{
Wpoint p1(mP1, mC1);
Wpoint p2(mP2, mC2);
Wpoint p3(mP3, mC3);
Vector3d d1 = mNear1 - mP1;
Vector3d d2 = mNear2 - mP2;
Vector3d d3 = mNear3 - mP3;
d1*=WSCALE;
d2*=WSCALE;
d3*=WSCALE;
d1 *= WSCALE;
d2 *= WSCALE;
d3 *= WSCALE;
d1 = d1 + mP1;
d2 = d2 + mP2;
d3 = d3 + mP3;
d3 = d3 + mP3;
Wpoint p4(d1,mC1);
Wpoint p5(d2,mC2);
Wpoint p6(d3,mC3);
Wpoint p4(d1, mC1);
Wpoint p5(d2, mC2);
Wpoint p6(d3, mC3);
list.push_back(p1);
list.push_back(p2);
list.push_back(p3);
list.push_back(p1);
list.push_back(p2);
list.push_back(p3);
list.push_back(p4);
list.push_back(p5);
list.push_back(p6);
list.push_back(p4);
list.push_back(p5);
list.push_back(p6);
#if 0
callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
@@ -387,39 +373,35 @@ public:
callback->ConvexDebugPoint( np3.Ptr(), 0.01F, 0XFF00FF );
#endif
}
}
Vector3d mP1;
Vector3d mP2;
Vector3d mP3;
Vector3d mNear1;
Vector3d mNear2;
Vector3d mNear3;
Vector3d mNormal;
float mPlaneD;
float mConcavity;
float mC1;
float mC2;
float mC3;
unsigned int mI1;
unsigned int mI2;
unsigned int mI3;
int mProcessed; // already been added...
Vector3d mP1;
Vector3d mP2;
Vector3d mP3;
Vector3d mNear1;
Vector3d mNear2;
Vector3d mNear3;
Vector3d mNormal;
float mPlaneD;
float mConcavity;
float mC1;
float mC2;
float mC3;
unsigned int mI1;
unsigned int mI2;
unsigned int mI3;
int mProcessed; // already been added...
};
typedef std::vector< CTri > CTriVector;
typedef std::vector<CTri> CTriVector;
bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback,const CTriVector &input_mesh)
bool featureMatch(CTri &m, const CTriVector &tris, ConvexDecompInterface *callback, const CTriVector &input_mesh)
{
bool ret = false;
bool ret = false;
float neardot = 0.707f;
float neardot = 0.707f;
m.mConcavity = 0;
m.mConcavity = 0;
//gLog->Display("*********** FEATURE MATCH *************\r\n");
//gLog->Display("Plane: %0.4f,%0.4f,%0.4f %0.4f\r\n", m.mNormal.x, m.mNormal.y, m.mNormal.z, m.mPlaneD );
@@ -429,87 +411,81 @@ bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback
CTri nearest;
for (i=tris.begin(); i!=tris.end(); ++i)
for (i = tris.begin(); i != tris.end(); ++i)
{
const CTri &t = (*i);
//gLog->Display(" HullPlane: %0.4f,%0.4f,%0.4f %0.4f\r\n", t.mNormal.x, t.mNormal.y, t.mNormal.z, t.mPlaneD );
//gLog->Display(" HullPlane: %0.4f,%0.4f,%0.4f %0.4f\r\n", t.mNormal.x, t.mNormal.y, t.mNormal.z, t.mPlaneD );
if ( t.samePlane(m) )
if (t.samePlane(m))
{
//gLog->Display("*** PLANE MATCH!!!\r\n");
ret = false;
break;
}
float dot = t.mNormal.Dot(m.mNormal);
float dot = t.mNormal.Dot(m.mNormal);
if ( dot > neardot )
{
if (dot > neardot)
{
float d1 = t.planeDistance(m.mP1);
float d2 = t.planeDistance(m.mP2);
float d3 = t.planeDistance(m.mP3);
float d1 = t.planeDistance( m.mP1 );
float d2 = t.planeDistance( m.mP2 );
float d3 = t.planeDistance( m.mP3 );
if (d1 > 0.001f || d2 > 0.001f || d3 > 0.001f) // can't be near coplaner!
{
neardot = dot;
if ( d1 > 0.001f || d2 > 0.001f || d3 > 0.001f ) // can't be near coplaner!
{
Vector3d n1, n2, n3;
neardot = dot;
Vector3d n1,n2,n3;
t.raySect( m.mP1, m.mNormal, m.mNear1 );
t.raySect( m.mP2, m.mNormal, m.mNear2 );
t.raySect( m.mP3, m.mNormal, m.mNear3 );
t.raySect(m.mP1, m.mNormal, m.mNear1);
t.raySect(m.mP2, m.mNormal, m.mNear2);
t.raySect(m.mP3, m.mNormal, m.mNear3);
nearest = t;
ret = true;
}
}
ret = true;
}
}
}
if ( ret )
if (ret)
{
if ( 0 )
{
CTriVector::const_iterator i;
for (i=input_mesh.begin(); i!=input_mesh.end(); ++i)
{
const CTri &c = (*i);
if ( c.mI1 != m.mI1 && c.mI2 != m.mI2 && c.mI3 != m.mI3 )
{
c.clip( m.mP1, m.mNear1 );
c.clip( m.mP2, m.mNear2 );
c.clip( m.mP3, m.mNear3 );
}
}
}
if (0)
{
CTriVector::const_iterator i;
for (i = input_mesh.begin(); i != input_mesh.end(); ++i)
{
const CTri &c = (*i);
if (c.mI1 != m.mI1 && c.mI2 != m.mI2 && c.mI3 != m.mI3)
{
c.clip(m.mP1, m.mNear1);
c.clip(m.mP2, m.mNear2);
c.clip(m.mP3, m.mNear3);
}
}
}
//gLog->Display("*********************************************\r\n");
//gLog->Display(" HullPlaneNearest: %0.4f,%0.4f,%0.4f %0.4f\r\n", nearest.mNormal.x, nearest.mNormal.y, nearest.mNormal.z, nearest.mPlaneD );
//gLog->Display("*********************************************\r\n");
//gLog->Display(" HullPlaneNearest: %0.4f,%0.4f,%0.4f %0.4f\r\n", nearest.mNormal.x, nearest.mNormal.y, nearest.mNormal.z, nearest.mPlaneD );
m.mC1 = m.mP1.Distance( m.mNear1 );
m.mC2 = m.mP2.Distance( m.mNear2 );
m.mC3 = m.mP3.Distance( m.mNear3 );
m.mC1 = m.mP1.Distance(m.mNear1);
m.mC2 = m.mP2.Distance(m.mNear2);
m.mC3 = m.mP3.Distance(m.mNear3);
m.mConcavity = m.mC1;
if ( m.mC2 > m.mConcavity ) m.mConcavity = m.mC2;
if ( m.mC3 > m.mConcavity ) m.mConcavity = m.mC3;
if (m.mC2 > m.mConcavity) m.mConcavity = m.mC2;
if (m.mC3 > m.mConcavity) m.mConcavity = m.mC3;
#if 0
#if 0
callback->ConvexDebugTri( m.mP1.Ptr(), m.mP2.Ptr(), m.mP3.Ptr(), 0x00FF00 );
callback->ConvexDebugTri( m.mNear1.Ptr(), m.mNear2.Ptr(), m.mNear3.Ptr(), 0xFF0000 );
callback->ConvexDebugTri( m.mP1.Ptr(), m.mP1.Ptr(), m.mNear1.Ptr(), 0xFFFF00 );
callback->ConvexDebugTri( m.mP2.Ptr(), m.mP2.Ptr(), m.mNear2.Ptr(), 0xFFFF00 );
callback->ConvexDebugTri( m.mP3.Ptr(), m.mP3.Ptr(), m.mNear3.Ptr(), 0xFFFF00 );
#endif
#endif
}
else
{
@@ -520,83 +496,78 @@ bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback
return ret;
}
bool isFeatureTri(CTri &t,CTriVector &flist,float fc,ConvexDecompInterface *callback,unsigned int color)
bool isFeatureTri(CTri &t, CTriVector &flist, float fc, ConvexDecompInterface *callback, unsigned int color)
{
bool ret = false;
bool ret = false;
if ( t.mProcessed == 0 ) // if not already processed
{
if (t.mProcessed == 0) // if not already processed
{
float c = t.mConcavity / fc; // must be within 80% of the concavity of the parent.
float c = t.mConcavity / fc; // must be within 80% of the concavity of the parent.
if ( c > 0.85f )
{
// see if this triangle is a 'feature' triangle. Meaning it shares an
// edge with any existing feature triangle and is within roughly the same
// concavity of the parent.
if ( flist.size() )
if (c > 0.85f)
{
// see if this triangle is a 'feature' triangle. Meaning it shares an
// edge with any existing feature triangle and is within roughly the same
// concavity of the parent.
if (flist.size())
{
CTriVector::iterator i;
for (i=flist.begin(); i!=flist.end(); ++i)
{
CTri &ftri = (*i);
if ( ftri.sharesEdge(t) )
{
t.mProcessed = 2; // it is now part of a feature.
flist.push_back(t); // add it to the feature list.
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
ret = true;
break;
}
CTriVector::iterator i;
for (i = flist.begin(); i != flist.end(); ++i)
{
CTri &ftri = (*i);
if (ftri.sharesEdge(t))
{
t.mProcessed = 2; // it is now part of a feature.
flist.push_back(t); // add it to the feature list.
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
ret = true;
break;
}
}
}
else
{
t.mProcessed = 2;
flist.push_back(t); // add it to the feature list.
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
flist.push_back(t); // add it to the feature list.
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
ret = true;
}
}
else
{
t.mProcessed = 1; // eliminated for this feature, but might be valid for the next one..
}
}
return ret;
}
else
{
t.mProcessed = 1; // eliminated for this feature, but might be valid for the next one..
}
}
return ret;
}
float computeConcavity(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane, // plane equation to split on
float &volume)
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane, // plane equation to split on
float &volume)
{
float cret = 0;
volume = 1;
HullResult result;
HullLibrary hl;
HullDesc desc;
HullResult result;
HullLibrary hl;
HullDesc desc;
desc.mMaxFaces = 256;
desc.mMaxVertices = 256;
desc.SetHullFlag(QF_TRIANGLES);
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float) * 3;
desc.mVcount = vcount;
desc.mVertices = vertices;
desc.mVertexStride = sizeof(float)*3;
HullError ret = hl.CreateConvexHull(desc, result);
HullError ret = hl.CreateConvexHull(desc,result);
if ( ret == QE_OK )
{
if (ret == QE_OK)
{
#if 0
float bmin[3];
float bmax[3];
@@ -612,7 +583,7 @@ float computeConcavity(unsigned int vcount,
center.z = bmin[2] + dz*0.5f;
#endif
volume = computeMeshVolume2( result.mOutputVertices, result.mNumFaces, result.mIndices );
volume = computeMeshVolume2(result.mOutputVertices, result.mNumFaces, result.mIndices);
#if 1
// ok..now..for each triangle on the original mesh..
@@ -621,87 +592,81 @@ float computeConcavity(unsigned int vcount,
CTriVector tris;
for (unsigned int i=0; i<result.mNumFaces; i++)
{
unsigned int i1 = *source++;
unsigned int i2 = *source++;
unsigned int i3 = *source++;
for (unsigned int i = 0; i < result.mNumFaces; i++)
{
unsigned int i1 = *source++;
unsigned int i2 = *source++;
unsigned int i3 = *source++;
const float *p1 = &result.mOutputVertices[i1*3];
const float *p2 = &result.mOutputVertices[i2*3];
const float *p3 = &result.mOutputVertices[i3*3];
const float *p1 = &result.mOutputVertices[i1 * 3];
const float *p2 = &result.mOutputVertices[i2 * 3];
const float *p3 = &result.mOutputVertices[i3 * 3];
// callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF);
// callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF);
CTri t(p1,p2,p3,i1,i2,i3); //
CTri t(p1, p2, p3, i1, i2, i3); //
tris.push_back(t);
}
// we have not pre-computed the plane equation for each triangle in the convex hull..
// we have not pre-computed the plane equation for each triangle in the convex hull..
float totalVolume = 0;
CTriVector ftris; // 'feature' triangles.
CTriVector ftris; // 'feature' triangles.
const unsigned int *src = indices;
float maxc = 0;
float maxc=0;
if ( 1 )
if (1)
{
CTriVector input_mesh;
if ( 1 )
{
const unsigned int *src = indices;
for (unsigned int i=0; i<tcount; i++)
{
unsigned int i1 = *src++;
unsigned int i2 = *src++;
unsigned int i3 = *src++;
const float *p1 = &vertices[i1*3];
const float *p2 = &vertices[i2*3];
const float *p3 = &vertices[i3*3];
CTri t(p1,p2,p3,i1,i2,i3);
input_mesh.push_back(t);
}
}
CTri maxctri;
for (unsigned int i=0; i<tcount; i++)
CTriVector input_mesh;
if (1)
{
unsigned int i1 = *src++;
unsigned int i2 = *src++;
unsigned int i3 = *src++;
const float *p1 = &vertices[i1*3];
const float *p2 = &vertices[i2*3];
const float *p3 = &vertices[i3*3];
CTri t(p1,p2,p3,i1,i2,i3);
featureMatch(t, tris, callback, input_mesh );
if ( t.mConcavity > CONCAVE_THRESH )
const unsigned int *src = indices;
for (unsigned int i = 0; i < tcount; i++)
{
unsigned int i1 = *src++;
unsigned int i2 = *src++;
unsigned int i3 = *src++;
if ( t.mConcavity > maxc )
{
maxc = t.mConcavity;
maxctri = t;
}
const float *p1 = &vertices[i1 * 3];
const float *p2 = &vertices[i2 * 3];
const float *p3 = &vertices[i3 * 3];
float v = t.getVolume(0);
totalVolume+=v;
ftris.push_back(t);
}
CTri t(p1, p2, p3, i1, i2, i3);
input_mesh.push_back(t);
}
}
CTri maxctri;
for (unsigned int i = 0; i < tcount; i++)
{
unsigned int i1 = *src++;
unsigned int i2 = *src++;
unsigned int i3 = *src++;
const float *p1 = &vertices[i1 * 3];
const float *p2 = &vertices[i2 * 3];
const float *p3 = &vertices[i3 * 3];
CTri t(p1, p2, p3, i1, i2, i3);
featureMatch(t, tris, callback, input_mesh);
if (t.mConcavity > CONCAVE_THRESH)
{
if (t.mConcavity > maxc)
{
maxc = t.mConcavity;
maxctri = t;
}
float v = t.getVolume(0);
totalVolume += v;
ftris.push_back(t);
}
}
}
@@ -786,12 +751,11 @@ float computeConcavity(unsigned int vcount,
cret = totalVolume;
hl.ReleaseResult(result);
}
hl.ReleaseResult(result);
}
#endif
return cret;
}
}
} // namespace ConvexDecomposition

View File

@@ -36,25 +36,20 @@
// http://www.amillionpixels.us
//
namespace ConvexDecomposition
{
class ConvexDecompInterface;
// compute's how 'concave' this object is and returns the total volume of the
// convex hull as well as the volume of the 'concavity' which was found.
float computeConcavity(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane,
float &volume);
}
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane,
float &volume);
} // namespace ConvexDecomposition
#endif

View File

@@ -6,7 +6,6 @@
#include "fitsphere.h"
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -53,27 +52,26 @@ from "Graphics Gems", Academic Press, 1990
/* The abs() of all coordinates must be < BIGNUMBER */
/* Code written by Jack Ritter and Lyle Rains. */
#define BIGNUMBER 100000000.0 /* hundred million */
#define BIGNUMBER 100000000.0 /* hundred million */
static inline void Set(float *n,float x,float y,float z)
static inline void Set(float *n, float x, float y, float z)
{
n[0] = x;
n[1] = y;
n[2] = z;
}
static inline void Copy(float *dest,const float *source)
static inline void Copy(float *dest, const float *source)
{
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
}
float computeBoundingSphere(unsigned int vcount,const float *points,float *center)
float computeBoundingSphere(unsigned int vcount, const float *points, float *center)
{
float mRadius;
float mRadius2;
float mRadius;
float mRadius2;
float xmin[3];
float xmax[3];
@@ -84,119 +82,116 @@ float computeBoundingSphere(unsigned int vcount,const float *points,float *cente
float dia1[3];
float dia2[3];
/* FIRST PASS: find 6 minima/maxima points */
Set(xmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
Set(xmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
Set(ymin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
Set(ymax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
Set(zmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
Set(zmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
/* FIRST PASS: find 6 minima/maxima points */
Set(xmin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
Set(xmax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
Set(ymin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
Set(ymax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
Set(zmin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
Set(zmax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
for (unsigned i=0; i<vcount; i++)
for (unsigned i = 0; i < vcount; i++)
{
const float *caller_p = &points[i*3];
const float *caller_p = &points[i * 3];
if (caller_p[0]<xmin[0])
Copy(xmin,caller_p); /* New xminimum point */
if (caller_p[0]>xmax[0])
Copy(xmax,caller_p);
if (caller_p[1]<ymin[1])
Copy(ymin,caller_p);
if (caller_p[1]>ymax[1])
Copy(ymax,caller_p);
if (caller_p[2]<zmin[2])
Copy(zmin,caller_p);
if (caller_p[2]>zmax[2])
Copy(zmax,caller_p);
if (caller_p[0] < xmin[0])
Copy(xmin, caller_p); /* New xminimum point */
if (caller_p[0] > xmax[0])
Copy(xmax, caller_p);
if (caller_p[1] < ymin[1])
Copy(ymin, caller_p);
if (caller_p[1] > ymax[1])
Copy(ymax, caller_p);
if (caller_p[2] < zmin[2])
Copy(zmin, caller_p);
if (caller_p[2] > zmax[2])
Copy(zmax, caller_p);
}
/* Set xspan = distance between the 2 points xmin & xmax (squared) */
float dx = xmax[0] - xmin[0];
float dy = xmax[1] - xmin[1];
float dz = xmax[2] - xmin[2];
float xspan = dx*dx + dy*dy + dz*dz;
/* Set xspan = distance between the 2 points xmin & xmax (squared) */
float dx = xmax[0] - xmin[0];
float dy = xmax[1] - xmin[1];
float dz = xmax[2] - xmin[2];
float xspan = dx * dx + dy * dy + dz * dz;
/* Same for y & z spans */
dx = ymax[0] - ymin[0];
dy = ymax[1] - ymin[1];
dz = ymax[2] - ymin[2];
float yspan = dx*dx + dy*dy + dz*dz;
/* Same for y & z spans */
dx = ymax[0] - ymin[0];
dy = ymax[1] - ymin[1];
dz = ymax[2] - ymin[2];
float yspan = dx * dx + dy * dy + dz * dz;
dx = zmax[0] - zmin[0];
dy = zmax[1] - zmin[1];
dz = zmax[2] - zmin[2];
float zspan = dx*dx + dy*dy + dz*dz;
dx = zmax[0] - zmin[0];
dy = zmax[1] - zmin[1];
dz = zmax[2] - zmin[2];
float zspan = dx * dx + dy * dy + dz * dz;
/* Set points dia1 & dia2 to the maximally separated pair */
Copy(dia1,xmin);
Copy(dia2,xmax); /* assume xspan biggest */
float maxspan = xspan;
/* Set points dia1 & dia2 to the maximally separated pair */
Copy(dia1, xmin);
Copy(dia2, xmax); /* assume xspan biggest */
float maxspan = xspan;
if (yspan>maxspan)
if (yspan > maxspan)
{
maxspan = yspan;
Copy(dia1,ymin);
Copy(dia2,ymax);
maxspan = yspan;
Copy(dia1, ymin);
Copy(dia2, ymax);
}
if (zspan>maxspan)
if (zspan > maxspan)
{
Copy(dia1,zmin);
Copy(dia2,zmax);
Copy(dia1, zmin);
Copy(dia2, zmax);
}
/* dia1,dia2 is a diameter of initial sphere */
/* calc initial center */
center[0] = (dia1[0] + dia2[0]) * 0.5f;
center[1] = (dia1[1] + dia2[1]) * 0.5f;
center[2] = (dia1[2] + dia2[2]) * 0.5f;
/* dia1,dia2 is a diameter of initial sphere */
/* calc initial center */
center[0] = (dia1[0]+dia2[0])*0.5f;
center[1] = (dia1[1]+dia2[1])*0.5f;
center[2] = (dia1[2]+dia2[2])*0.5f;
/* calculate initial radius**2 and radius */
/* calculate initial radius**2 and radius */
dx = dia2[0] - center[0]; /* x component of radius vector */
dy = dia2[1] - center[1]; /* y component of radius vector */
dz = dia2[2] - center[2]; /* z component of radius vector */
dx = dia2[0]-center[0]; /* x component of radius vector */
dy = dia2[1]-center[1]; /* y component of radius vector */
dz = dia2[2]-center[2]; /* z component of radius vector */
mRadius2 = dx * dx + dy * dy + dz * dz;
mRadius = float(sqrt(mRadius2));
mRadius2 = dx*dx + dy*dy + dz*dz;
mRadius = float(sqrt(mRadius2));
/* SECOND PASS: increment current sphere */
/* SECOND PASS: increment current sphere */
if ( 1 )
if (1)
{
for (unsigned i=0; i<vcount; i++)
for (unsigned i = 0; i < vcount; i++)
{
const float *caller_p = &points[i*3];
const float *caller_p = &points[i * 3];
dx = caller_p[0]-center[0];
dy = caller_p[1]-center[1];
dz = caller_p[2]-center[2];
dx = caller_p[0] - center[0];
dy = caller_p[1] - center[1];
dz = caller_p[2] - center[2];
float old_to_p_sq = dx*dx + dy*dy + dz*dz;
float old_to_p_sq = dx * dx + dy * dy + dz * dz;
if (old_to_p_sq > mRadius2) /* do r**2 test first */
{ /* this point is outside of current sphere */
float old_to_p = float(sqrt(old_to_p_sq));
if (old_to_p_sq > mRadius2) /* do r**2 test first */
{ /* this point is outside of current sphere */
float old_to_p = float(sqrt(old_to_p_sq));
/* calc radius of new sphere */
mRadius = (mRadius + old_to_p) * 0.5f;
mRadius2 = mRadius*mRadius; /* for next r**2 compare */
float old_to_new = old_to_p - mRadius;
mRadius = (mRadius + old_to_p) * 0.5f;
mRadius2 = mRadius * mRadius; /* for next r**2 compare */
float old_to_new = old_to_p - mRadius;
/* calc center of new sphere */
/* calc center of new sphere */
float recip = 1.0f /old_to_p;
float recip = 1.0f / old_to_p;
float cx = (mRadius*center[0] + old_to_new*caller_p[0]) * recip;
float cy = (mRadius*center[1] + old_to_new*caller_p[1]) * recip;
float cz = (mRadius*center[2] + old_to_new*caller_p[2]) * recip;
float cx = (mRadius * center[0] + old_to_new * caller_p[0]) * recip;
float cy = (mRadius * center[1] + old_to_new * caller_p[1]) * recip;
float cz = (mRadius * center[2] + old_to_new * caller_p[2]) * recip;
Set(center,cx,cy,cz);
Set(center, cx, cy, cz);
}
}
}
return mRadius;
return mRadius;
}

View File

@@ -36,8 +36,6 @@
// http://www.amillionpixels.us
//
float computeBoundingSphere(unsigned int vcount,const float *points,float *center);
float computeBoundingSphere(unsigned int vcount, const float *points, float *center);
#endif

View File

@@ -6,7 +6,6 @@
#include <assert.h>
#include <math.h>
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -41,58 +40,53 @@
// http://www.amillionpixels.us
//
void fm_inverseRT(const float *matrix,const float *pos,float *t) // inverse rotate translate the point.
void fm_inverseRT(const float *matrix, const float *pos, float *t) // inverse rotate translate the point.
{
float _x = pos[0] - matrix[3*4+0];
float _y = pos[1] - matrix[3*4+1];
float _z = pos[2] - matrix[3*4+2];
float _x = pos[0] - matrix[3 * 4 + 0];
float _y = pos[1] - matrix[3 * 4 + 1];
float _z = pos[2] - matrix[3 * 4 + 2];
// Multiply inverse-translated source vector by inverted rotation transform
t[0] = (matrix[0*4+0] * _x) + (matrix[0*4+1] * _y) + (matrix[0*4+2] * _z);
t[1] = (matrix[1*4+0] * _x) + (matrix[1*4+1] * _y) + (matrix[1*4+2] * _z);
t[2] = (matrix[2*4+0] * _x) + (matrix[2*4+1] * _y) + (matrix[2*4+2] * _z);
t[0] = (matrix[0 * 4 + 0] * _x) + (matrix[0 * 4 + 1] * _y) + (matrix[0 * 4 + 2] * _z);
t[1] = (matrix[1 * 4 + 0] * _x) + (matrix[1 * 4 + 1] * _y) + (matrix[1 * 4 + 2] * _z);
t[2] = (matrix[2 * 4 + 0] * _x) + (matrix[2 * 4 + 1] * _y) + (matrix[2 * 4 + 2] * _z);
}
void fm_identity(float *matrix) // set 4x4 matrix to identity.
void fm_identity(float *matrix) // set 4x4 matrix to identity.
{
matrix[0*4+0] = 1;
matrix[1*4+1] = 1;
matrix[2*4+2] = 1;
matrix[3*4+3] = 1;
matrix[0 * 4 + 0] = 1;
matrix[1 * 4 + 1] = 1;
matrix[2 * 4 + 2] = 1;
matrix[3 * 4 + 3] = 1;
matrix[1*4+0] = 0;
matrix[2*4+0] = 0;
matrix[3*4+0] = 0;
matrix[1 * 4 + 0] = 0;
matrix[2 * 4 + 0] = 0;
matrix[3 * 4 + 0] = 0;
matrix[0*4+1] = 0;
matrix[2*4+1] = 0;
matrix[3*4+1] = 0;
matrix[0 * 4 + 1] = 0;
matrix[2 * 4 + 1] = 0;
matrix[3 * 4 + 1] = 0;
matrix[0*4+2] = 0;
matrix[1*4+2] = 0;
matrix[3*4+2] = 0;
matrix[0*4+3] = 0;
matrix[1*4+3] = 0;
matrix[2*4+3] = 0;
matrix[0 * 4 + 2] = 0;
matrix[1 * 4 + 2] = 0;
matrix[3 * 4 + 2] = 0;
matrix[0 * 4 + 3] = 0;
matrix[1 * 4 + 3] = 0;
matrix[2 * 4 + 3] = 0;
}
void fm_eulerMatrix(float ax,float ay,float az,float *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
void fm_eulerMatrix(float ax, float ay, float az, float *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
{
float quat[4];
fm_eulerToQuat(ax,ay,az,quat);
fm_quatToMatrix(quat,matrix);
float quat[4];
fm_eulerToQuat(ax, ay, az, quat);
fm_quatToMatrix(quat, matrix);
}
void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax)
void fm_getAABB(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax)
{
const unsigned char *source = (const unsigned char *) points;
const unsigned char *source = (const unsigned char *)points;
bmin[0] = points[0];
bmin[1] = points[1];
@@ -102,29 +96,26 @@ void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,flo
bmax[1] = points[1];
bmax[2] = points[2];
for (unsigned int i = 1; i < vcount; i++)
{
source += pstride;
const float *p = (const float *)source;
for (unsigned int i=1; i<vcount; i++)
{
source+=pstride;
const float *p = (const float *) source;
if (p[0] < bmin[0]) bmin[0] = p[0];
if (p[1] < bmin[1]) bmin[1] = p[1];
if (p[2] < bmin[2]) bmin[2] = p[2];
if ( p[0] < bmin[0] ) bmin[0] = p[0];
if ( p[1] < bmin[1] ) bmin[1] = p[1];
if ( p[2] < bmin[2] ) bmin[2] = p[2];
if ( p[0] > bmax[0] ) bmax[0] = p[0];
if ( p[1] > bmax[1] ) bmax[1] = p[1];
if ( p[2] > bmax[2] ) bmax[2] = p[2];
}
if (p[0] > bmax[0]) bmax[0] = p[0];
if (p[1] > bmax[1]) bmax[1] = p[1];
if (p[2] > bmax[2]) bmax[2] = p[2];
}
}
void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat) // convert euler angles to quaternion.
void fm_eulerToQuat(float roll, float pitch, float yaw, float *quat) // convert euler angles to quaternion.
{
roll *= 0.5f;
roll *= 0.5f;
pitch *= 0.5f;
yaw *= 0.5f;
yaw *= 0.5f;
float cr = cosf(roll);
float cp = cosf(pitch);
@@ -139,119 +130,109 @@ void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat) // convert eul
float spcy = sp * cy;
float cpsy = cp * sy;
quat[0] = ( sr * cpcy - cr * spsy);
quat[1] = ( cr * spcy + sr * cpsy);
quat[2] = ( cr * cpsy - sr * spcy);
quat[3] = cr * cpcy + sr * spsy;
quat[0] = (sr * cpcy - cr * spsy);
quat[1] = (cr * spcy + sr * cpsy);
quat[2] = (cr * cpsy - sr * spcy);
quat[3] = cr * cpcy + sr * spsy;
}
void fm_quatToMatrix(const float *quat,float *matrix) // convert quaterinion rotation to matrix, zeros out the translation component.
void fm_quatToMatrix(const float *quat, float *matrix) // convert quaterinion rotation to matrix, zeros out the translation component.
{
float xx = quat[0] * quat[0];
float yy = quat[1] * quat[1];
float zz = quat[2] * quat[2];
float xy = quat[0] * quat[1];
float xz = quat[0] * quat[2];
float yz = quat[1] * quat[2];
float wx = quat[3] * quat[0];
float wy = quat[3] * quat[1];
float wz = quat[3] * quat[2];
float xx = quat[0]*quat[0];
float yy = quat[1]*quat[1];
float zz = quat[2]*quat[2];
float xy = quat[0]*quat[1];
float xz = quat[0]*quat[2];
float yz = quat[1]*quat[2];
float wx = quat[3]*quat[0];
float wy = quat[3]*quat[1];
float wz = quat[3]*quat[2];
matrix[0 * 4 + 0] = 1 - 2 * (yy + zz);
matrix[1 * 4 + 0] = 2 * (xy - wz);
matrix[2 * 4 + 0] = 2 * (xz + wy);
matrix[0*4+0] = 1 - 2 * ( yy + zz );
matrix[1*4+0] = 2 * ( xy - wz );
matrix[2*4+0] = 2 * ( xz + wy );
matrix[0 * 4 + 1] = 2 * (xy + wz);
matrix[1 * 4 + 1] = 1 - 2 * (xx + zz);
matrix[2 * 4 + 1] = 2 * (yz - wx);
matrix[0*4+1] = 2 * ( xy + wz );
matrix[1*4+1] = 1 - 2 * ( xx + zz );
matrix[2*4+1] = 2 * ( yz - wx );
matrix[0*4+2] = 2 * ( xz - wy );
matrix[1*4+2] = 2 * ( yz + wx );
matrix[2*4+2] = 1 - 2 * ( xx + yy );
matrix[3*4+0] = matrix[3*4+1] = matrix[3*4+2] = 0.0f;
matrix[0*4+3] = matrix[1*4+3] = matrix[2*4+3] = 0.0f;
matrix[3*4+3] = 1.0f;
matrix[0 * 4 + 2] = 2 * (xz - wy);
matrix[1 * 4 + 2] = 2 * (yz + wx);
matrix[2 * 4 + 2] = 1 - 2 * (xx + yy);
matrix[3 * 4 + 0] = matrix[3 * 4 + 1] = matrix[3 * 4 + 2] = 0.0f;
matrix[0 * 4 + 3] = matrix[1 * 4 + 3] = matrix[2 * 4 + 3] = 0.0f;
matrix[3 * 4 + 3] = 1.0f;
}
void fm_quatRotate(const float *quat,const float *v,float *r) // rotate a vector directly by a quaternion.
void fm_quatRotate(const float *quat, const float *v, float *r) // rotate a vector directly by a quaternion.
{
float left[4];
float left[4];
left[0] = quat[3]*v[0] + quat[1]*v[2] - v[1]*quat[2];
left[1] = quat[3]*v[1] + quat[2]*v[0] - v[2]*quat[0];
left[2] = quat[3]*v[2] + quat[0]*v[1] - v[0]*quat[1];
left[3] = - quat[0]*v[0] - quat[1]*v[1] - quat[2]*v[2];
r[0] = (left[3]*-quat[0]) + (quat[3]*left[0]) + (left[1]*-quat[2]) - (-quat[1]*left[2]);
r[1] = (left[3]*-quat[1]) + (quat[3]*left[1]) + (left[2]*-quat[0]) - (-quat[2]*left[0]);
r[2] = (left[3]*-quat[2]) + (quat[3]*left[2]) + (left[0]*-quat[1]) - (-quat[0]*left[1]);
left[0] = quat[3] * v[0] + quat[1] * v[2] - v[1] * quat[2];
left[1] = quat[3] * v[1] + quat[2] * v[0] - v[2] * quat[0];
left[2] = quat[3] * v[2] + quat[0] * v[1] - v[0] * quat[1];
left[3] = -quat[0] * v[0] - quat[1] * v[1] - quat[2] * v[2];
r[0] = (left[3] * -quat[0]) + (quat[3] * left[0]) + (left[1] * -quat[2]) - (-quat[1] * left[2]);
r[1] = (left[3] * -quat[1]) + (quat[3] * left[1]) + (left[2] * -quat[0]) - (-quat[2] * left[0]);
r[2] = (left[3] * -quat[2]) + (quat[3] * left[2]) + (left[0] * -quat[1]) - (-quat[0] * left[1]);
}
void fm_getTranslation(const float *matrix,float *t)
void fm_getTranslation(const float *matrix, float *t)
{
t[0] = matrix[3*4+0];
t[1] = matrix[3*4+1];
t[2] = matrix[3*4+2];
t[0] = matrix[3 * 4 + 0];
t[1] = matrix[3 * 4 + 1];
t[2] = matrix[3 * 4 + 2];
}
void fm_matrixToQuat(const float *matrix,float *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
void fm_matrixToQuat(const float *matrix, float *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
{
float tr = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2];
float tr = matrix[0 * 4 + 0] + matrix[1 * 4 + 1] + matrix[2 * 4 + 2];
// check the diagonal
if (tr > 0.0f )
if (tr > 0.0f)
{
float s = (float) sqrt ( (double) (tr + 1.0f) );
float s = (float)sqrt((double)(tr + 1.0f));
quat[3] = s * 0.5f;
s = 0.5f / s;
quat[0] = (matrix[1*4+2] - matrix[2*4+1]) * s;
quat[1] = (matrix[2*4+0] - matrix[0*4+2]) * s;
quat[2] = (matrix[0*4+1] - matrix[1*4+0]) * s;
quat[0] = (matrix[1 * 4 + 2] - matrix[2 * 4 + 1]) * s;
quat[1] = (matrix[2 * 4 + 0] - matrix[0 * 4 + 2]) * s;
quat[2] = (matrix[0 * 4 + 1] - matrix[1 * 4 + 0]) * s;
}
else
{
// diagonal is negative
int nxt[3] = {1, 2, 0};
float qa[4];
float qa[4];
int i = 0;
if (matrix[1*4+1] > matrix[0*4+0]) i = 1;
if (matrix[2*4+2] > matrix[i*4+i]) i = 2;
if (matrix[1 * 4 + 1] > matrix[0 * 4 + 0]) i = 1;
if (matrix[2 * 4 + 2] > matrix[i * 4 + i]) i = 2;
int j = nxt[i];
int k = nxt[j];
float s = sqrtf ( ((matrix[i*4+i] - (matrix[j*4+j] + matrix[k*4+k])) + 1.0f) );
float s = sqrtf(((matrix[i * 4 + i] - (matrix[j * 4 + j] + matrix[k * 4 + k])) + 1.0f));
qa[i] = s * 0.5f;
if (s != 0.0f ) s = 0.5f / s;
if (s != 0.0f) s = 0.5f / s;
qa[3] = (matrix[j*4+k] - matrix[k*4+j]) * s;
qa[j] = (matrix[i*4+j] + matrix[j*4+i]) * s;
qa[k] = (matrix[i*4+k] + matrix[k*4+i]) * s;
qa[3] = (matrix[j * 4 + k] - matrix[k * 4 + j]) * s;
qa[j] = (matrix[i * 4 + j] + matrix[j * 4 + i]) * s;
qa[k] = (matrix[i * 4 + k] + matrix[k * 4 + i]) * s;
quat[0] = qa[0];
quat[1] = qa[1];
quat[2] = qa[2];
quat[3] = qa[3];
}
}
float fm_sphereVolume(float radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed )
float fm_sphereVolume(float radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed )
{
return (4.0f / 3.0f ) * FM_PI * radius * radius * radius;
return (4.0f / 3.0f) * FM_PI * radius * radius * radius;
}

View File

@@ -3,12 +3,12 @@
#define FLOAT_MATH_H
#ifdef _WIN32
#pragma warning(disable : 4324) // disable padding warning
#pragma warning(disable : 4244) // disable padding warning
#pragma warning(disable : 4267) // possible loss of data
#pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
#pragma warning(disable:4996) //Turn off warnings about deprecated C routines
#pragma warning(disable:4786) // Disable the "debug name too long" warning
#pragma warning(disable : 4324) // disable padding warning
#pragma warning(disable : 4244) // disable padding warning
#pragma warning(disable : 4267) // possible loss of data
#pragma warning(disable : 4530) // Disable the exception disable but used in MSCV Stl warning.
#pragma warning(disable : 4996) //Turn off warnings about deprecated C routines
#pragma warning(disable : 4786) // Disable the "debug name too long" warning
#endif
/*----------------------------------------------------------------------
@@ -45,7 +45,6 @@
// http://www.amillionpixels.us
//
// a set of routines that last you do common 3d math
// operations without any vector, matrix, or quaternion
// classes or templates.
@@ -58,15 +57,15 @@ const float FM_PI = 3.141592654f;
const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
void fm_identity(float *matrix); // set 4x4 matrix to identity.
void fm_inverseRT(const float *matrix,const float *pos,float *t); // inverse rotate translate the point.
void fm_eulerMatrix(float ax,float ay,float az,float *matrix); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax);
void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat); // convert euler angles to quaternion.
void fm_quatToMatrix(const float *quat,float *matrix); // convert quaterinion rotation to matrix, translation set to zero.
void fm_quatRotate(const float *quat,const float *v,float *r); // rotate a vector directly by a quaternion.
void fm_getTranslation(const float *matrix,float *t);
void fm_matrixToQuat(const float *matrix,float *quat); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
void fm_identity(float *matrix); // set 4x4 matrix to identity.
void fm_inverseRT(const float *matrix, const float *pos, float *t); // inverse rotate translate the point.
void fm_eulerMatrix(float ax, float ay, float az, float *matrix); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
void fm_getAABB(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax);
void fm_eulerToQuat(float roll, float pitch, float yaw, float *quat); // convert euler angles to quaternion.
void fm_quatToMatrix(const float *quat, float *matrix); // convert quaterinion rotation to matrix, translation set to zero.
void fm_quatRotate(const float *quat, const float *v, float *r); // rotate a vector directly by a quaternion.
void fm_getTranslation(const float *matrix, float *t);
void fm_matrixToQuat(const float *matrix, float *quat); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
#endif

View File

@@ -35,94 +35,90 @@
// http://www.amillionpixels.us
//
inline float det(const float *p1,const float *p2,const float *p3)
inline float det(const float *p1, const float *p2, const float *p3)
{
return p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2];
return p1[0] * p2[1] * p3[2] + p2[0] * p3[1] * p1[2] + p3[0] * p1[1] * p2[2] - p1[0] * p3[1] * p2[2] - p2[0] * p1[1] * p3[2] - p3[0] * p2[1] * p1[2];
}
float computeMeshVolume(const float *vertices,unsigned int tcount,const unsigned int *indices)
float computeMeshVolume(const float *vertices, unsigned int tcount, const unsigned int *indices)
{
float volume = 0;
for (unsigned int i=0; i<tcount; i++,indices+=3)
for (unsigned int i = 0; i < tcount; i++, indices += 3)
{
const float *p1 = &vertices[indices[0] * 3];
const float *p2 = &vertices[indices[1] * 3];
const float *p3 = &vertices[indices[2] * 3];
const float *p1 = &vertices[ indices[0]*3 ];
const float *p2 = &vertices[ indices[1]*3 ];
const float *p3 = &vertices[ indices[2]*3 ];
volume+=det(p1,p2,p3); // compute the volume of the tetrahedran relative to the origin.
volume += det(p1, p2, p3); // compute the volume of the tetrahedran relative to the origin.
}
volume*=(1.0f/6.0f);
if ( volume < 0 )
volume*=-1;
volume *= (1.0f / 6.0f);
if (volume < 0)
volume *= -1;
return volume;
}
inline void CrossProduct(const float *a,const float *b,float *cross)
inline void CrossProduct(const float *a, const float *b, float *cross)
{
cross[0] = a[1]*b[2] - a[2]*b[1];
cross[1] = a[2]*b[0] - a[0]*b[2];
cross[2] = a[0]*b[1] - a[1]*b[0];
cross[0] = a[1] * b[2] - a[2] * b[1];
cross[1] = a[2] * b[0] - a[0] * b[2];
cross[2] = a[0] * b[1] - a[1] * b[0];
}
inline float DotProduct(const float *a,const float *b)
inline float DotProduct(const float *a, const float *b)
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
inline float tetVolume(const float *p0,const float *p1,const float *p2,const float *p3)
inline float tetVolume(const float *p0, const float *p1, const float *p2, const float *p3)
{
float a[3];
float b[3];
float c[3];
a[0] = p1[0] - p0[0];
a[1] = p1[1] - p0[1];
a[2] = p1[2] - p0[2];
a[0] = p1[0] - p0[0];
a[1] = p1[1] - p0[1];
a[2] = p1[2] - p0[2];
b[0] = p2[0] - p0[0];
b[1] = p2[1] - p0[1];
b[2] = p2[2] - p0[2];
c[0] = p3[0] - p0[0];
c[1] = p3[1] - p0[1];
c[2] = p3[2] - p0[2];
c[0] = p3[0] - p0[0];
c[1] = p3[1] - p0[1];
c[2] = p3[2] - p0[2];
float cross[3];
float cross[3];
CrossProduct( b, c, cross );
CrossProduct(b, c, cross);
float volume = DotProduct( a, cross );
float volume = DotProduct(a, cross);
if ( volume < 0 )
return -volume;
if (volume < 0)
return -volume;
return volume;
return volume;
}
inline float det(const float *p0,const float *p1,const float *p2,const float *p3)
inline float det(const float *p0, const float *p1, const float *p2, const float *p3)
{
return p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2];
return p1[0] * p2[1] * p3[2] + p2[0] * p3[1] * p1[2] + p3[0] * p1[1] * p2[2] - p1[0] * p3[1] * p2[2] - p2[0] * p1[1] * p3[2] - p3[0] * p2[1] * p1[2];
}
float computeMeshVolume2(const float *vertices,unsigned int tcount,const unsigned int *indices)
float computeMeshVolume2(const float *vertices, unsigned int tcount, const unsigned int *indices)
{
float volume = 0;
const float *p0 = vertices;
for (unsigned int i=0; i<tcount; i++,indices+=3)
for (unsigned int i = 0; i < tcount; i++, indices += 3)
{
const float *p1 = &vertices[indices[0] * 3];
const float *p2 = &vertices[indices[1] * 3];
const float *p3 = &vertices[indices[2] * 3];
const float *p1 = &vertices[ indices[0]*3 ];
const float *p2 = &vertices[ indices[1]*3 ];
const float *p3 = &vertices[ indices[2]*3 ];
volume+=tetVolume(p0,p1,p2,p3); // compute the volume of the tetrahdren relative to the root vertice
volume += tetVolume(p0, p1, p2, p3); // compute the volume of the tetrahdren relative to the root vertice
}
return volume * (1.0f / 6.0f );
return volume * (1.0f / 6.0f);
}

View File

@@ -36,10 +36,7 @@
// http://www.amillionpixels.us
//
float computeMeshVolume(const float *vertices,unsigned int tcount,const unsigned int *indices);
float computeMeshVolume2(const float *vertices,unsigned int tcount,const unsigned int *indices);
float computeMeshVolume(const float *vertices, unsigned int tcount, const unsigned int *indices);
float computeMeshVolume2(const float *vertices, unsigned int tcount, const unsigned int *indices);
#endif

View File

@@ -40,199 +40,188 @@
// http://www.amillionpixels.us
//
static inline float DistToPt(const float *p,const float *plane)
static inline float DistToPt(const float *p, const float *plane)
{
float x = p[0];
float y = p[1];
float z = p[2];
float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
return d;
}
static PlaneTriResult getSidePlane(const float *p,const float *plane,float epsilon)
static PlaneTriResult getSidePlane(const float *p, const float *plane, float epsilon)
{
float d = DistToPt(p, plane);
float d = DistToPt(p,plane);
if ((d + epsilon) > 0)
return PTR_FRONT; // it is 'in front' within the provided epsilon value.
if ( (d+epsilon) > 0 )
return PTR_FRONT; // it is 'in front' within the provided epsilon value.
return PTR_BACK;
return PTR_BACK;
}
static void add(const float *p,float *dest,unsigned int tstride,unsigned int &pcount)
static void add(const float *p, float *dest, unsigned int tstride, unsigned int &pcount)
{
char *d = (char *) dest;
d = d + pcount*tstride;
dest = (float *) d;
dest[0] = p[0];
dest[1] = p[1];
dest[2] = p[2];
pcount++;
assert( pcount <= 4 );
char *d = (char *)dest;
d = d + pcount * tstride;
dest = (float *)d;
dest[0] = p[0];
dest[1] = p[1];
dest[2] = p[2];
pcount++;
assert(pcount <= 4);
}
// assumes that the points are on opposite sides of the plane!
static void intersect(const float *p1,const float *p2,float *split,const float *plane)
static void intersect(const float *p1, const float *p2, float *split, const float *plane)
{
float dp1 = DistToPt(p1, plane);
float dp1 = DistToPt(p1,plane);
float dir[3];
float dir[3];
dir[0] = p2[0] - p1[0];
dir[1] = p2[1] - p1[1];
dir[2] = p2[2] - p1[2];
dir[0] = p2[0] - p1[0];
dir[1] = p2[1] - p1[1];
dir[2] = p2[2] - p1[2];
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
float dot2 = dp1 - plane[3];
float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2];
float dot2 = dp1 - plane[3];
float t = -(plane[3] + dot2 ) / dot1;
split[0] = (dir[0]*t)+p1[0];
split[1] = (dir[1]*t)+p1[1];
split[2] = (dir[2]*t)+p1[2];
float t = -(plane[3] + dot2) / dot1;
split[0] = (dir[0] * t) + p1[0];
split[1] = (dir[1] * t) + p1[1];
split[2] = (dir[2] * t) + p1[2];
}
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
const float *triangle, // the source triangle.
unsigned int tstride, // stride in bytes of the input and output triangles
float epsilon, // the co-planer epsilon value.
float *front, // the triangle in front of the
unsigned int &fcount, // number of vertices in the 'front' triangle
float *back, // the triangle in back of the plane
unsigned int &bcount) // the number of vertices in the 'back' triangle.
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
const float *triangle, // the source triangle.
unsigned int tstride, // stride in bytes of the input and output triangles
float epsilon, // the co-planer epsilon value.
float *front, // the triangle in front of the
unsigned int &fcount, // number of vertices in the 'front' triangle
float *back, // the triangle in back of the plane
unsigned int &bcount) // the number of vertices in the 'back' triangle.
{
fcount = 0;
bcount = 0;
fcount = 0;
bcount = 0;
const char *tsource = (const char *) triangle;
const char *tsource = (const char *)triangle;
// get the three vertices of the triangle.
const float *p1 = (const float *) (tsource);
const float *p2 = (const float *) (tsource+tstride);
const float *p3 = (const float *) (tsource+tstride*2);
// get the three vertices of the triangle.
const float *p1 = (const float *)(tsource);
const float *p2 = (const float *)(tsource + tstride);
const float *p3 = (const float *)(tsource + tstride * 2);
PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);
PlaneTriResult r1 = getSidePlane(p1,plane,epsilon); // compute the side of the plane each vertex is on
PlaneTriResult r2 = getSidePlane(p2,plane,epsilon);
PlaneTriResult r3 = getSidePlane(p3,plane,epsilon);
if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
{
if (r1 == PTR_FRONT) // if all three are in front of the plane, then copy to the 'front' output triangle.
{
add(p1, front, tstride, fcount);
add(p2, front, tstride, fcount);
add(p3, front, tstride, fcount);
}
else
{
add(p1, back, tstride, bcount); // if all three are in 'abck' then copy to the 'back' output triangle.
add(p2, back, tstride, bcount);
add(p3, back, tstride, bcount);
}
return r1; // if all three points are on the same side of the plane return result
}
if ( r1 == r2 && r1 == r3 ) // if all three vertices are on the same side of the plane.
{
if ( r1 == PTR_FRONT ) // if all three are in front of the plane, then copy to the 'front' output triangle.
{
add(p1,front,tstride,fcount);
add(p2,front,tstride,fcount);
add(p3,front,tstride,fcount);
}
else
{
add(p1,back,tstride,bcount); // if all three are in 'abck' then copy to the 'back' output triangle.
add(p2,back,tstride,bcount);
add(p3,back,tstride,bcount);
}
return r1; // if all three points are on the same side of the plane return result
}
// ok.. we need to split the triangle at the plane.
// ok.. we need to split the triangle at the plane.
// First test ray segment P1 to P2
if (r1 == r2) // if these are both on the same side...
{
if (r1 == PTR_FRONT)
{
add(p1, front, tstride, fcount);
add(p2, front, tstride, fcount);
}
else
{
add(p1, back, tstride, bcount);
add(p2, back, tstride, bcount);
}
}
else
{
float split[3]; // split the point
intersect(p1, p2, split, plane);
// First test ray segment P1 to P2
if ( r1 == r2 ) // if these are both on the same side...
{
if ( r1 == PTR_FRONT )
{
add( p1, front, tstride, fcount );
add( p2, front, tstride, fcount );
}
else
{
add( p1, back, tstride, bcount );
add( p2, back, tstride, bcount );
}
}
else
{
float split[3]; // split the point
intersect(p1,p2,split,plane);
if (r1 == PTR_FRONT)
{
add(p1, front, tstride, fcount);
add(split, front, tstride, fcount);
if ( r1 == PTR_FRONT )
{
add(split, back, tstride, bcount);
add(p2, back, tstride, bcount);
}
else
{
add(p1, back, tstride, bcount);
add(split, back, tstride, bcount);
add(p1, front, tstride, fcount );
add(split, front, tstride, fcount );
add(split, front, tstride, fcount);
add(p2, front, tstride, fcount);
}
}
add(split, back, tstride, bcount );
add(p2, back, tstride, bcount );
// Next test ray segment P2 to P3
if (r2 == r3) // if these are both on the same side...
{
if (r3 == PTR_FRONT)
{
add(p3, front, tstride, fcount);
}
else
{
add(p3, back, tstride, bcount);
}
}
else
{
float split[3]; // split the point
intersect(p2, p3, split, plane);
}
else
{
add(p1, back, tstride, bcount );
add(split, back, tstride, bcount );
if (r3 == PTR_FRONT)
{
add(split, front, tstride, fcount);
add(split, back, tstride, bcount);
add(split, front, tstride, fcount );
add(p2, front, tstride, fcount );
}
add(p3, front, tstride, fcount);
}
else
{
add(split, front, tstride, fcount);
add(split, back, tstride, bcount);
}
add(p3, back, tstride, bcount);
}
}
// Next test ray segment P2 to P3
if ( r2 == r3 ) // if these are both on the same side...
{
if ( r3 == PTR_FRONT )
{
add( p3, front, tstride, fcount );
}
else
{
add( p3, back, tstride, bcount );
}
}
else
{
float split[3]; // split the point
intersect(p2,p3,split,plane);
// Next test ray segment P3 to P1
if (r3 != r1) // if these are both on the same side...
{
float split[3]; // split the point
if ( r3 == PTR_FRONT )
{
add(split, front, tstride, fcount );
add(split, back, tstride, bcount );
intersect(p3, p1, split, plane);
add(p3, front, tstride, fcount );
}
else
{
add(split, front, tstride, fcount );
add(split, back, tstride, bcount );
if (r1 == PTR_FRONT)
{
add(split, front, tstride, fcount);
add(split, back, tstride, bcount);
}
else
{
add(split, front, tstride, fcount);
add(split, back, tstride, bcount);
}
}
add(p3, back, tstride, bcount );
}
}
// Next test ray segment P3 to P1
if ( r3 != r1 ) // if these are both on the same side...
{
float split[3]; // split the point
intersect(p3,p1,split,plane);
if ( r1 == PTR_FRONT )
{
add(split, front, tstride, fcount );
add(split, back, tstride, bcount );
}
else
{
add(split, front, tstride, fcount );
add(split, back, tstride, bcount );
}
}
return PTR_SPLIT;
return PTR_SPLIT;
}

View File

@@ -36,23 +36,20 @@
// http://www.amillionpixels.us
//
enum PlaneTriResult
{
PTR_FRONT,
PTR_BACK,
PTR_SPLIT
PTR_FRONT,
PTR_BACK,
PTR_SPLIT
};
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
const float *triangle, // the source position triangle.
unsigned int tstride, // stride in bytes between vertices of the triangle.
float epsilon, // the co-planer epsilon value.
float *front, // the triangle in front of the
unsigned int &fcount, // number of vertices in the 'front' triangle.
float *back, // the triangle in back of the plane
unsigned int &bcount); // the number of vertices in the 'back' triangle.
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
const float *triangle, // the source position triangle.
unsigned int tstride, // stride in bytes between vertices of the triangle.
float epsilon, // the co-planer epsilon value.
float *front, // the triangle in front of the
unsigned int &fcount, // number of vertices in the 'front' triangle.
float *back, // the triangle in back of the plane
unsigned int &bcount); // the number of vertices in the 'back' triangle.
#endif

View File

@@ -41,88 +41,82 @@
// http://www.amillionpixels.us
//
/* a = b - c */
#define vector(a,b,c) \
(a)[0] = (b)[0] - (c)[0]; \
(a)[1] = (b)[1] - (c)[1]; \
#define vector(a, b, c) \
(a)[0] = (b)[0] - (c)[0]; \
(a)[1] = (b)[1] - (c)[1]; \
(a)[2] = (b)[2] - (c)[2];
#define innerProduct(v, q) \
((v)[0] * (q)[0] + \
(v)[1] * (q)[1] + \
(v)[2] * (q)[2])
#define innerProduct(v,q) \
((v)[0] * (q)[0] + \
(v)[1] * (q)[1] + \
(v)[2] * (q)[2])
#define crossProduct(a,b,c) \
#define crossProduct(a, b, c) \
(a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \
(a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \
(a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1];
bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t)
bool rayIntersectsTriangle(const float *p, const float *d, const float *v0, const float *v1, const float *v2, float &t)
{
float e1[3], e2[3], h[3], s[3], q[3];
float a, f, u, v;
float e1[3],e2[3],h[3],s[3],q[3];
float a,f,u,v;
vector(e1,v1,v0);
vector(e2,v2,v0);
crossProduct(h,d,e2);
a = innerProduct(e1,h);
vector(e1, v1, v0);
vector(e2, v2, v0);
crossProduct(h, d, e2);
a = innerProduct(e1, h);
if (a > -0.00001 && a < 0.00001)
return(false);
return (false);
f = 1/a;
vector(s,p,v0);
u = f * (innerProduct(s,h));
f = 1 / a;
vector(s, p, v0);
u = f * (innerProduct(s, h));
if (u < 0.0 || u > 1.0)
return(false);
return (false);
crossProduct(q,s,e1);
v = f * innerProduct(d,q);
crossProduct(q, s, e1);
v = f * innerProduct(d, q);
if (v < 0.0 || u + v > 1.0)
return(false);
return (false);
// at this stage we can compute t to find out where
// the intersection point is on the line
t = f * innerProduct(e2,q);
if (t > 0) // ray intersection
return(true);
else // this means that there is a line intersection
// but not a ray intersection
return (false);
t = f * innerProduct(e2, q);
if (t > 0) // ray intersection
return (true);
else // this means that there is a line intersection
// but not a ray intersection
return (false);
}
bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect)
bool lineIntersectsTriangle(const float *rayStart, const float *rayEnd, const float *p1, const float *p2, const float *p3, float *sect)
{
float dir[3];
dir[0] = rayEnd[0] - rayStart[0];
dir[1] = rayEnd[1] - rayStart[1];
dir[2] = rayEnd[2] - rayStart[2];
dir[0] = rayEnd[0] - rayStart[0];
dir[1] = rayEnd[1] - rayStart[1];
dir[2] = rayEnd[2] - rayStart[2];
float d = sqrtf(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
float r = 1.0f / d;
float d = sqrtf(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
float r = 1.0f / d;
dir[0]*=r;
dir[1]*=r;
dir[2]*=r;
dir[0] *= r;
dir[1] *= r;
dir[2] *= r;
float t;
float t;
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t );
if ( ret )
if (ret)
{
if ( t > d )
if (t > d)
{
sect[0] = rayStart[0] + dir[0]*t;
sect[1] = rayStart[1] + dir[1]*t;
sect[2] = rayStart[2] + dir[2]*t;
sect[0] = rayStart[0] + dir[0] * t;
sect[1] = rayStart[1] + dir[1] * t;
sect[2] = rayStart[2] + dir[2] * t;
}
else
{
@@ -130,5 +124,5 @@ bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const floa
}
}
return ret;
return ret;
}

View File

@@ -36,10 +36,8 @@
// http://www.amillionpixels.us
//
// returns true if the ray intersects the triangle.
bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect);
bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t);
bool lineIntersectsTriangle(const float *rayStart, const float *rayEnd, const float *p1, const float *p2, const float *p3, float *sect);
bool rayIntersectsTriangle(const float *p, const float *d, const float *v0, const float *v1, const float *v2, float &t);
#endif

View File

@@ -6,7 +6,6 @@
#include <float.h>
#include <math.h>
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -53,10 +52,8 @@
namespace ConvexDecomposition
{
static void computePlane(const float *A,const float *B,const float *C,float *plane)
static void computePlane(const float *A, const float *B, const float *C, float *plane)
{
float vx = (B[0] - C[0]);
float vy = (B[1] - C[1]);
float vz = (B[2] - C[2]);
@@ -71,108 +68,104 @@ static void computePlane(const float *A,const float *B,const float *C,float *pla
float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
if ( mag < 0.000001f )
if (mag < 0.000001f)
{
mag = 0;
}
else
{
mag = 1.0f/mag;
mag = 1.0f / mag;
}
float x = vw_x * mag;
float y = vw_y * mag;
float z = vw_z * mag;
float D = 0.0f - ((x * A[0]) + (y * A[1]) + (z * A[2]));
float D = 0.0f - ((x*A[0])+(y*A[1])+(z*A[2]));
plane[0] = x;
plane[1] = y;
plane[2] = z;
plane[3] = D;
plane[0] = x;
plane[1] = y;
plane[2] = z;
plane[3] = D;
}
class Rect3d
{
public:
Rect3d(void) { };
Rect3d(void){};
Rect3d(const float *bmin,const float *bmax)
{
Rect3d(const float *bmin, const float *bmax)
{
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
}
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
void SetMin(const float *bmin)
{
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
}
}
void SetMax(const float *bmax)
{
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
}
void SetMin(const float *bmin)
{
mMin[0] = bmin[0];
mMin[1] = bmin[1];
mMin[2] = bmin[2];
}
void SetMax(const float *bmax)
{
mMax[0] = bmax[0];
mMax[1] = bmax[1];
mMax[2] = bmax[2];
}
void SetMin(float x,float y,float z)
void SetMin(float x, float y, float z)
{
mMin[0] = x;
mMin[1] = y;
mMin[2] = z;
}
void SetMax(float x,float y,float z)
void SetMax(float x, float y, float z)
{
mMax[0] = x;
mMax[1] = y;
mMax[2] = z;
}
float mMin[3];
float mMax[3];
float mMin[3];
float mMax[3];
};
void splitRect(unsigned int axis,
const Rect3d &source,
Rect3d &b1,
Rect3d &b2,
const float *midpoint)
const Rect3d &source,
Rect3d &b1,
Rect3d &b2,
const float *midpoint)
{
switch ( axis )
switch (axis)
{
case 0:
b1.SetMin(source.mMin);
b1.SetMax( midpoint[0], source.mMax[1], source.mMax[2] );
b1.SetMax(midpoint[0], source.mMax[1], source.mMax[2]);
b2.SetMin( midpoint[0], source.mMin[1], source.mMin[2] );
b2.SetMin(midpoint[0], source.mMin[1], source.mMin[2]);
b2.SetMax(source.mMax);
break;
case 1:
b1.SetMin(source.mMin);
b1.SetMax( source.mMax[0], midpoint[1], source.mMax[2] );
b1.SetMax(source.mMax[0], midpoint[1], source.mMax[2]);
b2.SetMin( source.mMin[0], midpoint[1], source.mMin[2] );
b2.SetMin(source.mMin[0], midpoint[1], source.mMin[2]);
b2.SetMax(source.mMax);
break;
case 2:
b1.SetMin(source.mMin);
b1.SetMax( source.mMax[0], source.mMax[1], midpoint[2] );
b1.SetMax(source.mMax[0], source.mMax[1], midpoint[2]);
b2.SetMin( source.mMin[0], source.mMin[1], midpoint[2] );
b2.SetMin(source.mMin[0], source.mMin[1], midpoint[2]);
b2.SetMax(source.mMax);
break;
@@ -180,127 +173,122 @@ void splitRect(unsigned int axis,
}
bool computeSplitPlane(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane)
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane)
{
float bmin[3] = { 1e9, 1e9, 1e9 };
float bmax[3] = { -1e9, -1e9, -1e9 };
float bmin[3] = {1e9, 1e9, 1e9};
float bmax[3] = {-1e9, -1e9, -1e9};
for (unsigned int i=0; i<vcount; i++)
{
const float *p = &vertices[i*3];
for (unsigned int i = 0; i < vcount; i++)
{
const float *p = &vertices[i * 3];
if ( p[0] < bmin[0] ) bmin[0] = p[0];
if ( p[1] < bmin[1] ) bmin[1] = p[1];
if ( p[2] < bmin[2] ) bmin[2] = p[2];
if (p[0] < bmin[0]) bmin[0] = p[0];
if (p[1] < bmin[1]) bmin[1] = p[1];
if (p[2] < bmin[2]) bmin[2] = p[2];
if ( p[0] > bmax[0] ) bmax[0] = p[0];
if ( p[1] > bmax[1] ) bmax[1] = p[1];
if ( p[2] > bmax[2] ) bmax[2] = p[2];
}
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
if (p[0] > bmax[0]) bmax[0] = p[0];
if (p[1] > bmax[1]) bmax[1] = p[1];
if (p[2] > bmax[2]) bmax[2] = p[2];
}
float dx = bmax[0] - bmin[0];
float dy = bmax[1] - bmin[1];
float dz = bmax[2] - bmin[2];
float laxis = dx;
unsigned int axis = 0;
if ( dy > dx )
if (dy > dx)
{
axis = 1;
laxis = dy;
}
if ( dz > dx && dz > dy )
if (dz > dx && dz > dy)
{
axis = 2;
laxis = dz;
}
float p1[3];
float p2[3];
float p3[3];
float p1[3];
float p2[3];
float p3[3];
p3[0] = p2[0] = p1[0] = bmin[0] + dx*0.5f;
p3[1] = p2[1] = p1[1] = bmin[1] + dy*0.5f;
p3[2] = p2[2] = p1[2] = bmin[2] + dz*0.5f;
p3[0] = p2[0] = p1[0] = bmin[0] + dx * 0.5f;
p3[1] = p2[1] = p1[1] = bmin[1] + dy * 0.5f;
p3[2] = p2[2] = p1[2] = bmin[2] + dz * 0.5f;
Rect3d b(bmin,bmax);
Rect3d b(bmin, bmax);
Rect3d b1,b2;
Rect3d b1, b2;
splitRect(axis,b,b1,b2,p1);
splitRect(axis, b, b1, b2, p1);
// callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00);
// callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00);
// callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00);
// callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00);
switch (axis)
{
case 0:
p2[1] = bmin[1];
p2[2] = bmin[2];
switch ( axis )
{
case 0:
p2[1] = bmin[1];
p2[2] = bmin[2];
if (dz > dy)
{
p3[1] = bmax[1];
p3[2] = bmin[2];
}
else
{
p3[1] = bmin[1];
p3[2] = bmax[2];
}
if ( dz > dy )
{
p3[1] = bmax[1];
p3[2] = bmin[2];
}
else
{
p3[1] = bmin[1];
p3[2] = bmax[2];
}
break;
case 1:
p2[0] = bmin[0];
p2[2] = bmin[2];
break;
case 1:
p2[0] = bmin[0];
p2[2] = bmin[2];
if (dx > dz)
{
p3[0] = bmax[0];
p3[2] = bmin[2];
}
else
{
p3[0] = bmin[0];
p3[2] = bmax[2];
}
if ( dx > dz )
{
p3[0] = bmax[0];
p3[2] = bmin[2];
}
else
{
p3[0] = bmin[0];
p3[2] = bmax[2];
}
break;
case 2:
p2[0] = bmin[0];
p2[1] = bmin[1];
break;
case 2:
p2[0] = bmin[0];
p2[1] = bmin[1];
if (dx > dy)
{
p3[0] = bmax[0];
p3[1] = bmin[1];
}
else
{
p3[0] = bmin[0];
p3[1] = bmax[1];
}
if ( dx > dy )
{
p3[0] = bmax[0];
p3[1] = bmin[1];
}
else
{
p3[0] = bmin[0];
p3[1] = bmax[1];
}
break;
}
break;
}
// callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
// callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
computePlane(p1,p2,p3,plane);
return true;
computePlane(p1, p2, p3, plane);
return true;
}
}
} // namespace ConvexDecomposition

View File

@@ -39,21 +39,17 @@
// http://www.amillionpixels.us
//
namespace ConvexDecomposition
{
class ConvexDecompInterface;
bool computeSplitPlane(unsigned int vcount,
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane);
const float *vertices,
unsigned int tcount,
const unsigned int *indices,
ConvexDecompInterface *callback,
float *plane);
}
} // namespace ConvexDecomposition
#endif

View File

@@ -4,13 +4,12 @@
#include <string.h>
#include <assert.h>
#pragma warning(disable:4786)
#pragma warning(disable : 4786)
#include <vector>
#include <map>
#include <set>
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -107,55 +106,50 @@
// You could easily modify this code to support other vertex
// formats with any number of interpolants.
#include "vlookup.h"
namespace Vlookup
{
class VertexPosition
{
public:
VertexPosition(void) { };
VertexPosition(const float *p)
{
mPos[0] = p[0];
mPos[1] = p[1];
mPos[2] = p[2];
};
void Set(int index,const float *pos)
VertexPosition(void){};
VertexPosition(const float *p)
{
const float * p = &pos[index*3];
mPos[0] = p[0];
mPos[1] = p[1];
mPos[2] = p[2];
mPos[0] = p[0];
mPos[1] = p[1];
mPos[2] = p[2];
};
float GetX(void) const { return mPos[0]; };
float GetY(void) const { return mPos[1]; };
float GetZ(void) const { return mPos[2]; };
void Set(int index, const float *pos)
{
const float *p = &pos[index * 3];
mPos[0] = p[0];
mPos[1] = p[1];
mPos[2] = p[2];
};
float GetX(void) const { return mPos[0]; };
float GetY(void) const { return mPos[1]; };
float GetZ(void) const { return mPos[2]; };
float mPos[3];
};
typedef std::vector< VertexPosition > VertexVector;
typedef std::vector<VertexPosition> VertexVector;
struct Tracker
{
VertexPosition mFind; // vertice to locate.
VertexVector *mList;
VertexPosition mFind; // vertice to locate.
VertexVector *mList;
Tracker()
{
mList = 0;
}
void SetSearch(const VertexPosition& match,VertexVector *list)
void SetSearch(const VertexPosition &match, VertexVector *list)
{
mFind = match;
mList = list;
@@ -165,9 +159,9 @@ struct Tracker
struct VertexID
{
int mID;
Tracker* mTracker;
Tracker *mTracker;
VertexID(int ID, Tracker* Tracker)
VertexID(int ID, Tracker *Tracker)
{
mID = ID;
mTracker = Tracker;
@@ -177,46 +171,45 @@ struct VertexID
class VertexLess
{
public:
bool operator()(VertexID v1,VertexID v2) const;
bool operator()(VertexID v1, VertexID v2) const;
private:
const VertexPosition& Get(VertexID index) const
const VertexPosition &Get(VertexID index) const
{
if ( index.mID == -1 ) return index.mTracker->mFind;
if (index.mID == -1) return index.mTracker->mFind;
VertexVector &vlist = *index.mTracker->mList;
return vlist[index.mID];
}
};
template <class Type> class VertexPool
template <class Type>
class VertexPool
{
public:
typedef std::set<VertexID, VertexLess > VertexSet;
typedef std::vector< Type > VertexVector;
typedef std::set<VertexID, VertexLess> VertexSet;
typedef std::vector<Type> VertexVector;
int getVertex(const Type& vtx)
int getVertex(const Type &vtx)
{
mTracker.SetSearch(vtx,&mVtxs);
mTracker.SetSearch(vtx, &mVtxs);
VertexSet::iterator found;
found = mVertSet.find( VertexID(-1,&mTracker) );
if ( found != mVertSet.end() )
found = mVertSet.find(VertexID(-1, &mTracker));
if (found != mVertSet.end())
{
return found->mID;
}
int idx = (int)mVtxs.size();
mVtxs.push_back( vtx );
mVertSet.insert( VertexID(idx,&mTracker) );
mVtxs.push_back(vtx);
mVertSet.insert(VertexID(idx, &mTracker));
return idx;
};
const float * GetPos(int idx) const
const float *GetPos(int idx) const
{
return mVtxs[idx].mPos;
}
const Type& Get(int idx) const
const Type &Get(int idx) const
{
return mVtxs[idx];
};
@@ -233,9 +226,9 @@ public:
mVtxs.reserve(reservesize);
};
const VertexVector& GetVertexList(void) const { return mVtxs; };
const VertexVector &GetVertexList(void) const { return mVtxs; };
void Set(const Type& vtx)
void Set(const Type &vtx)
{
mVtxs.push_back(vtx);
}
@@ -245,82 +238,74 @@ public:
return mVtxs.size();
};
Type * getBuffer(void)
Type *getBuffer(void)
{
return &mVtxs[0];
};
private:
VertexSet mVertSet; // ordered list.
VertexVector mVtxs; // set of vertices.
Tracker mTracker;
VertexSet mVertSet; // ordered list.
VertexVector mVtxs; // set of vertices.
Tracker mTracker;
};
bool VertexLess::operator()(VertexID v1,VertexID v2) const
bool VertexLess::operator()(VertexID v1, VertexID v2) const
{
const VertexPosition &a = Get(v1);
const VertexPosition &b = Get(v2);
const VertexPosition& a = Get(v1);
const VertexPosition& b = Get(v2);
int ixA = (int)(a.GetX() * 10000.0f);
int ixB = (int)(b.GetX() * 10000.0f);
int ixA = (int) (a.GetX()*10000.0f);
int ixB = (int) (b.GetX()*10000.0f);
if (ixA < ixB) return true;
if (ixA > ixB) return false;
if ( ixA < ixB ) return true;
if ( ixA > ixB ) return false;
int iyA = (int)(a.GetY() * 10000.0f);
int iyB = (int)(b.GetY() * 10000.0f);
int iyA = (int) (a.GetY()*10000.0f);
int iyB = (int) (b.GetY()*10000.0f);
if (iyA < iyB) return true;
if (iyA > iyB) return false;
if ( iyA < iyB ) return true;
if ( iyA > iyB ) return false;
int izA = (int) (a.GetZ()*10000.0f);
int izB = (int) (b.GetZ()*10000.0f);
if ( izA < izB ) return true;
if ( izA > izB ) return false;
int izA = (int)(a.GetZ() * 10000.0f);
int izB = (int)(b.GetZ() * 10000.0f);
if (izA < izB) return true;
if (izA > izB) return false;
return false;
}
}
} // namespace Vlookup
using namespace Vlookup;
VertexLookup Vl_createVertexLookup(void)
{
VertexLookup ret = new VertexPool< VertexPosition >;
return ret;
VertexLookup ret = new VertexPool<VertexPosition>;
return ret;
}
void Vl_releaseVertexLookup(VertexLookup vlook)
void Vl_releaseVertexLookup(VertexLookup vlook)
{
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
delete vp;
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
delete vp;
}
unsigned int Vl_getIndex(VertexLookup vlook,const float *pos) // get index.
unsigned int Vl_getIndex(VertexLookup vlook, const float *pos) // get index.
{
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
VertexPosition p(pos);
return vp->getVertex(p);
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
VertexPosition p(pos);
return vp->getVertex(p);
}
const float * Vl_getVertices(VertexLookup vlook)
const float *Vl_getVertices(VertexLookup vlook)
{
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
return vp->GetPos(0);
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
return vp->GetPos(0);
}
unsigned int Vl_getVcount(VertexLookup vlook)
unsigned int Vl_getVcount(VertexLookup vlook)
{
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
return vp->GetVertexCount();
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
return vp->GetVertexCount();
}

View File

@@ -2,7 +2,6 @@
#define VLOOKUP_H
/*----------------------------------------------------------------------
Copyright (c) 2004 Open Dynamics Framework Group
www.physicstools.org
@@ -37,7 +36,6 @@
// http://www.amillionpixels.us
//
// CodeSnippet provided by John W. Ratcliff
// on March 23, 2006.
//
@@ -105,15 +103,13 @@
// Uses an STL set to create an index table for a bunch of vertex positions
// used typically to re-index a collection of raw triangle data.
typedef void *VertexLookup;
typedef void * VertexLookup;
VertexLookup Vl_createVertexLookup(void);
void Vl_releaseVertexLookup(VertexLookup vlook);
unsigned int Vl_getIndex(VertexLookup vlook,const float *pos); // get index.
const float * Vl_getVertices(VertexLookup vlook);
unsigned int Vl_getVcount(VertexLookup vlook);
VertexLookup Vl_createVertexLookup(void);
void Vl_releaseVertexLookup(VertexLookup vlook);
unsigned int Vl_getIndex(VertexLookup vlook, const float *pos); // get index.
const float *Vl_getVertices(VertexLookup vlook);
unsigned int Vl_getVcount(VertexLookup vlook);
#endif