mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-04 17:40:06 +00:00
add the 'extras' and Bullet 2 tests, to make it easier to create a new intermediate release
This commit is contained in:
parent
e0784b2da6
commit
2cf7806c87
7
Extras/CMakeLists.txt
Normal file
7
Extras/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
SUBDIRS( Serialize ConvexDecomposition HACD GIMPACTUtils )
|
||||
|
||||
#Maya Dynamica plugin is moved to http://dynamica.googlecode.com
|
||||
|
||||
IF (USE_GLUT AND GLUT_FOUND)
|
||||
SUBDIRS (glui)
|
||||
ENDIF ()
|
64
Extras/ConvexDecomposition/CMakeLists.txt
Normal file
64
Extras/ConvexDecomposition/CMakeLists.txt
Normal file
@ -0,0 +1,64 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
SET(ConvexDecomposition_SRCS
|
||||
bestfitobb.cpp
|
||||
ConvexBuilder.cpp
|
||||
cd_wavefront.cpp
|
||||
fitsphere.cpp
|
||||
meshvolume.cpp
|
||||
raytri.cpp
|
||||
vlookup.cpp
|
||||
bestfit.cpp
|
||||
cd_hull.cpp
|
||||
ConvexDecomposition.cpp
|
||||
concavity.cpp
|
||||
float_math.cpp
|
||||
planetri.cpp
|
||||
splitplane.cpp
|
||||
)
|
||||
|
||||
SET(ConvexDecomposition_HDRS
|
||||
ConvexDecomposition.h
|
||||
cd_vector.h
|
||||
concavity.h
|
||||
bestfitobb.h
|
||||
ConvexBuilder.h
|
||||
cd_wavefront.h
|
||||
fitsphere.h
|
||||
meshvolume.h
|
||||
raytri.h
|
||||
vlookup.h
|
||||
bestfit.h
|
||||
cd_hull.h
|
||||
)
|
||||
|
||||
ADD_LIBRARY(ConvexDecomposition ${ConvexDecomposition_SRCS} ${ConvexDecomposition_HDRS})
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(ConvexDecomposition BulletCollision LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS ConvexDecomposition DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS ConvexDecomposition DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES PUBLIC_HEADER "${ConvexDecomposition_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
373
Extras/ConvexDecomposition/ConvexBuilder.cpp
Normal file
373
Extras/ConvexDecomposition/ConvexBuilder.cpp
Normal file
@ -0,0 +1,373 @@
|
||||
#include "float_math.h"
|
||||
#include "ConvexBuilder.h"
|
||||
#include "meshvolume.h"
|
||||
#include "bestfit.h"
|
||||
#include <assert.h>
|
||||
#include "cd_hull.h"
|
||||
|
||||
#include "fitsphere.h"
|
||||
#include "bestfitobb.h"
|
||||
|
||||
unsigned int MAXDEPTH = 8 ;
|
||||
float CONCAVE_PERCENT = 1.0f ;
|
||||
float MERGE_PERCENT = 2.0f ;
|
||||
|
||||
CHull::CHull(const ConvexResult &result)
|
||||
{
|
||||
mResult = new ConvexResult(result);
|
||||
mVolume = computeMeshVolume( result.mHullVertices, result.mHullTcount, result.mHullIndices );
|
||||
|
||||
mDiagonal = getBoundingRegion( result.mHullVcount, result.mHullVertices, sizeof(float)*3, mMin, mMax );
|
||||
|
||||
float dx = mMax[0] - mMin[0];
|
||||
float dy = mMax[1] - mMin[1];
|
||||
float dz = mMax[2] - mMin[2];
|
||||
|
||||
dx*=0.1f; // inflate 1/10th on each edge
|
||||
dy*=0.1f; // inflate 1/10th on each edge
|
||||
dz*=0.1f; // inflate 1/10th on each edge
|
||||
|
||||
mMin[0]-=dx;
|
||||
mMin[1]-=dy;
|
||||
mMin[2]-=dz;
|
||||
|
||||
mMax[0]+=dx;
|
||||
mMax[1]+=dy;
|
||||
mMax[2]+=dz;
|
||||
|
||||
|
||||
}
|
||||
|
||||
CHull::~CHull(void)
|
||||
{
|
||||
delete mResult;
|
||||
}
|
||||
|
||||
bool CHull::overlap(const CHull &h) const
|
||||
{
|
||||
return overlapAABB(mMin,mMax, h.mMin, h.mMax );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback)
|
||||
{
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
ConvexBuilder::~ConvexBuilder(void)
|
||||
{
|
||||
int 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)
|
||||
{
|
||||
unsigned int dcount = 0;
|
||||
|
||||
assert( i1 != i2 && i1 != i3 && i2 != i3 );
|
||||
assert( ci1 != ci2 && ci1 != ci3 && ci2 != ci3 );
|
||||
|
||||
if ( i1 == ci1 || i1 == ci2 || i1 == ci3 ) dcount++;
|
||||
if ( i2 == ci1 || i2 == ci2 || i2 == ci3 ) dcount++;
|
||||
if ( i3 == ci1 || i3 == ci2 || i3 == ci3 ) dcount++;
|
||||
|
||||
return dcount == 3;
|
||||
}
|
||||
|
||||
void ConvexBuilder::getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices)
|
||||
{
|
||||
unsigned int *src = cr.mHullIndices;
|
||||
|
||||
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];
|
||||
|
||||
i1 = Vl_getIndex(vc,p1);
|
||||
i2 = Vl_getIndex(vc,p2);
|
||||
i3 = Vl_getIndex(vc,p3);
|
||||
|
||||
#if 0
|
||||
bool duplicate = false;
|
||||
|
||||
unsigned int tcount = indices.size()/3;
|
||||
for (unsigned int j=0; j<tcount; j++)
|
||||
{
|
||||
unsigned int ci1 = indices[j*3+0];
|
||||
unsigned int ci2 = indices[j*3+1];
|
||||
unsigned int ci3 = indices[j*3+2];
|
||||
if ( isDuplicate(i1,i2,i3, ci1, ci2, ci3 ) )
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !duplicate )
|
||||
{
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i2);
|
||||
indices.push_back(i3);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
CHull *ret = 0;
|
||||
|
||||
// ok..we are going to combine both meshes into a single mesh
|
||||
// and then we are going to compute the concavity...
|
||||
|
||||
VertexLookup vc = Vl_createVertexLookup();
|
||||
|
||||
UintVector indices;
|
||||
|
||||
getMesh( *a->mResult, vc, indices );
|
||||
getMesh( *b->mResult, vc, indices );
|
||||
|
||||
unsigned int vcount = Vl_getVcount(vc);
|
||||
const float *vertices = Vl_getVertices(vc);
|
||||
unsigned int tcount = indices.size()/3;
|
||||
|
||||
//don't do anything if hull is empty
|
||||
if (!tcount)
|
||||
{
|
||||
Vl_releaseVertexLookup (vc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HullResult hresult;
|
||||
HullLibrary hl;
|
||||
HullDesc desc;
|
||||
|
||||
desc.SetHullFlag(QF_TRIANGLES);
|
||||
|
||||
desc.mVcount = vcount;
|
||||
desc.mVertices = vertices;
|
||||
desc.mVertexStride = sizeof(float)*3;
|
||||
|
||||
HullError hret = hl.CreateConvexHull(desc,hresult);
|
||||
|
||||
if ( hret == QE_OK )
|
||||
{
|
||||
|
||||
float combineVolume = computeMeshVolume( hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices );
|
||||
float sumVolume = a->mVolume + b->mVolume;
|
||||
|
||||
float percent = (sumVolume*100) / combineVolume;
|
||||
if ( percent >= (100.0f-MERGE_PERCENT) )
|
||||
{
|
||||
ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
|
||||
ret = new CHull(cr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vl_releaseVertexLookup(vc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ConvexBuilder::combineHulls(void)
|
||||
{
|
||||
|
||||
bool combine = false;
|
||||
|
||||
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)
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
|
||||
int 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
|
||||
{
|
||||
|
||||
CHull *merge = canMerge(cr,match); // if we can merge these two....
|
||||
|
||||
if ( merge )
|
||||
{
|
||||
|
||||
output.push_back(merge);
|
||||
|
||||
|
||||
++i;
|
||||
while ( i != mChulls.size() )
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
if ( cr != match )
|
||||
{
|
||||
output.push_back(cr);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
delete cr;
|
||||
delete match;
|
||||
combine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( combine )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
output.push_back(cr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( combine )
|
||||
{
|
||||
mChulls.clear();
|
||||
mChulls.copyFromArray(output);
|
||||
output.clear();
|
||||
}
|
||||
|
||||
|
||||
return combine;
|
||||
}
|
||||
|
||||
unsigned int ConvexBuilder::process(const DecompDesc &desc)
|
||||
{
|
||||
|
||||
unsigned int ret = 0;
|
||||
|
||||
MAXDEPTH = desc.mDepth;
|
||||
CONCAVE_PERCENT = desc.mCpercent;
|
||||
MERGE_PERCENT = desc.mPpercent;
|
||||
|
||||
|
||||
calcConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices,this,0,0);
|
||||
|
||||
|
||||
while ( combineHulls() ); // keep combinging hulls until I can't combine any more...
|
||||
|
||||
int 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 ConvexResult &c = *cr->mResult; // the high resolution hull...
|
||||
|
||||
HullResult result;
|
||||
HullLibrary hl;
|
||||
HullDesc hdesc;
|
||||
|
||||
hdesc.SetHullFlag(QF_TRIANGLES);
|
||||
|
||||
hdesc.mVcount = c.mHullVcount;
|
||||
hdesc.mVertices = c.mHullVertices;
|
||||
hdesc.mVertexStride = sizeof(float)*3;
|
||||
hdesc.mMaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output
|
||||
|
||||
if ( desc.mSkinWidth )
|
||||
{
|
||||
hdesc.mSkinWidth = desc.mSkinWidth;
|
||||
hdesc.SetHullFlag(QF_SKIN_WIDTH); // do skin width computation.
|
||||
}
|
||||
|
||||
HullError ret = hl.CreateConvexHull(hdesc,result);
|
||||
|
||||
if ( ret == QE_OK )
|
||||
{
|
||||
ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
|
||||
|
||||
r.mHullVolume = computeMeshVolume( result.mOutputVertices, result.mNumFaces, result.mIndices ); // the volume of the hull.
|
||||
|
||||
// compute the best fit OBB
|
||||
computeBestFitOBB( result.mNumOutputVertices, result.mOutputVertices, sizeof(float)*3, r.mOBBSides, r.mOBBTransform );
|
||||
|
||||
r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] *r.mOBBSides[2]; // compute the OBB volume.
|
||||
|
||||
fm_getTranslation( r.mOBBTransform, r.mOBBCenter ); // get the translation component of the 4x4 matrix.
|
||||
|
||||
fm_matrixToQuat( r.mOBBTransform, r.mOBBOrientation ); // extract the orientation as a quaternion.
|
||||
|
||||
r.mSphereRadius = computeBoundingSphere( result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter );
|
||||
r.mSphereVolume = fm_sphereVolume( r.mSphereRadius );
|
||||
|
||||
|
||||
mCallback->ConvexDecompResult(r);
|
||||
}
|
||||
|
||||
hl.ReleaseResult (result);
|
||||
|
||||
|
||||
delete cr;
|
||||
}
|
||||
|
||||
ret = mChulls.size();
|
||||
|
||||
mChulls.clear();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void ConvexBuilder::ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugTri(p1,p2,p3,color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugOBB(sides,matrix,color);
|
||||
}
|
||||
void ConvexBuilder::ConvexDebugPoint(const float *p,float dist,unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugPoint(p,dist,color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugBound(bmin,bmax,color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDecompResult(ConvexResult &result)
|
||||
{
|
||||
CHull *ch = new CHull(result);
|
||||
mChulls.push_back(ch);
|
||||
}
|
||||
|
||||
void ConvexBuilder::sortChulls(CHullVector &hulls)
|
||||
{
|
||||
hulls.quickSort(CHullSort());
|
||||
//hulls.heapSort(CHullSort());
|
||||
}
|
||||
|
||||
|
112
Extras/ConvexDecomposition/ConvexBuilder.h
Normal file
112
Extras/ConvexDecomposition/ConvexBuilder.h
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef CONVEX_BUILDER_H
|
||||
#define CONVEX_BUILDER_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "vlookup.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
using namespace ConvexDecomposition;
|
||||
|
||||
|
||||
class CHull
|
||||
{
|
||||
public:
|
||||
CHull(const ConvexResult &result);
|
||||
|
||||
~CHull(void);
|
||||
|
||||
bool overlap(const CHull &h) const;
|
||||
|
||||
float mMin[3];
|
||||
float mMax[3];
|
||||
float mVolume;
|
||||
float mDiagonal; // long edge..
|
||||
ConvexResult *mResult;
|
||||
};
|
||||
|
||||
// Usage: std::sort( list.begin(), list.end(), StringSortRef() );
|
||||
class CHullSort
|
||||
{
|
||||
public:
|
||||
|
||||
inline bool operator()(const CHull *a,const CHull *b) const
|
||||
{
|
||||
return a->mVolume < b->mVolume;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef btAlignedObjectArray< CHull * > CHullVector;
|
||||
|
||||
|
||||
|
||||
class ConvexBuilder : public ConvexDecompInterface
|
||||
{
|
||||
public:
|
||||
ConvexBuilder(ConvexDecompInterface *callback);
|
||||
|
||||
virtual ~ConvexBuilder(void);
|
||||
|
||||
bool isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3,
|
||||
unsigned int ci1,unsigned int ci2,unsigned int ci3);
|
||||
|
||||
void getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices);
|
||||
|
||||
CHull * canMerge(CHull *a,CHull *b);
|
||||
|
||||
bool combineHulls(void);
|
||||
|
||||
unsigned int process(const DecompDesc &desc);
|
||||
|
||||
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 ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color);
|
||||
|
||||
virtual void ConvexDecompResult(ConvexResult &result);
|
||||
|
||||
void sortChulls(CHullVector &hulls);
|
||||
|
||||
CHullVector mChulls;
|
||||
ConvexDecompInterface *mCallback;
|
||||
};
|
||||
|
||||
#endif //CONVEX_BUILDER_H
|
||||
|
375
Extras/ConvexDecomposition/ConvexDecomposition.cpp
Normal file
375
Extras/ConvexDecomposition/ConvexDecomposition.cpp
Normal file
@ -0,0 +1,375 @@
|
||||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "cd_vector.h"
|
||||
#include "cd_hull.h"
|
||||
#include "bestfit.h"
|
||||
#include "planetri.h"
|
||||
#include "vlookup.h"
|
||||
#include "splitplane.h"
|
||||
#include "meshvolume.h"
|
||||
#include "concavity.h"
|
||||
#include "bestfitobb.h"
|
||||
#include "float_math.h"
|
||||
#include "fitsphere.h"
|
||||
|
||||
#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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
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() );
|
||||
|
||||
// do *not* process degenerate triangles!
|
||||
|
||||
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)
|
||||
|
||||
{
|
||||
|
||||
float plane[4];
|
||||
|
||||
bool split = false;
|
||||
|
||||
|
||||
if ( depth < MAXDEPTH )
|
||||
{
|
||||
|
||||
float 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.
|
||||
{
|
||||
split = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( depth >= MAXDEPTH || !split )
|
||||
{
|
||||
|
||||
#if 1
|
||||
|
||||
HullResult result;
|
||||
HullLibrary hl;
|
||||
HullDesc desc;
|
||||
|
||||
desc.SetHullFlag(QF_TRIANGLES);
|
||||
|
||||
desc.mVcount = vcount;
|
||||
desc.mVertices = vertices;
|
||||
desc.mVertexStride = sizeof(float)*3;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
static int count = 0;
|
||||
|
||||
count++;
|
||||
|
||||
if ( count == 8 ) count = 0;
|
||||
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
|
||||
PlaneTriResult result;
|
||||
|
||||
result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
|
||||
|
||||
if( fcount > 4 || bcount > 4 )
|
||||
{
|
||||
result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
|
||||
}
|
||||
|
||||
switch ( result )
|
||||
{
|
||||
case PTR_FRONT:
|
||||
|
||||
assert( fcount == 3 );
|
||||
|
||||
if ( showmesh )
|
||||
callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00 );
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
addTri( vfront, ifront, front[0], front[1], front[2] );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PTR_BACK:
|
||||
assert( bcount == 3 );
|
||||
|
||||
if ( showmesh )
|
||||
callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00 );
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
addTri( vback, iback, back[0], back[1], back[2] );
|
||||
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PTR_SPLIT:
|
||||
|
||||
assert( fcount >= 3 && fcount <= 4);
|
||||
assert( bcount >= 3 && bcount <= 4);
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
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 ( bcount == 4 )
|
||||
{
|
||||
addTri( vback, iback, back[0], back[2], back[3] );
|
||||
}
|
||||
|
||||
#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 ( 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;
|
||||
|
||||
calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1);
|
||||
|
||||
}
|
||||
|
||||
ifront.clear();
|
||||
|
||||
Vl_releaseVertexLookup(vfront);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
220
Extras/ConvexDecomposition/ConvexDecomposition.h
Normal file
220
Extras/ConvexDecomposition/ConvexDecomposition.h
Normal file
@ -0,0 +1,220 @@
|
||||
#ifndef CONVEX_DECOMPOSITION_H
|
||||
|
||||
#define CONVEX_DECOMPOSITION_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#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 ;
|
||||
|
||||
|
||||
typedef btAlignedObjectArray< unsigned int > UintVector;
|
||||
|
||||
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
|
||||
class ConvexResult
|
||||
{
|
||||
public:
|
||||
ConvexResult(void)
|
||||
{
|
||||
mHullVcount = 0;
|
||||
mHullVertices = 0;
|
||||
mHullTcount = 0;
|
||||
mHullIndices = 0;
|
||||
}
|
||||
|
||||
ConvexResult(unsigned int hvcount,const float *hvertices,unsigned int htcount,const unsigned int *hindices)
|
||||
{
|
||||
mHullVcount = hvcount;
|
||||
if ( mHullVcount )
|
||||
{
|
||||
mHullVertices = new float[mHullVcount*sizeof(float)*3];
|
||||
memcpy(mHullVertices, hvertices, sizeof(float)*3*mHullVcount );
|
||||
}
|
||||
else
|
||||
{
|
||||
mHullVertices = 0;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
466
Extras/ConvexDecomposition/bestfit.cpp
Normal file
466
Extras/ConvexDecomposition/bestfit.cpp
Normal file
@ -0,0 +1,466 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
// Geometric Tools, Inc.
|
||||
// http://www.geometrictools.com
|
||||
// Copyright (c) 1998-2006. All Rights Reserved
|
||||
//
|
||||
// The Wild Magic Library (WM3) source code is supplied under the terms of
|
||||
// the license agreement
|
||||
// http://www.geometrictools.com/License/WildMagic3License.pdf
|
||||
// and may not be copied or disclosed except in accordance with the terms
|
||||
// of that agreement.
|
||||
|
||||
#include "bestfit.h"
|
||||
|
||||
namespace BestFit
|
||||
{
|
||||
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
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 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];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool QLAlgorithm(void)
|
||||
{
|
||||
const int iMaxIter = 32;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
using namespace BestFit;
|
||||
|
||||
|
||||
bool getBestFitPlane(unsigned int vcount,
|
||||
const float *points,
|
||||
unsigned int vstride,
|
||||
const float *weights,
|
||||
unsigned int wstride,
|
||||
float *plane)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
Vec3 kOrigin(0,0,0);
|
||||
|
||||
float wtotal = 0;
|
||||
|
||||
if ( 1 )
|
||||
{
|
||||
const char *source = (const char *) points;
|
||||
const char *wsource = (const char *) weights;
|
||||
|
||||
for (unsigned int i=0; i<vcount; i++)
|
||||
{
|
||||
|
||||
const float *p = (const float *) source;
|
||||
|
||||
float w = 1;
|
||||
|
||||
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;
|
||||
|
||||
wtotal+=w;
|
||||
|
||||
source+=vstride;
|
||||
}
|
||||
}
|
||||
|
||||
float recip = 1.0f / wtotal; // reciprocol of total weighting
|
||||
|
||||
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;
|
||||
|
||||
|
||||
if ( 1 )
|
||||
{
|
||||
const char *source = (const char *) points;
|
||||
const char *wsource = (const char *) weights;
|
||||
|
||||
for (unsigned int i=0; i<vcount; i++)
|
||||
{
|
||||
|
||||
const float *p = (const float *) source;
|
||||
|
||||
float w = 1;
|
||||
|
||||
if ( wsource )
|
||||
{
|
||||
const float *ws = (const float *) wsource;
|
||||
w = *ws; //
|
||||
wsource+=wstride;
|
||||
}
|
||||
|
||||
Vec3 kDiff;
|
||||
|
||||
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+= 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.
|
||||
|
||||
fSumYY+= kDiff.y * kDiff.y;
|
||||
fSumYZ+= kDiff.y * kDiff.z;
|
||||
fSumZZ+= kDiff.z * kDiff.z;
|
||||
|
||||
|
||||
source+=vstride;
|
||||
}
|
||||
}
|
||||
|
||||
fSumXX *= recip;
|
||||
fSumXY *= recip;
|
||||
fSumXZ *= recip;
|
||||
fSumYY *= recip;
|
||||
fSumYZ *= recip;
|
||||
fSumZZ *= recip;
|
||||
|
||||
// setup the eigensolver
|
||||
Eigen kES;
|
||||
|
||||
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;
|
||||
|
||||
kES.mElement[2][0] = fSumXZ;
|
||||
kES.mElement[2][1] = fSumYZ;
|
||||
kES.mElement[2][2] = fSumZZ;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
bmin[0] = points[0];
|
||||
bmin[1] = points[1];
|
||||
bmin[2] = points[2];
|
||||
|
||||
bmax[0] = points[0];
|
||||
bmax[1] = points[1];
|
||||
bmax[2] = points[2];
|
||||
|
||||
|
||||
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] > 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 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 ( 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
|
||||
}
|
||||
|
||||
|
65
Extras/ConvexDecomposition/bestfit.h
Normal file
65
Extras/ConvexDecomposition/bestfit.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef BEST_FIT_H
|
||||
|
||||
#define BEST_FIT_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
// This routine was released in 'snippet' form
|
||||
// by John W. Ratcliff mailto:jratcliff@infiniplex.net
|
||||
// on March 22, 2006.
|
||||
//
|
||||
// This routine computes the 'best fit' plane equation to
|
||||
// a set of input data points with an optional per vertex
|
||||
// weighting component.
|
||||
//
|
||||
// The implementation for this was lifted directly from
|
||||
// David Eberly's Magic Software implementation.
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
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
|
173
Extras/ConvexDecomposition/bestfitobb.cpp
Normal file
173
Extras/ConvexDecomposition/bestfitobb.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "bestfitobb.h"
|
||||
#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)
|
||||
{
|
||||
const char *src = (const char *) points;
|
||||
|
||||
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];
|
||||
|
||||
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] > 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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix)
|
||||
{
|
||||
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
|
||||
fm_getAABB(vcount,points,pstride,bmin,bmax);
|
||||
|
||||
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];
|
||||
|
||||
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 bestVolume = 1e9;
|
||||
float angle[3]={0.f,0.f,0.f};
|
||||
|
||||
while ( sweep >= 1 )
|
||||
{
|
||||
|
||||
bool found = false;
|
||||
|
||||
float stepsize = sweep / steps;
|
||||
|
||||
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];
|
||||
|
||||
fm_eulerMatrix( x*FM_DEG_TO_RAD, y*FM_DEG_TO_RAD, z*FM_DEG_TO_RAD, pmatrix );
|
||||
|
||||
pmatrix[3*4+0] = center[0];
|
||||
pmatrix[3*4+1] = center[1];
|
||||
pmatrix[3*4+2] = center[2];
|
||||
|
||||
float psides[3];
|
||||
|
||||
computeOBB( vcount, points, pstride, psides, pmatrix );
|
||||
|
||||
float volume = psides[0]*psides[1]*psides[2]; // the volume of the cube
|
||||
|
||||
if ( volume <= bestVolume )
|
||||
{
|
||||
bestVolume = volume;
|
||||
|
||||
sides[0] = psides[0];
|
||||
sides[1] = psides[1];
|
||||
sides[2] = psides[2];
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
43
Extras/ConvexDecomposition/bestfitobb.h
Normal file
43
Extras/ConvexDecomposition/bestfitobb.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef BEST_FIT_OBB_H
|
||||
|
||||
#define BEST_FIT_OBB_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
|
||||
void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix);
|
||||
|
||||
#endif
|
3261
Extras/ConvexDecomposition/cd_hull.cpp
Normal file
3261
Extras/ConvexDecomposition/cd_hull.cpp
Normal file
File diff suppressed because it is too large
Load Diff
153
Extras/ConvexDecomposition/cd_hull.h
Normal file
153
Extras/ConvexDecomposition/cd_hull.h
Normal file
@ -0,0 +1,153 @@
|
||||
#ifndef CD_HULL_H
|
||||
|
||||
#define CD_HULL_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
|
||||
class HullResult
|
||||
{
|
||||
public:
|
||||
HullResult(void)
|
||||
{
|
||||
mPolygons = true;
|
||||
mNumOutputVertices = 0;
|
||||
mOutputVertices = 0;
|
||||
mNumFaces = 0;
|
||||
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.
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
HullDesc(HullFlag flag,
|
||||
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
|
||||
}
|
||||
|
||||
bool HasHullFlag(HullFlag flag) const
|
||||
{
|
||||
if ( mFlags & flag ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags|=flag;
|
||||
}
|
||||
|
||||
void ClearHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags&=~flag;
|
||||
}
|
||||
|
||||
unsigned int mFlags; // flags to use when generating the convex hull.
|
||||
unsigned int mVcount; // number of vertices in the input point cloud
|
||||
const 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.
|
||||
};
|
||||
|
||||
class HullLibrary
|
||||
{
|
||||
public:
|
||||
|
||||
HullError CreateConvexHull(const HullDesc &desc, // describes the input request
|
||||
HullResult &result); // contains the resulst
|
||||
|
||||
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
|
||||
|
||||
private:
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
1185
Extras/ConvexDecomposition/cd_vector.h
Normal file
1185
Extras/ConvexDecomposition/cd_vector.h
Normal file
File diff suppressed because it is too large
Load Diff
860
Extras/ConvexDecomposition/cd_wavefront.cpp
Normal file
860
Extras/ConvexDecomposition/cd_wavefront.cpp
Normal file
@ -0,0 +1,860 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
#include "float_math.h"
|
||||
|
||||
#include "cd_wavefront.h"
|
||||
|
||||
|
||||
using namespace ConvexDecomposition;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
|
||||
typedef std::vector< int > IntVector;
|
||||
typedef std::vector< float > FloatVector;
|
||||
|
||||
#if defined(__APPLE__) || defined(__CELLOS_LV2__)
|
||||
#define stricmp(a, b) strcasecmp((a), (b))
|
||||
#endif
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** InParser.h ********************************/
|
||||
/*******************************************************************/
|
||||
class InPlaceParserInterface
|
||||
{
|
||||
public:
|
||||
virtual ~InPlaceParserInterface () {} ;
|
||||
|
||||
virtual int ParseLine(int lineno,int argc,const char **argv) =0; // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
};
|
||||
|
||||
enum SeparatorType
|
||||
{
|
||||
ST_DATA, // is data
|
||||
ST_HARD, // is a hard separator
|
||||
ST_SOFT, // is a soft separator
|
||||
ST_EOS // is a comment symbol, and everything past this character should be ignored
|
||||
};
|
||||
|
||||
class InPlaceParser
|
||||
{
|
||||
public:
|
||||
InPlaceParser(void)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
InPlaceParser(char *data,int len)
|
||||
{
|
||||
Init();
|
||||
SetSourceData(data,len);
|
||||
}
|
||||
|
||||
InPlaceParser(const char *fname)
|
||||
{
|
||||
Init();
|
||||
SetFile(fname);
|
||||
}
|
||||
|
||||
~InPlaceParser(void);
|
||||
|
||||
void Init(void)
|
||||
{
|
||||
mQuoteChar = 34;
|
||||
mData = 0;
|
||||
mLen = 0;
|
||||
mMyAlloc = false;
|
||||
for (int i=0; i<256; i++)
|
||||
{
|
||||
mHard[i] = ST_DATA;
|
||||
mHardString[i*2] = i;
|
||||
mHardString[i*2+1] = 0;
|
||||
}
|
||||
mHard[0] = ST_EOS;
|
||||
mHard[32] = ST_SOFT;
|
||||
mHard[9] = ST_SOFT;
|
||||
mHard[13] = ST_SOFT;
|
||||
mHard[10] = ST_SOFT;
|
||||
}
|
||||
|
||||
void SetFile(const char *fname); // use this file as source data to parse.
|
||||
|
||||
void SetSourceData(char *data,int len)
|
||||
{
|
||||
mData = data;
|
||||
mLen = len;
|
||||
mMyAlloc = false;
|
||||
};
|
||||
|
||||
int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
|
||||
|
||||
int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
|
||||
|
||||
const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
|
||||
|
||||
void SetHardSeparator(char c) // add a hard separator
|
||||
{
|
||||
mHard[(int)c] = ST_HARD;
|
||||
}
|
||||
|
||||
void SetHard(char c) // add a hard separator
|
||||
{
|
||||
mHard[(int)c] = ST_HARD;
|
||||
}
|
||||
|
||||
|
||||
void SetCommentSymbol(char c) // comment character, treated as 'end of string'
|
||||
{
|
||||
mHard[(int)c] = ST_EOS;
|
||||
}
|
||||
|
||||
void ClearHardSeparator(char c)
|
||||
{
|
||||
mHard[(int)c] = ST_DATA;
|
||||
}
|
||||
|
||||
|
||||
void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
|
||||
|
||||
bool EOS(char c)
|
||||
{
|
||||
if ( mHard[(int)c] == ST_EOS )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetQuoteChar(char c)
|
||||
{
|
||||
mQuoteChar = c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
inline char * AddHard(int &argc,const char **argv,char *foo);
|
||||
inline bool IsHard(char c);
|
||||
inline char * SkipSpaces(char *foo);
|
||||
inline bool IsWhiteSpace(char c);
|
||||
inline bool IsNonSeparator(char c); // non seperator,neither hard nor soft
|
||||
|
||||
bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
|
||||
char *mData; // ascii data to parse.
|
||||
int mLen; // length of data
|
||||
SeparatorType mHard[256];
|
||||
char mHardString[256*2];
|
||||
char mQuoteChar;
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** InParser.cpp ********************************/
|
||||
/*******************************************************************/
|
||||
void InPlaceParser::SetFile(const char *fname)
|
||||
{
|
||||
if ( mMyAlloc )
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
mData = 0;
|
||||
mLen = 0;
|
||||
mMyAlloc = false;
|
||||
|
||||
|
||||
FILE *fph = fopen(fname,"rb");
|
||||
if ( fph )
|
||||
{
|
||||
fseek(fph,0L,SEEK_END);
|
||||
mLen = ftell(fph);
|
||||
fseek(fph,0L,SEEK_SET);
|
||||
if ( mLen )
|
||||
{
|
||||
mData = (char *) malloc(sizeof(char)*(mLen+1));
|
||||
int ok = fread(mData, mLen, 1, fph);
|
||||
if ( !ok )
|
||||
{
|
||||
free(mData);
|
||||
mData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mData[mLen] = 0; // zero byte terminate end of file marker.
|
||||
mMyAlloc = true;
|
||||
}
|
||||
}
|
||||
fclose(fph);
|
||||
}
|
||||
}
|
||||
|
||||
InPlaceParser::~InPlaceParser(void)
|
||||
{
|
||||
if ( mMyAlloc )
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAXARGS 512
|
||||
|
||||
bool InPlaceParser::IsHard(char c)
|
||||
{
|
||||
return mHard[(int)c] == ST_HARD;
|
||||
}
|
||||
|
||||
char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
|
||||
{
|
||||
while ( IsHard(*foo) )
|
||||
{
|
||||
const char *hard = &mHardString[*foo*2];
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
}
|
||||
return foo;
|
||||
}
|
||||
|
||||
bool InPlaceParser::IsWhiteSpace(char c)
|
||||
{
|
||||
return mHard[(int)c] == ST_SOFT;
|
||||
}
|
||||
|
||||
char * InPlaceParser::SkipSpaces(char *foo)
|
||||
{
|
||||
while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
|
||||
return foo;
|
||||
}
|
||||
|
||||
bool InPlaceParser::IsNonSeparator(char c)
|
||||
{
|
||||
if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
const char *argv[MAXARGS];
|
||||
int argc = 0;
|
||||
|
||||
char *foo = line;
|
||||
|
||||
while ( !EOS(*foo) && argc < MAXARGS )
|
||||
{
|
||||
|
||||
foo = SkipSpaces(foo); // skip any leading spaces
|
||||
|
||||
if ( EOS(*foo) ) break;
|
||||
|
||||
if ( *foo == mQuoteChar ) // if it is an open quote
|
||||
{
|
||||
foo++;
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
|
||||
if ( !EOS(*foo) )
|
||||
{
|
||||
*foo = 0; // replace close quote with zero byte EOS
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
|
||||
|
||||
if ( IsNonSeparator(*foo) ) // add non-hard argument.
|
||||
{
|
||||
bool quote = false;
|
||||
if ( *foo == mQuoteChar )
|
||||
{
|
||||
foo++;
|
||||
quote = true;
|
||||
}
|
||||
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
|
||||
if ( quote )
|
||||
{
|
||||
while (*foo && *foo != mQuoteChar ) foo++;
|
||||
if ( *foo ) *foo = 32;
|
||||
}
|
||||
|
||||
// continue..until we hit an eos ..
|
||||
while ( !EOS(*foo) ) // until we hit EOS
|
||||
{
|
||||
if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
|
||||
{
|
||||
*foo = 0;
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
|
||||
{
|
||||
const char *hard = &mHardString[*foo*2];
|
||||
*foo = 0;
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
foo++;
|
||||
} // end of while loop...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( argc )
|
||||
{
|
||||
ret = callback->ParseLine(lineno, argc, argv );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
|
||||
{
|
||||
assert( callback );
|
||||
if ( !mData ) return 0;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
int lineno = 0;
|
||||
|
||||
char *foo = mData;
|
||||
char *begin = foo;
|
||||
|
||||
|
||||
while ( *foo )
|
||||
{
|
||||
if ( *foo == 10 || *foo == 13 )
|
||||
{
|
||||
lineno++;
|
||||
*foo = 0;
|
||||
|
||||
if ( *begin ) // if there is any data to parse at all...
|
||||
{
|
||||
int v = ProcessLine(lineno,begin,callback);
|
||||
if ( v ) ret = v;
|
||||
}
|
||||
|
||||
foo++;
|
||||
if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
|
||||
begin = foo;
|
||||
}
|
||||
else
|
||||
{
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
|
||||
lineno++; // lasst line.
|
||||
|
||||
int v = ProcessLine(lineno,begin,callback);
|
||||
if ( v ) ret = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void InPlaceParser::DefaultSymbols(void)
|
||||
{
|
||||
SetHardSeparator(',');
|
||||
SetHardSeparator('(');
|
||||
SetHardSeparator(')');
|
||||
SetHardSeparator('=');
|
||||
SetHardSeparator('[');
|
||||
SetHardSeparator(']');
|
||||
SetHardSeparator('{');
|
||||
SetHardSeparator('}');
|
||||
SetCommentSymbol('#');
|
||||
}
|
||||
|
||||
|
||||
const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
|
||||
{
|
||||
const char **ret = 0;
|
||||
|
||||
const char *argv[MAXARGS];
|
||||
int argc = 0;
|
||||
|
||||
char *foo = line;
|
||||
|
||||
while ( !EOS(*foo) && argc < MAXARGS )
|
||||
{
|
||||
|
||||
foo = SkipSpaces(foo); // skip any leading spaces
|
||||
|
||||
if ( EOS(*foo) ) break;
|
||||
|
||||
if ( *foo == mQuoteChar ) // if it is an open quote
|
||||
{
|
||||
foo++;
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
|
||||
if ( !EOS(*foo) )
|
||||
{
|
||||
*foo = 0; // replace close quote with zero byte EOS
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
|
||||
|
||||
if ( IsNonSeparator(*foo) ) // add non-hard argument.
|
||||
{
|
||||
bool quote = false;
|
||||
if ( *foo == mQuoteChar )
|
||||
{
|
||||
foo++;
|
||||
quote = true;
|
||||
}
|
||||
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
|
||||
if ( quote )
|
||||
{
|
||||
while (*foo && *foo != mQuoteChar ) foo++;
|
||||
if ( *foo ) *foo = 32;
|
||||
}
|
||||
|
||||
// continue..until we hit an eos ..
|
||||
while ( !EOS(*foo) ) // until we hit EOS
|
||||
{
|
||||
if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
|
||||
{
|
||||
*foo = 0;
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
|
||||
{
|
||||
const char *hard = &mHardString[*foo*2];
|
||||
*foo = 0;
|
||||
if ( argc < MAXARGS )
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
foo++;
|
||||
} // end of while loop...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = argc;
|
||||
if ( argc )
|
||||
{
|
||||
ret = argv;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Geometry.h ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
class GeometryVertex
|
||||
{
|
||||
public:
|
||||
float mPos[3];
|
||||
float mNormal[3];
|
||||
float mTexel[2];
|
||||
};
|
||||
|
||||
|
||||
class GeometryInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3) {}
|
||||
|
||||
virtual ~GeometryInterface () {}
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Obj.h ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
class OBJ : public InPlaceParserInterface
|
||||
{
|
||||
public:
|
||||
int LoadMesh(const char *fname,GeometryInterface *callback);
|
||||
int ParseLine(int lineno,int argc,const char **argv); // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
private:
|
||||
|
||||
void getVertex(GeometryVertex &v,const char *face) const;
|
||||
|
||||
FloatVector mVerts;
|
||||
FloatVector mTexels;
|
||||
FloatVector mNormals;
|
||||
|
||||
GeometryInterface *mCallback;
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Obj.cpp ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
int OBJ::LoadMesh(const char *fname,GeometryInterface *iface)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mVerts.clear();
|
||||
mTexels.clear();
|
||||
mNormals.clear();
|
||||
|
||||
mCallback = iface;
|
||||
|
||||
InPlaceParser ipp(fname);
|
||||
|
||||
ipp.Parse(this);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static const char * GetArg(const char **argv,int i,int argc)
|
||||
//{
|
||||
// const char * ret = 0;
|
||||
// if ( i < argc ) ret = argv[i];
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
void OBJ::getVertex(GeometryVertex &v,const char *face) const
|
||||
{
|
||||
v.mPos[0] = 0;
|
||||
v.mPos[1] = 0;
|
||||
v.mPos[2] = 0;
|
||||
|
||||
v.mTexel[0] = 0;
|
||||
v.mTexel[1] = 0;
|
||||
|
||||
v.mNormal[0] = 0;
|
||||
v.mNormal[1] = 1;
|
||||
v.mNormal[2] = 0;
|
||||
|
||||
int index = atoi( face )-1;
|
||||
|
||||
const char *texel = strstr(face,"/");
|
||||
|
||||
if ( texel )
|
||||
{
|
||||
int tindex = atoi( texel+1) - 1;
|
||||
|
||||
if ( tindex >=0 && tindex < (int)(mTexels.size()/2) )
|
||||
{
|
||||
const float *t = &mTexels[tindex*2];
|
||||
|
||||
v.mTexel[0] = t[0];
|
||||
v.mTexel[1] = t[1];
|
||||
|
||||
}
|
||||
|
||||
const char *normal = strstr(texel+1,"/");
|
||||
if ( normal )
|
||||
{
|
||||
int nindex = atoi( normal+1 ) - 1;
|
||||
|
||||
if (nindex >= 0 && nindex < (int)(mNormals.size()/3) )
|
||||
{
|
||||
const float *n = &mNormals[nindex*3];
|
||||
|
||||
v.mNormal[0] = n[0];
|
||||
v.mNormal[1] = n[1];
|
||||
v.mNormal[2] = n[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( index >= 0 && index < (int)(mVerts.size()/3) )
|
||||
{
|
||||
|
||||
const float *p = &mVerts[index*3];
|
||||
|
||||
v.mPos[0] = p[0];
|
||||
v.mPos[1] = p[1];
|
||||
v.mPos[2] = p[2];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int OBJ::ParseLine(int lineno,int argc,const char **argv) // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ( argc >= 1 )
|
||||
{
|
||||
const char *foo = argv[0];
|
||||
if ( *foo != '#' )
|
||||
{
|
||||
if ( strcmp(argv[0],"v") == 0 && argc == 4 )
|
||||
|
||||
//if ( stricmp(argv[0],"v") == 0 && argc == 4 )
|
||||
{
|
||||
float vx = (float) atof( argv[1] );
|
||||
float vy = (float) atof( argv[2] );
|
||||
float vz = (float) atof( argv[3] );
|
||||
mVerts.push_back(vx);
|
||||
mVerts.push_back(vy);
|
||||
mVerts.push_back(vz);
|
||||
}
|
||||
else if ( strcmp(argv[0],"vt") == 0 && argc == 3 )
|
||||
|
||||
// else if ( stricmp(argv[0],"vt") == 0 && argc == 3 )
|
||||
{
|
||||
float tx = (float) atof( argv[1] );
|
||||
float ty = (float) atof( argv[2] );
|
||||
mTexels.push_back(tx);
|
||||
mTexels.push_back(ty);
|
||||
}
|
||||
// else if ( stricmp(argv[0],"vn") == 0 && argc == 4 )
|
||||
|
||||
else if ( strcmp(argv[0],"vn") == 0 && argc == 4 )
|
||||
{
|
||||
float normalx = (float) atof(argv[1]);
|
||||
float normaly = (float) atof(argv[2]);
|
||||
float normalz = (float) atof(argv[3]);
|
||||
mNormals.push_back(normalx);
|
||||
mNormals.push_back(normaly);
|
||||
mNormals.push_back(normalz);
|
||||
}
|
||||
// else if ( stricmp(argv[0],"f") == 0 && argc >= 4 )
|
||||
|
||||
else if ( strcmp(argv[0],"f") == 0 && argc >= 4 )
|
||||
{
|
||||
GeometryVertex v[32];
|
||||
|
||||
int vcount = argc-1;
|
||||
|
||||
for (int i=1; i<argc; i++)
|
||||
{
|
||||
getVertex(v[i-1],argv[i] );
|
||||
}
|
||||
|
||||
// need to generate a normal!
|
||||
#if 0 // not currently implemented
|
||||
if ( mNormals.empty() )
|
||||
{
|
||||
Vector3d<float> p1( v[0].mPos );
|
||||
Vector3d<float> p2( v[1].mPos );
|
||||
Vector3d<float> p3( v[2].mPos );
|
||||
|
||||
Vector3d<float> n;
|
||||
n.ComputeNormal(p3,p2,p1);
|
||||
|
||||
for (int i=0; i<vcount; i++)
|
||||
{
|
||||
v[i].mNormal[0] = n.x;
|
||||
v[i].mNormal[1] = n.y;
|
||||
v[i].mNormal[2] = n.z;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
mCallback->NodeTriangle(&v[0],&v[1],&v[2]);
|
||||
|
||||
if ( vcount >=3 ) // do the fan
|
||||
{
|
||||
for (int i=2; i<(vcount-1); i++)
|
||||
{
|
||||
mCallback->NodeTriangle(&v[0],&v[i],&v[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class BuildMesh : public GeometryInterface
|
||||
{
|
||||
public:
|
||||
|
||||
int getIndex(const float *p)
|
||||
{
|
||||
|
||||
int vcount = mVertices.size()/3;
|
||||
|
||||
if(vcount>0)
|
||||
{
|
||||
//New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
|
||||
const float *v = &mVertices[0];
|
||||
|
||||
for (int i=0; i<vcount; i++)
|
||||
{
|
||||
if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] ) return i;
|
||||
v+=3;
|
||||
}
|
||||
}
|
||||
|
||||
mVertices.push_back( p[0] );
|
||||
mVertices.push_back( p[1] );
|
||||
mVertices.push_back( p[2] );
|
||||
|
||||
return vcount;
|
||||
}
|
||||
|
||||
virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3)
|
||||
{
|
||||
mIndices.push_back( getIndex(v1->mPos) );
|
||||
mIndices.push_back( getIndex(v2->mPos) );
|
||||
mIndices.push_back( getIndex(v3->mPos) );
|
||||
}
|
||||
|
||||
const FloatVector& GetVertices(void) const { return mVertices; };
|
||||
const IntVector& GetIndices(void) const { return mIndices; };
|
||||
|
||||
private:
|
||||
FloatVector mVertices;
|
||||
IntVector mIndices;
|
||||
};
|
||||
|
||||
|
||||
WavefrontObj::WavefrontObj(void)
|
||||
{
|
||||
mVertexCount = 0;
|
||||
mTriCount = 0;
|
||||
mIndices = 0;
|
||||
mVertices = 0;
|
||||
}
|
||||
|
||||
WavefrontObj::~WavefrontObj(void)
|
||||
{
|
||||
delete [] mIndices;
|
||||
delete [] mVertices;
|
||||
}
|
||||
|
||||
unsigned int WavefrontObj::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 ret = 0;
|
||||
|
||||
delete [] mVertices;
|
||||
mVertices = 0;
|
||||
delete [] mIndices;
|
||||
mIndices = 0;
|
||||
mVertexCount = 0;
|
||||
mTriCount = 0;
|
||||
|
||||
|
||||
BuildMesh bm;
|
||||
|
||||
OBJ obj;
|
||||
|
||||
obj.LoadMesh(fname,&bm);
|
||||
|
||||
|
||||
const FloatVector &vlist = bm.GetVertices();
|
||||
const IntVector &indices = bm.GetIndices();
|
||||
if ( vlist.size() )
|
||||
{
|
||||
mVertexCount = vlist.size()/3;
|
||||
mVertices = new float[mVertexCount*3];
|
||||
memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 );
|
||||
mTriCount = indices.size()/3;
|
||||
mIndices = new int[mTriCount*3*sizeof(int)];
|
||||
memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3);
|
||||
ret = mTriCount;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
62
Extras/ConvexDecomposition/cd_wavefront.h
Normal file
62
Extras/ConvexDecomposition/cd_wavefront.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef CD_WAVEFRONT_OBJ_H
|
||||
|
||||
|
||||
#define CD_WAVEFRONT_OBJ_H
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
|
||||
class WavefrontObj
|
||||
{
|
||||
public:
|
||||
|
||||
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.
|
||||
|
||||
int mVertexCount;
|
||||
int mTriCount;
|
||||
int *mIndices;
|
||||
float *mVertices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
795
Extras/ConvexDecomposition/concavity.cpp
Normal file
795
Extras/ConvexDecomposition/concavity.cpp
Normal file
@ -0,0 +1,795 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "concavity.h"
|
||||
#include "raytri.h"
|
||||
#include "bestfit.h"
|
||||
#include "cd_hull.h"
|
||||
#include "meshvolume.h"
|
||||
#include "cd_vector.h"
|
||||
#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
|
||||
};
|
||||
|
||||
static int count = 0;
|
||||
|
||||
count++;
|
||||
|
||||
if ( count == 8 ) count = 0;
|
||||
|
||||
assert( count >= 0 && count < 8 );
|
||||
|
||||
unsigned int color = colors[count];
|
||||
|
||||
return color;
|
||||
|
||||
}
|
||||
|
||||
class Wpoint
|
||||
{
|
||||
public:
|
||||
Wpoint(const Vector3d &p,float w)
|
||||
{
|
||||
mPoint = p;
|
||||
mWeight = w;
|
||||
}
|
||||
|
||||
Vector3d mPoint;
|
||||
float mWeight;
|
||||
};
|
||||
|
||||
typedef std::vector< Wpoint > WpointVector;
|
||||
|
||||
|
||||
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];
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
static void intersect(const float *p1,const float *p2,float *split,const float *plane)
|
||||
{
|
||||
|
||||
float dp1 = DistToPt(p1,plane);
|
||||
|
||||
float dir[3];
|
||||
|
||||
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 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];
|
||||
}
|
||||
|
||||
|
||||
class CTri
|
||||
{
|
||||
public:
|
||||
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;
|
||||
|
||||
mP1.Set(p1);
|
||||
mP2.Set(p2);
|
||||
mP3.Set(p3);
|
||||
|
||||
mPlaneD = mNormal.ComputePlane(mP1,mP2,mP3);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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 tcount = 0;
|
||||
|
||||
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,1,4,5,tcount);
|
||||
addTri(indices,1,5,2,tcount);
|
||||
|
||||
addTri(indices,0,3,5,tcount);
|
||||
addTri(indices,0,5,2,tcount);
|
||||
|
||||
const float *vertices = mP1.Ptr();
|
||||
|
||||
if ( callback )
|
||||
{
|
||||
unsigned int color = getDebugColor();
|
||||
|
||||
#if 0
|
||||
Vector3d d1 = mNear1;
|
||||
Vector3d d2 = mNear2;
|
||||
Vector3d d3 = mNear3;
|
||||
|
||||
callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00);
|
||||
|
||||
#else
|
||||
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];
|
||||
|
||||
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 );
|
||||
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
float raySect(const Vector3d &p,const Vector3d &dir,Vector3d §) const
|
||||
{
|
||||
float plane[4];
|
||||
|
||||
plane[0] = mNormal.x;
|
||||
plane[1] = mNormal.y;
|
||||
plane[2] = mNormal.z;
|
||||
plane[3] = mPlaneD;
|
||||
|
||||
Vector3d dest = p+dir*100000;
|
||||
|
||||
intersect( p.Ptr(), dest.Ptr(), sect.Ptr(), plane );
|
||||
|
||||
return sect.Distance(p); // return the intersection distance.
|
||||
|
||||
}
|
||||
|
||||
float planeDistance(const Vector3d &p) const
|
||||
{
|
||||
float plane[4];
|
||||
|
||||
plane[0] = mNormal.x;
|
||||
plane[1] = mNormal.y;
|
||||
plane[2] = mNormal.z;
|
||||
plane[3] = mPlaneD;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool hasIndex(unsigned int i) const
|
||||
{
|
||||
if ( i == mI1 || i == mI2 || i == mI3 ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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 ( count >= 2 ) ret = true;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Vector3d d1 = mNear1 - mP1;
|
||||
Vector3d d2 = mNear2 - mP2;
|
||||
Vector3d d3 = mNear3 - mP3;
|
||||
|
||||
d1*=WSCALE;
|
||||
d2*=WSCALE;
|
||||
d3*=WSCALE;
|
||||
|
||||
d1 = d1 + mP1;
|
||||
d2 = d2 + mP2;
|
||||
d3 = d3 + mP3;
|
||||
|
||||
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(p4);
|
||||
list.push_back(p5);
|
||||
list.push_back(p6);
|
||||
|
||||
#if 0
|
||||
callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00);
|
||||
|
||||
Vector3d np1 = mP1 + mNormal*0.05f;
|
||||
Vector3d np2 = mP2 + mNormal*0.05f;
|
||||
Vector3d np3 = mP3 + mNormal*0.05f;
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), np1.Ptr(), np1.Ptr(), 0xFF00FF );
|
||||
callback->ConvexDebugTri(mP2.Ptr(), np2.Ptr(), np2.Ptr(), 0xFF00FF );
|
||||
callback->ConvexDebugTri(mP3.Ptr(), np3.Ptr(), np3.Ptr(), 0xFF00FF );
|
||||
|
||||
callback->ConvexDebugPoint( np1.Ptr(), 0.01F, 0XFF00FF );
|
||||
callback->ConvexDebugPoint( np2.Ptr(), 0.01F, 0XFF00FF );
|
||||
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...
|
||||
};
|
||||
|
||||
typedef std::vector< CTri > CTriVector;
|
||||
|
||||
bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback,const CTriVector &input_mesh)
|
||||
{
|
||||
|
||||
bool ret = false;
|
||||
|
||||
float neardot = 0.707f;
|
||||
|
||||
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 );
|
||||
//gLog->Display("*********************************************\r\n");
|
||||
|
||||
CTriVector::const_iterator i;
|
||||
|
||||
CTri nearest;
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
if ( t.samePlane(m) )
|
||||
{
|
||||
//gLog->Display("*** PLANE MATCH!!!\r\n");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
float dot = t.mNormal.Dot(m.mNormal);
|
||||
|
||||
if ( dot > neardot )
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
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 );
|
||||
|
||||
nearest = t;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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.mConcavity = m.mC1;
|
||||
|
||||
if ( m.mC2 > m.mConcavity ) m.mConcavity = m.mC2;
|
||||
if ( m.mC3 > m.mConcavity ) m.mConcavity = m.mC3;
|
||||
|
||||
#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
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//gLog->Display("No match\r\n");
|
||||
}
|
||||
|
||||
//gLog->Display("*********************************************\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isFeatureTri(CTri &t,CTriVector &flist,float fc,ConvexDecompInterface *callback,unsigned int color)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if ( t.mProcessed == 0 ) // if not already processed
|
||||
{
|
||||
|
||||
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() )
|
||||
{
|
||||
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 );
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
|
||||
float cret = 0;
|
||||
volume = 1;
|
||||
|
||||
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;
|
||||
|
||||
HullError ret = hl.CreateConvexHull(desc,result);
|
||||
|
||||
if ( ret == QE_OK )
|
||||
{
|
||||
#if 0
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
|
||||
float dx = bmax[0] - bmin[0];
|
||||
float dy = bmax[1] - bmin[1];
|
||||
float dz = bmax[2] - bmin[2];
|
||||
|
||||
Vector3d center;
|
||||
|
||||
center.x = bmin[0] + dx*0.5f;
|
||||
center.y = bmin[1] + dy*0.5f;
|
||||
center.z = bmin[2] + dz*0.5f;
|
||||
#endif
|
||||
|
||||
volume = computeMeshVolume2( result.mOutputVertices, result.mNumFaces, result.mIndices );
|
||||
|
||||
#if 1
|
||||
// ok..now..for each triangle on the original mesh..
|
||||
// we extrude the points to the nearest point on the hull.
|
||||
const unsigned int *source = result.mIndices;
|
||||
|
||||
CTriVector tris;
|
||||
|
||||
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];
|
||||
|
||||
// callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF);
|
||||
|
||||
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..
|
||||
|
||||
float totalVolume = 0;
|
||||
|
||||
CTriVector ftris; // 'feature' triangles.
|
||||
|
||||
const unsigned int *src = indices;
|
||||
|
||||
|
||||
float maxc=0;
|
||||
|
||||
|
||||
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++)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( ftris.size() && 0 )
|
||||
{
|
||||
|
||||
// ok..now we extract the triangles which form the maximum concavity.
|
||||
CTriVector major_feature;
|
||||
float maxarea = 0;
|
||||
|
||||
while ( maxc > CONCAVE_THRESH )
|
||||
{
|
||||
|
||||
unsigned int color = getDebugColor(); //
|
||||
|
||||
CTriVector flist;
|
||||
|
||||
bool found;
|
||||
|
||||
float totalarea = 0;
|
||||
|
||||
do
|
||||
{
|
||||
found = false;
|
||||
CTriVector::iterator i;
|
||||
for (i=ftris.begin(); i!=ftris.end(); ++i)
|
||||
{
|
||||
CTri &t = (*i);
|
||||
if ( isFeatureTri(t,flist,maxc,callback,color) )
|
||||
{
|
||||
found = true;
|
||||
totalarea+=t.area();
|
||||
}
|
||||
}
|
||||
} while ( found );
|
||||
|
||||
|
||||
if ( totalarea > maxarea )
|
||||
{
|
||||
major_feature = flist;
|
||||
maxarea = totalarea;
|
||||
}
|
||||
|
||||
maxc = 0;
|
||||
|
||||
for (unsigned int i=0; i<ftris.size(); i++)
|
||||
{
|
||||
CTri &t = ftris[i];
|
||||
if ( t.mProcessed != 2 )
|
||||
{
|
||||
t.mProcessed = 0;
|
||||
if ( t.mConcavity > maxc )
|
||||
{
|
||||
maxc = t.mConcavity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int color = getDebugColor();
|
||||
|
||||
WpointVector list;
|
||||
for (unsigned int i=0; i<major_feature.size(); ++i)
|
||||
{
|
||||
major_feature[i].addWeighted(list,callback);
|
||||
major_feature[i].debug(color,callback);
|
||||
}
|
||||
|
||||
getBestFitPlane( list.size(), &list[0].mPoint.x, sizeof(Wpoint), &list[0].mWeight, sizeof(Wpoint), plane );
|
||||
|
||||
computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
|
||||
}
|
||||
#endif
|
||||
|
||||
cret = totalVolume;
|
||||
|
||||
hl.ReleaseResult(result);
|
||||
}
|
||||
|
||||
|
||||
return cret;
|
||||
}
|
||||
|
||||
|
||||
}
|
60
Extras/ConvexDecomposition/concavity.h
Normal file
60
Extras/ConvexDecomposition/concavity.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef COMPUTE_CONCAVITY_H
|
||||
|
||||
#define COMPUTE_CONCAVITY_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// 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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
202
Extras/ConvexDecomposition/fitsphere.cpp
Normal file
202
Extras/ConvexDecomposition/fitsphere.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "fitsphere.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
/*
|
||||
An Efficient Bounding Sphere
|
||||
by Jack Ritter
|
||||
from "Graphics Gems", Academic Press, 1990
|
||||
*/
|
||||
|
||||
/* Routine to calculate tight bounding sphere over */
|
||||
/* a set of points in 3D */
|
||||
/* This contains the routine find_bounding_sphere(), */
|
||||
/* the struct definition, and the globals used for parameters. */
|
||||
/* The abs() of all coordinates must be < BIGNUMBER */
|
||||
/* Code written by Jack Ritter and Lyle Rains. */
|
||||
|
||||
#define BIGNUMBER 100000000.0 /* hundred million */
|
||||
|
||||
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)
|
||||
{
|
||||
dest[0] = source[0];
|
||||
dest[1] = source[1];
|
||||
dest[2] = source[2];
|
||||
}
|
||||
|
||||
float computeBoundingSphere(unsigned int vcount,const float *points,float *center)
|
||||
{
|
||||
|
||||
float mRadius;
|
||||
float mRadius2;
|
||||
|
||||
float xmin[3];
|
||||
float xmax[3];
|
||||
float ymin[3];
|
||||
float ymax[3];
|
||||
float zmin[3];
|
||||
float zmax[3];
|
||||
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);
|
||||
|
||||
for (unsigned i=0; i<vcount; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
if (yspan>maxspan)
|
||||
{
|
||||
maxspan = yspan;
|
||||
Copy(dia1,ymin);
|
||||
Copy(dia2,ymax);
|
||||
}
|
||||
|
||||
if (zspan>maxspan)
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
|
||||
mRadius2 = dx*dx + dy*dy + dz*dz;
|
||||
mRadius = float(sqrt(mRadius2));
|
||||
|
||||
/* SECOND PASS: increment current sphere */
|
||||
|
||||
if ( 1 )
|
||||
{
|
||||
for (unsigned i=0; i<vcount; i++)
|
||||
{
|
||||
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];
|
||||
|
||||
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));
|
||||
/* 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;
|
||||
|
||||
/* calc center of new sphere */
|
||||
|
||||
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;
|
||||
|
||||
Set(center,cx,cy,cz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
|
43
Extras/ConvexDecomposition/fitsphere.h
Normal file
43
Extras/ConvexDecomposition/fitsphere.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef FIT_SPHERE_H
|
||||
|
||||
#define FIT_SPHERE_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
|
||||
float computeBoundingSphere(unsigned int vcount,const float *points,float *center);
|
||||
|
||||
#endif
|
257
Extras/ConvexDecomposition/float_math.cpp
Normal file
257
Extras/ConvexDecomposition/float_math.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
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];
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
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[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+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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
const unsigned char *source = (const unsigned char *) points;
|
||||
|
||||
bmin[0] = points[0];
|
||||
bmin[1] = points[1];
|
||||
bmin[2] = points[2];
|
||||
|
||||
bmax[0] = points[0];
|
||||
bmax[1] = points[1];
|
||||
bmax[2] = points[2];
|
||||
|
||||
|
||||
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] > 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.
|
||||
{
|
||||
roll *= 0.5f;
|
||||
pitch *= 0.5f;
|
||||
yaw *= 0.5f;
|
||||
|
||||
float cr = cosf(roll);
|
||||
float cp = cosf(pitch);
|
||||
float cy = cosf(yaw);
|
||||
|
||||
float sr = sinf(roll);
|
||||
float sp = sinf(pitch);
|
||||
float sy = sinf(yaw);
|
||||
|
||||
float cpcy = cp * cy;
|
||||
float spsy = sp * sy;
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
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+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.
|
||||
{
|
||||
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]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
// check the diagonal
|
||||
|
||||
if (tr > 0.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;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// diagonal is negative
|
||||
int nxt[3] = {1, 2, 0};
|
||||
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;
|
||||
|
||||
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) );
|
||||
|
||||
qa[i] = s * 0.5f;
|
||||
|
||||
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;
|
||||
|
||||
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 )
|
||||
{
|
||||
return (4.0f / 3.0f ) * FM_PI * radius * radius * radius;
|
||||
}
|
72
Extras/ConvexDecomposition/float_math.h
Normal file
72
Extras/ConvexDecomposition/float_math.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef FLOAT_MATH_H
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// a vector (or point) is a 'float *' to 3 floating point numbers.
|
||||
// a matrix is a 'float *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
|
||||
// a quaternion is a 'float *' to 4 floats representing a quaternion x,y,z,w
|
||||
|
||||
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 )
|
||||
|
||||
#endif
|
128
Extras/ConvexDecomposition/meshvolume.cpp
Normal file
128
Extras/ConvexDecomposition/meshvolume.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "float_math.h"
|
||||
#include "meshvolume.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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*=(1.0f/6.0f);
|
||||
if ( volume < 0 )
|
||||
volume*=-1;
|
||||
return volume;
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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];
|
||||
|
||||
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];
|
||||
|
||||
float cross[3];
|
||||
|
||||
CrossProduct( b, c, cross );
|
||||
|
||||
float volume = DotProduct( a, cross );
|
||||
|
||||
if ( volume < 0 )
|
||||
return -volume;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return volume * (1.0f / 6.0f );
|
||||
}
|
||||
|
45
Extras/ConvexDecomposition/meshvolume.h
Normal file
45
Extras/ConvexDecomposition/meshvolume.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef MESH_VOLUME_H
|
||||
|
||||
#define MESH_VOLUME_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// 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);
|
||||
|
||||
|
||||
#endif
|
238
Extras/ConvexDecomposition/planetri.cpp
Normal file
238
Extras/ConvexDecomposition/planetri.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "planetri.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
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];
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
static PlaneTriResult getSidePlane(const float *p,const float *plane,float epsilon)
|
||||
{
|
||||
|
||||
float d = DistToPt(p,plane);
|
||||
|
||||
if ( (d+epsilon) > 0 )
|
||||
return PTR_FRONT; // it is 'in front' within the provided epsilon value.
|
||||
|
||||
return PTR_BACK;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
||||
float dp1 = DistToPt(p1,plane);
|
||||
|
||||
float dir[3];
|
||||
|
||||
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 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.
|
||||
{
|
||||
fcount = 0;
|
||||
bcount = 0;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
if ( r1 == PTR_FRONT )
|
||||
{
|
||||
|
||||
add(p1, front, tstride, fcount );
|
||||
add(split, front, tstride, fcount );
|
||||
|
||||
add(split, back, tstride, bcount );
|
||||
add(p2, back, tstride, bcount );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
add(p1, back, tstride, bcount );
|
||||
add(split, back, tstride, bcount );
|
||||
|
||||
add(split, front, tstride, fcount );
|
||||
add(p2, front, tstride, fcount );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
if ( r3 == PTR_FRONT )
|
||||
{
|
||||
add(split, front, tstride, fcount );
|
||||
add(split, back, tstride, bcount );
|
||||
|
||||
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 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;
|
||||
}
|
58
Extras/ConvexDecomposition/planetri.h
Normal file
58
Extras/ConvexDecomposition/planetri.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef PLANE_TRI_H
|
||||
|
||||
#define PLANE_TRI_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
|
||||
enum PlaneTriResult
|
||||
{
|
||||
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.
|
||||
|
||||
|
||||
#endif
|
9
Extras/ConvexDecomposition/premake4.lua
Normal file
9
Extras/ConvexDecomposition/premake4.lua
Normal file
@ -0,0 +1,9 @@
|
||||
project "ConvexDecomposition"
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {".","../../src"}
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
134
Extras/ConvexDecomposition/raytri.cpp
Normal file
134
Extras/ConvexDecomposition/raytri.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "raytri.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
/* a = b - c */
|
||||
#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 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)
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
if (a > -0.00001 && a < 0.00001)
|
||||
return(false);
|
||||
|
||||
f = 1/a;
|
||||
vector(s,p,v0);
|
||||
u = f * (innerProduct(s,h));
|
||||
|
||||
if (u < 0.0 || u > 1.0)
|
||||
return(false);
|
||||
|
||||
crossProduct(q,s,e1);
|
||||
v = f * innerProduct(d,q);
|
||||
if (v < 0.0 || u + v > 1.0)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
|
||||
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;
|
||||
|
||||
|
||||
float t;
|
||||
|
||||
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t );
|
||||
|
||||
if ( ret )
|
||||
{
|
||||
if ( t > d )
|
||||
{
|
||||
sect[0] = rayStart[0] + dir[0]*t;
|
||||
sect[1] = rayStart[1] + dir[1]*t;
|
||||
sect[2] = rayStart[2] + dir[2]*t;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
45
Extras/ConvexDecomposition/raytri.h
Normal file
45
Extras/ConvexDecomposition/raytri.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef RAY_TRI_H
|
||||
|
||||
#define RAY_TRI_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// 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);
|
||||
|
||||
#endif
|
306
Extras/ConvexDecomposition/splitplane.cpp
Normal file
306
Extras/ConvexDecomposition/splitplane.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "splitplane.h"
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "cd_vector.h"
|
||||
#include "cd_hull.h"
|
||||
#include "cd_wavefront.h"
|
||||
#include "bestfit.h"
|
||||
#include "planetri.h"
|
||||
#include "vlookup.h"
|
||||
#include "meshvolume.h"
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
|
||||
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]);
|
||||
|
||||
float wx = (A[0] - B[0]);
|
||||
float wy = (A[1] - B[1]);
|
||||
float wz = (A[2] - B[2]);
|
||||
|
||||
float vw_x = vy * wz - vz * wy;
|
||||
float vw_y = vz * wx - vx * wz;
|
||||
float vw_z = vx * wy - vy * wx;
|
||||
|
||||
float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
|
||||
|
||||
if ( mag < 0.000001f )
|
||||
{
|
||||
mag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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]));
|
||||
|
||||
plane[0] = x;
|
||||
plane[1] = y;
|
||||
plane[2] = z;
|
||||
plane[3] = D;
|
||||
|
||||
}
|
||||
|
||||
class Rect3d
|
||||
{
|
||||
public:
|
||||
Rect3d(void) { };
|
||||
|
||||
Rect3d(const float *bmin,const float *bmax)
|
||||
{
|
||||
|
||||
mMin[0] = bmin[0];
|
||||
mMin[1] = bmin[1];
|
||||
mMin[2] = bmin[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(float x,float y,float z)
|
||||
{
|
||||
mMin[0] = x;
|
||||
mMin[1] = y;
|
||||
mMin[2] = z;
|
||||
}
|
||||
|
||||
void SetMax(float x,float y,float z)
|
||||
{
|
||||
mMax[0] = x;
|
||||
mMax[1] = y;
|
||||
mMax[2] = z;
|
||||
}
|
||||
|
||||
float mMin[3];
|
||||
float mMax[3];
|
||||
};
|
||||
|
||||
void splitRect(unsigned int axis,
|
||||
const Rect3d &source,
|
||||
Rect3d &b1,
|
||||
Rect3d &b2,
|
||||
const float *midpoint)
|
||||
{
|
||||
switch ( axis )
|
||||
{
|
||||
case 0:
|
||||
b1.SetMin(source.mMin);
|
||||
b1.SetMax( midpoint[0], source.mMax[1], source.mMax[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] );
|
||||
|
||||
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] );
|
||||
|
||||
b2.SetMin( source.mMin[0], source.mMin[1], midpoint[2] );
|
||||
b2.SetMax(source.mMax);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool computeSplitPlane(unsigned int vcount,
|
||||
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 };
|
||||
|
||||
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] > 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 )
|
||||
{
|
||||
axis = 1;
|
||||
laxis = dy;
|
||||
}
|
||||
|
||||
if ( dz > dx && dz > dy )
|
||||
{
|
||||
axis = 2;
|
||||
laxis = dz;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Rect3d b(bmin,bmax);
|
||||
|
||||
Rect3d b1,b2;
|
||||
|
||||
splitRect(axis,b,b1,b2,p1);
|
||||
|
||||
|
||||
// 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];
|
||||
|
||||
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];
|
||||
|
||||
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];
|
||||
|
||||
if ( dx > dy )
|
||||
{
|
||||
p3[0] = bmax[0];
|
||||
p3[1] = bmin[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
p3[0] = bmin[0];
|
||||
p3[1] = bmax[1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
|
||||
|
||||
computePlane(p1,p2,p3,plane);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
59
Extras/ConvexDecomposition/splitplane.h
Normal file
59
Extras/ConvexDecomposition/splitplane.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef SPLIT_PLANE_H
|
||||
|
||||
#define SPLIT_PLANE_H
|
||||
|
||||
//** Computes an 'optimal' split plane for the supplied mesh.
|
||||
//** needs much improvement since it currently just splits along
|
||||
//** the longest side of the AABB.
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// 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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
326
Extras/ConvexDecomposition/vlookup.cpp
Normal file
326
Extras/ConvexDecomposition/vlookup.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#pragma warning(disable:4786)
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// CodeSnippet provided by John W. Ratcliff
|
||||
// on March 23, 2006.
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// Personal website: http://jratcliffscarab.blogspot.com
|
||||
// Coding Website: http://codesuppository.blogspot.com
|
||||
// FundRaising Blog: http://amillionpixels.blogspot.com
|
||||
// Fundraising site: http://www.amillionpixels.us
|
||||
// New Temple Site: http://newtemple.blogspot.com
|
||||
//
|
||||
// This snippet shows how to 'hide' the complexity of
|
||||
// the STL by wrapping some useful piece of functionality
|
||||
// around a handful of discrete API calls.
|
||||
//
|
||||
// This API allows you to create an indexed triangle list
|
||||
// from a collection of raw input triangles. Internally
|
||||
// it uses an STL set to build the lookup table very rapidly.
|
||||
//
|
||||
// Here is how you would use it to build an indexed triangle
|
||||
// list from a raw list of triangles.
|
||||
//
|
||||
// (1) create a 'VertexLookup' interface by calling
|
||||
//
|
||||
// VertexLook vl = Vl_createVertexLookup();
|
||||
//
|
||||
// (2) For each vertice in each triangle call:
|
||||
//
|
||||
// unsigned int i1 = Vl_getIndex(vl,p1);
|
||||
// unsigned int i2 = Vl_getIndex(vl,p2);
|
||||
// unsigned int i3 = Vl_getIndex(vl,p3);
|
||||
//
|
||||
// save the 3 indices into your triangle list array.
|
||||
//
|
||||
// (3) Get the vertex array by calling:
|
||||
//
|
||||
// const float *vertices = Vl_getVertices(vl);
|
||||
//
|
||||
// (4) Get the number of vertices so you can copy them into
|
||||
// your own buffer.
|
||||
// unsigned int vcount = Vl_getVcount(vl);
|
||||
//
|
||||
// (5) Release the VertexLookup interface when you are done with it.
|
||||
// Vl_releaseVertexLookup(vl);
|
||||
//
|
||||
// Teaches the following lessons:
|
||||
//
|
||||
// How to wrap the complexity of STL and C++ classes around a
|
||||
// simple API interface.
|
||||
//
|
||||
// How to use an STL set and custom comparator operator for
|
||||
// a complex data type.
|
||||
//
|
||||
// How to create a template class.
|
||||
//
|
||||
// How to achieve significant performance improvements by
|
||||
// taking advantage of built in STL containers in just
|
||||
// a few lines of code.
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
|
||||
struct Tracker
|
||||
{
|
||||
VertexPosition mFind; // vertice to locate.
|
||||
VertexVector *mList;
|
||||
|
||||
Tracker()
|
||||
{
|
||||
mList = 0;
|
||||
}
|
||||
|
||||
void SetSearch(const VertexPosition& match,VertexVector *list)
|
||||
{
|
||||
mFind = match;
|
||||
mList = list;
|
||||
};
|
||||
};
|
||||
|
||||
struct VertexID
|
||||
{
|
||||
int mID;
|
||||
Tracker* mTracker;
|
||||
|
||||
VertexID(int ID, Tracker* Tracker)
|
||||
{
|
||||
mID = ID;
|
||||
mTracker = Tracker;
|
||||
}
|
||||
};
|
||||
|
||||
class VertexLess
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator()(VertexID v1,VertexID v2) const;
|
||||
|
||||
private:
|
||||
const VertexPosition& Get(VertexID index) const
|
||||
{
|
||||
if ( index.mID == -1 ) return index.mTracker->mFind;
|
||||
VertexVector &vlist = *index.mTracker->mList;
|
||||
return vlist[index.mID];
|
||||
}
|
||||
};
|
||||
|
||||
template <class Type> class VertexPool
|
||||
{
|
||||
public:
|
||||
typedef std::set<VertexID, VertexLess > VertexSet;
|
||||
typedef std::vector< Type > VertexVector;
|
||||
|
||||
int getVertex(const Type& vtx)
|
||||
{
|
||||
mTracker.SetSearch(vtx,&mVtxs);
|
||||
VertexSet::iterator found;
|
||||
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) );
|
||||
return idx;
|
||||
};
|
||||
|
||||
|
||||
const float * GetPos(int idx) const
|
||||
{
|
||||
return mVtxs[idx].mPos;
|
||||
}
|
||||
|
||||
const Type& Get(int idx) const
|
||||
{
|
||||
return mVtxs[idx];
|
||||
};
|
||||
|
||||
unsigned int GetSize(void) const
|
||||
{
|
||||
return mVtxs.size();
|
||||
};
|
||||
|
||||
void Clear(int reservesize) // clear the vertice pool.
|
||||
{
|
||||
mVertSet.clear();
|
||||
mVtxs.clear();
|
||||
mVtxs.reserve(reservesize);
|
||||
};
|
||||
|
||||
const VertexVector& GetVertexList(void) const { return mVtxs; };
|
||||
|
||||
void Set(const Type& vtx)
|
||||
{
|
||||
mVtxs.push_back(vtx);
|
||||
}
|
||||
|
||||
unsigned int GetVertexCount(void) const
|
||||
{
|
||||
return mVtxs.size();
|
||||
};
|
||||
|
||||
|
||||
Type * getBuffer(void)
|
||||
{
|
||||
return &mVtxs[0];
|
||||
};
|
||||
|
||||
private:
|
||||
VertexSet mVertSet; // ordered list.
|
||||
VertexVector mVtxs; // set of vertices.
|
||||
Tracker mTracker;
|
||||
};
|
||||
|
||||
|
||||
bool VertexLess::operator()(VertexID v1,VertexID v2) const
|
||||
{
|
||||
|
||||
const VertexPosition& a = Get(v1);
|
||||
const VertexPosition& b = Get(v2);
|
||||
|
||||
int ixA = (int) (a.GetX()*10000.0f);
|
||||
int ixB = (int) (b.GetX()*10000.0f);
|
||||
|
||||
if ( ixA < ixB ) return true;
|
||||
if ( ixA > ixB ) return false;
|
||||
|
||||
int iyA = (int) (a.GetY()*10000.0f);
|
||||
int iyB = (int) (b.GetY()*10000.0f);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
using namespace Vlookup;
|
||||
|
||||
VertexLookup Vl_createVertexLookup(void)
|
||||
{
|
||||
VertexLookup ret = new VertexPool< VertexPosition >;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Vl_releaseVertexLookup(VertexLookup vlook)
|
||||
{
|
||||
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
|
||||
delete vp;
|
||||
}
|
||||
|
||||
unsigned int Vl_getIndex(VertexLookup vlook,const float *pos) // get index.
|
||||
{
|
||||
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
|
||||
VertexPosition p(pos);
|
||||
return vp->getVertex(p);
|
||||
}
|
||||
|
||||
const float * Vl_getVertices(VertexLookup vlook)
|
||||
{
|
||||
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
|
||||
return vp->GetPos(0);
|
||||
}
|
||||
|
||||
|
||||
unsigned int Vl_getVcount(VertexLookup vlook)
|
||||
{
|
||||
VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
|
||||
return vp->GetVertexCount();
|
||||
}
|
119
Extras/ConvexDecomposition/vlookup.h
Normal file
119
Extras/ConvexDecomposition/vlookup.h
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef VLOOKUP_H
|
||||
|
||||
#define VLOOKUP_H
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
|
||||
// CodeSnippet provided by John W. Ratcliff
|
||||
// on March 23, 2006.
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// Personal website: http://jratcliffscarab.blogspot.com
|
||||
// Coding Website: http://codesuppository.blogspot.com
|
||||
// FundRaising Blog: http://amillionpixels.blogspot.com
|
||||
// Fundraising site: http://www.amillionpixels.us
|
||||
// New Temple Site: http://newtemple.blogspot.com
|
||||
//
|
||||
// This snippet shows how to 'hide' the complexity of
|
||||
// the STL by wrapping some useful piece of functionality
|
||||
// around a handful of discrete API calls.
|
||||
//
|
||||
// This API allows you to create an indexed triangle list
|
||||
// from a collection of raw input triangles. Internally
|
||||
// it uses an STL set to build the lookup table very rapidly.
|
||||
//
|
||||
// Here is how you would use it to build an indexed triangle
|
||||
// list from a raw list of triangles.
|
||||
//
|
||||
// (1) create a 'VertexLookup' interface by calling
|
||||
//
|
||||
// VertexLook vl = Vl_createVertexLookup();
|
||||
//
|
||||
// (2) For each vertice in each triangle call:
|
||||
//
|
||||
// unsigned int i1 = Vl_getIndex(vl,p1);
|
||||
// unsigned int i2 = Vl_getIndex(vl,p2);
|
||||
// unsigned int i3 = Vl_getIndex(vl,p3);
|
||||
//
|
||||
// save the 3 indices into your triangle list array.
|
||||
//
|
||||
// (3) Get the vertex array by calling:
|
||||
//
|
||||
// const float *vertices = Vl_getVertices(vl);
|
||||
//
|
||||
// (4) Get the number of vertices so you can copy them into
|
||||
// your own buffer.
|
||||
// unsigned int vcount = Vl_getVcount(vl);
|
||||
//
|
||||
// (5) Release the VertexLookup interface when you are done with it.
|
||||
// Vl_releaseVertexLookup(vl);
|
||||
//
|
||||
// Teaches the following lessons:
|
||||
//
|
||||
// How to wrap the complexity of STL and C++ classes around a
|
||||
// simple API interface.
|
||||
//
|
||||
// How to use an STL set and custom comparator operator for
|
||||
// a complex data type.
|
||||
//
|
||||
// How to create a template class.
|
||||
//
|
||||
// How to achieve significant performance improvements by
|
||||
// taking advantage of built in STL containers in just
|
||||
// a few lines of code.
|
||||
//
|
||||
// You could easily modify this code to support other vertex
|
||||
// formats with any number of interpolants.
|
||||
//
|
||||
// Hide C++ classes from the rest of your application by
|
||||
// keeping them in the CPP and wrapping them in a namespace
|
||||
// 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;
|
||||
|
||||
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
|
37
Extras/GIMPACTUtils/CMakeLists.txt
Normal file
37
Extras/GIMPACTUtils/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition
|
||||
)
|
||||
|
||||
ADD_LIBRARY(GIMPACTUtils
|
||||
btGImpactConvexDecompositionShape.cpp btGImpactConvexDecompositionShape.h
|
||||
)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(GIMPACTUtils ConvexDecomposition BulletCollision)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS GIMPACTUtils DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS GIMPACTUtils DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES PUBLIC_HEADER "btGImpactConvexDecompositionShape.h")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
240
Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp
Normal file
240
Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btGImpactConvexDecompositionShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
|
||||
|
||||
#include "ConvexBuilder.h"
|
||||
|
||||
class GIM_ConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface
|
||||
{
|
||||
protected:
|
||||
btGImpactConvexDecompositionShape * m_compoundShape;
|
||||
|
||||
btAlignedObjectArray<btCollisionShape*> m_convexShapes;
|
||||
|
||||
|
||||
public:
|
||||
int mBaseCount;
|
||||
int mHullCount;
|
||||
bool m_transformSubShapes;
|
||||
|
||||
GIM_ConvexDecomposition(btGImpactConvexDecompositionShape * compoundShape,bool transformSubShapes)
|
||||
{
|
||||
mBaseCount = 0;
|
||||
mHullCount = 0;
|
||||
m_compoundShape = compoundShape;
|
||||
m_transformSubShapes = transformSubShapes;
|
||||
}
|
||||
|
||||
virtual ~GIM_ConvexDecomposition()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<m_convexShapes.size();i++)
|
||||
{
|
||||
btCollisionShape* shape = m_convexShapes[i];
|
||||
delete shape;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
|
||||
{
|
||||
|
||||
//calc centroid, to shift vertices around center of mass
|
||||
btVector3 centroid(0,0,0);
|
||||
btAlignedObjectArray<btVector3> vertices;
|
||||
|
||||
if(m_transformSubShapes)
|
||||
{
|
||||
|
||||
//const unsigned int *src = result.mHullIndices;
|
||||
for (unsigned int i=0; i<result.mHullVcount; i++)
|
||||
{
|
||||
btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
|
||||
|
||||
centroid += vertex;
|
||||
|
||||
}
|
||||
centroid *= 1.f/(float(result.mHullVcount) );
|
||||
}
|
||||
|
||||
// collect vertices
|
||||
for (unsigned int i=0; i<result.mHullVcount; i++)
|
||||
{
|
||||
btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
|
||||
|
||||
if(m_transformSubShapes)
|
||||
{
|
||||
vertex -= centroid ;
|
||||
}
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// build convex shape
|
||||
|
||||
btCollisionShape* convexShape = new btConvexHullShape(
|
||||
&(vertices[0].getX()),vertices.size(),sizeof(btVector3));
|
||||
m_convexShapes.push_back(convexShape);
|
||||
|
||||
convexShape->setMargin(m_compoundShape->getMargin());
|
||||
|
||||
if(m_transformSubShapes)
|
||||
{
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
trans.setOrigin(centroid);
|
||||
|
||||
// add convex shape
|
||||
|
||||
m_compoundShape->addChildShape(trans,convexShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
//trans.setOrigin(centroid);
|
||||
|
||||
// add convex shape
|
||||
|
||||
m_compoundShape->addChildShape(trans,convexShape);
|
||||
|
||||
//m_compoundShape->addChildShape(convexShape);
|
||||
}
|
||||
}
|
||||
|
||||
void processDecomposition(int part)
|
||||
{
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
|
||||
m_compoundShape->getTrimeshInterface(part);
|
||||
|
||||
|
||||
trimeshInterface->lock();
|
||||
|
||||
//collect vertices
|
||||
btAlignedObjectArray<float> vertices;
|
||||
vertices.reserve(trimeshInterface->get_vertex_count()*3);
|
||||
|
||||
for(int vi = 0;vi<trimeshInterface->get_vertex_count();vi++)
|
||||
{
|
||||
btVector3 vec;
|
||||
trimeshInterface->get_vertex(vi,vec);
|
||||
vertices.push_back(vec[0]);
|
||||
vertices.push_back(vec[1]);
|
||||
vertices.push_back(vec[2]);
|
||||
}
|
||||
|
||||
|
||||
//collect indices
|
||||
btAlignedObjectArray<unsigned int> indices;
|
||||
indices.reserve(trimeshInterface->get_primitive_count()*3);
|
||||
|
||||
|
||||
for(int i = 0;i<trimeshInterface->get_primitive_count();i++)
|
||||
{
|
||||
unsigned int i0, i1,i2;
|
||||
trimeshInterface->get_indices(i,i0,i1,i2);
|
||||
indices.push_back(i0);
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i2);
|
||||
}
|
||||
|
||||
trimeshInterface->unlock();
|
||||
|
||||
|
||||
|
||||
unsigned int depth = 5;
|
||||
float cpercent = 5;
|
||||
float ppercent = 15;
|
||||
unsigned int maxv = 16;
|
||||
float skinWidth = 0.0f;
|
||||
|
||||
|
||||
ConvexDecomposition::DecompDesc desc;
|
||||
desc.mVcount = trimeshInterface->get_vertex_count();
|
||||
desc.mVertices = &vertices[0];
|
||||
desc.mTcount = trimeshInterface->get_primitive_count();
|
||||
desc.mIndices = &indices[0];
|
||||
desc.mDepth = depth;
|
||||
desc.mCpercent = cpercent;
|
||||
desc.mPpercent = ppercent;
|
||||
desc.mMaxVertices = maxv;
|
||||
desc.mSkinWidth = skinWidth;
|
||||
desc.mCallback = this;
|
||||
|
||||
//convexDecomposition.performConvexDecomposition(desc);
|
||||
|
||||
ConvexBuilder cb(desc.mCallback);
|
||||
cb.process(desc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
void btGImpactConvexDecompositionShape::buildConvexDecomposition(bool transformSubShapes)
|
||||
{
|
||||
|
||||
m_decomposition = new GIM_ConvexDecomposition(this,transformSubShapes);
|
||||
|
||||
int part_count = m_trimeshInterfaces.size();
|
||||
for (int i = 0;i<part_count ;i++ )
|
||||
{
|
||||
m_decomposition->processDecomposition(i);
|
||||
}
|
||||
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
btGImpactConvexDecompositionShape::~btGImpactConvexDecompositionShape()
|
||||
{
|
||||
delete m_decomposition;
|
||||
}
|
||||
void btGImpactConvexDecompositionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||
{
|
||||
|
||||
int part_count = m_trimeshInterfaces.size();
|
||||
for (int part = 0;part<part_count ;part++ )
|
||||
{
|
||||
void * ptr = (void * )&m_trimeshInterfaces[part];
|
||||
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
|
||||
static_cast<btGImpactMeshShapePart::TrimeshPrimitiveManager *>(ptr);
|
||||
|
||||
trimeshInterface->lock();
|
||||
|
||||
btPrimitiveTriangle triangle;
|
||||
|
||||
|
||||
int i = trimeshInterface->get_primitive_count();
|
||||
while(i--)
|
||||
{
|
||||
trimeshInterface->get_primitive_triangle(i,triangle);
|
||||
callback->processTriangle(triangle.m_vertices,part,i);
|
||||
}
|
||||
|
||||
trimeshInterface->unlock();
|
||||
}
|
||||
|
||||
|
||||
}
|
87
Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h
Normal file
87
Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*! \file btGImpactConvexDecompositionShape.h
|
||||
\author Francisco León Nájera
|
||||
*/
|
||||
/*
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
|
||||
#define GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
|
||||
|
||||
|
||||
#include "BulletCollision/Gimpact/btGImpactShape.h" // box tree class
|
||||
|
||||
|
||||
|
||||
//! This class creates a decomposition from a trimesh.
|
||||
/*!
|
||||
|
||||
*/
|
||||
class btGImpactConvexDecompositionShape : public btGImpactCompoundShape
|
||||
{
|
||||
protected:
|
||||
btAlignedObjectArray<btGImpactMeshShapePart::TrimeshPrimitiveManager> m_trimeshInterfaces;
|
||||
|
||||
class GIM_ConvexDecomposition* m_decomposition;
|
||||
|
||||
void buildConvexDecomposition(bool transformSubShapes);
|
||||
public:
|
||||
|
||||
btGImpactConvexDecompositionShape(
|
||||
btStridingMeshInterface * meshInterface,
|
||||
const btVector3 & mesh_scale,
|
||||
btScalar margin = btScalar(0.01),bool children_has_transform = true)
|
||||
:btGImpactCompoundShape(children_has_transform)
|
||||
{
|
||||
|
||||
m_collisionMargin = margin;
|
||||
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager triInterface;
|
||||
triInterface.m_meshInterface = meshInterface;
|
||||
triInterface.m_scale = mesh_scale;
|
||||
triInterface.m_margin = btScalar(1.0);
|
||||
|
||||
//add parts
|
||||
int part_count = meshInterface->getNumSubParts();
|
||||
for (int i=0;i< part_count;i++ )
|
||||
{
|
||||
triInterface.m_part = i;
|
||||
m_trimeshInterfaces.push_back(triInterface);
|
||||
}
|
||||
|
||||
m_decomposition = 0;
|
||||
|
||||
buildConvexDecomposition(children_has_transform);
|
||||
}
|
||||
|
||||
virtual ~btGImpactConvexDecompositionShape();
|
||||
|
||||
SIMD_FORCE_INLINE btGImpactMeshShapePart::TrimeshPrimitiveManager * getTrimeshInterface(int part)
|
||||
{
|
||||
return &m_trimeshInterfaces[part];
|
||||
}
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //GIMPACT_MESH_SHAPE_H
|
51
Extras/HACD/CMakeLists.txt
Normal file
51
Extras/HACD/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/HACD
|
||||
)
|
||||
|
||||
SET(HACD_SRCS
|
||||
hacdGraph.cpp
|
||||
hacdHACD.cpp
|
||||
hacdICHull.cpp
|
||||
hacdManifoldMesh.cpp
|
||||
)
|
||||
|
||||
SET(HACD_HDRS
|
||||
hacdCircularList.h
|
||||
hacdGraph.h
|
||||
hacdHACD.h
|
||||
hacdICHull.h
|
||||
hacdManifoldMesh.h
|
||||
hacdVector.h
|
||||
hacdVersion.h
|
||||
hacdCircularList.inl
|
||||
hacdVector.inl
|
||||
)
|
||||
|
||||
ADD_LIBRARY(HACD ${HACD_SRCS} ${HACD_HDRS})
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
#IF (BUILD_SHARED_LIBS)
|
||||
# TARGET_LINK_LIBRARIES(HACD BulletCollision LinearMath)
|
||||
#ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS HACD DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS HACD DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.inl" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES PUBLIC_HEADER "${HACD_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
80
Extras/HACD/hacdCircularList.h
Normal file
80
Extras/HACD/hacdCircularList.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_CIRCULAR_LIST_H
|
||||
#define HACD_CIRCULAR_LIST_H
|
||||
#include<stdlib.h>
|
||||
#include "hacdVersion.h"
|
||||
namespace HACD
|
||||
{
|
||||
//! CircularListElement class.
|
||||
template < typename T > class CircularListElement
|
||||
{
|
||||
public:
|
||||
T & GetData() { return m_data; }
|
||||
const T & GetData() const { return m_data; }
|
||||
CircularListElement<T> * & GetNext() { return m_next; }
|
||||
CircularListElement<T> * & GetPrev() { return m_prev; }
|
||||
const CircularListElement<T> * & GetNext() const { return m_next; }
|
||||
const CircularListElement<T> * & GetPrev() const { return m_prev; }
|
||||
//! Constructor
|
||||
CircularListElement(const T & data) {m_data = data;}
|
||||
CircularListElement(void){}
|
||||
//! Destructor
|
||||
~CircularListElement(void){}
|
||||
private:
|
||||
T m_data;
|
||||
CircularListElement<T> * m_next;
|
||||
CircularListElement<T> * m_prev;
|
||||
|
||||
CircularListElement(const CircularListElement & rhs);
|
||||
};
|
||||
|
||||
|
||||
//! CircularList class.
|
||||
template < typename T > class CircularList
|
||||
{
|
||||
public:
|
||||
CircularListElement<T> * & GetHead() { return m_head;}
|
||||
const CircularListElement<T> * GetHead() const { return m_head;}
|
||||
bool IsEmpty() const { return (m_size == 0);}
|
||||
size_t GetSize() const { return m_size; }
|
||||
const T & GetData() const { return m_head->GetData(); }
|
||||
T & GetData() { return m_head->GetData();}
|
||||
bool Delete() ;
|
||||
bool Delete(CircularListElement<T> * element);
|
||||
CircularListElement<T> * Add(const T * data = 0);
|
||||
CircularListElement<T> * Add(const T & data);
|
||||
bool Next();
|
||||
bool Prev();
|
||||
void Clear() { while(Delete());};
|
||||
const CircularList& operator=(const CircularList& rhs);
|
||||
//! Constructor
|
||||
CircularList()
|
||||
{
|
||||
m_head = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
CircularList(const CircularList& rhs);
|
||||
//! Destructor
|
||||
virtual ~CircularList(void) {Clear();};
|
||||
private:
|
||||
CircularListElement<T> * m_head; //!< a pointer to the head of the circular list
|
||||
size_t m_size; //!< number of element in the circular list
|
||||
|
||||
};
|
||||
}
|
||||
#include "hacdCircularList.inl"
|
||||
#endif
|
163
Extras/HACD/hacdCircularList.inl
Normal file
163
Extras/HACD/hacdCircularList.inl
Normal file
@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
#ifndef HACD_CIRCULAR_LIST_INL
|
||||
#define HACD_CIRCULAR_LIST_INL
|
||||
#include<stdlib.h>
|
||||
#include "hacdVersion.h"
|
||||
namespace HACD
|
||||
{
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Delete(CircularListElement<T> * element)
|
||||
{
|
||||
if (!element)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_size > 1)
|
||||
{
|
||||
CircularListElement<T> * next = element->GetNext();
|
||||
CircularListElement<T> * prev = element->GetPrev();
|
||||
delete element;
|
||||
m_size--;
|
||||
if (element == m_head)
|
||||
{
|
||||
m_head = next;
|
||||
}
|
||||
next->GetPrev() = prev;
|
||||
prev->GetNext() = next;
|
||||
return true;
|
||||
}
|
||||
else if (m_size == 1)
|
||||
{
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Delete()
|
||||
{
|
||||
if (m_size > 1)
|
||||
{
|
||||
CircularListElement<T> * next = m_head->GetNext();
|
||||
CircularListElement<T> * prev = m_head->GetPrev();
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = next;
|
||||
next->GetPrev() = prev;
|
||||
prev->GetNext() = next;
|
||||
return true;
|
||||
}
|
||||
else if (m_size == 1)
|
||||
{
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularListElement<T> * CircularList<T>::Add(const T * data)
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_head = new CircularListElement<T>(*data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_head = new CircularListElement<T>();
|
||||
}
|
||||
m_head->GetNext() = m_head->GetPrev() = m_head;
|
||||
}
|
||||
else
|
||||
{
|
||||
CircularListElement<T> * next = m_head->GetNext();
|
||||
CircularListElement<T> * element = m_head;
|
||||
if (data)
|
||||
{
|
||||
m_head = new CircularListElement<T>(*data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_head = new CircularListElement<T>;
|
||||
}
|
||||
m_head->GetNext() = next;
|
||||
m_head->GetPrev() = element;
|
||||
element->GetNext() = m_head;
|
||||
next->GetPrev() = m_head;
|
||||
}
|
||||
m_size++;
|
||||
return m_head;
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularListElement<T> * CircularList<T>::Add(const T & data)
|
||||
{
|
||||
const T * pData = &data;
|
||||
return Add(pData);
|
||||
}
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Next()
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_head = m_head->GetNext();
|
||||
return true;
|
||||
}
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Prev()
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_head = m_head->GetPrev();
|
||||
return true;
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularList<T>::CircularList(const CircularList& rhs)
|
||||
{
|
||||
if (rhs.m_size > 0)
|
||||
{
|
||||
CircularListElement<T> * current = rhs.m_head;
|
||||
do
|
||||
{
|
||||
current = current->GetNext();
|
||||
Add(current->GetData());
|
||||
}
|
||||
while ( current != rhs.m_head );
|
||||
}
|
||||
}
|
||||
template < typename T >
|
||||
inline const CircularList<T>& CircularList<T>::operator=(const CircularList& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
Clear();
|
||||
if (rhs.m_size > 0)
|
||||
{
|
||||
CircularListElement<T> * current = rhs.m_head;
|
||||
do
|
||||
{
|
||||
current = current->GetNext();
|
||||
Add(current->GetData());
|
||||
}
|
||||
while ( current != rhs.m_head );
|
||||
}
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
}
|
||||
#endif
|
292
Extras/HACD/hacdGraph.cpp
Normal file
292
Extras/HACD/hacdGraph.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "hacdGraph.h"
|
||||
namespace HACD
|
||||
{
|
||||
|
||||
GraphEdge::GraphEdge()
|
||||
{
|
||||
m_convexHull = 0;
|
||||
m_v1 = -1;
|
||||
m_v2 = -1;
|
||||
m_name = -1;
|
||||
m_error = 0;
|
||||
m_surf = 0;
|
||||
m_perimeter = 0;
|
||||
m_concavity = 0;
|
||||
m_volume = 0;
|
||||
m_deleted = false;
|
||||
}
|
||||
|
||||
GraphVertex::GraphVertex()
|
||||
{
|
||||
m_convexHull = 0;
|
||||
m_name = -1;
|
||||
m_cc = -1;
|
||||
m_error = 0;
|
||||
m_surf = 0;
|
||||
m_perimeter = 0;
|
||||
m_concavity = 0;
|
||||
m_volume = 0;
|
||||
m_deleted = false;
|
||||
}
|
||||
|
||||
bool GraphVertex::DeleteEdge(long name)
|
||||
{
|
||||
std::set<long>::iterator it = m_edges.find(name);
|
||||
if (it != m_edges.end() )
|
||||
{
|
||||
m_edges.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Graph::Graph()
|
||||
{
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
m_nCCs = 0;
|
||||
}
|
||||
|
||||
Graph::~Graph()
|
||||
{
|
||||
}
|
||||
|
||||
void Graph::Allocate(size_t nV, size_t nE)
|
||||
{
|
||||
m_nV = nV;
|
||||
m_edges.reserve(nE);
|
||||
m_vertices.resize(nV);
|
||||
for(size_t i = 0; i < nV; i++)
|
||||
{
|
||||
m_vertices[i].m_name = static_cast<long>(i);
|
||||
}
|
||||
}
|
||||
|
||||
long Graph::AddVertex()
|
||||
{
|
||||
size_t name = m_vertices.size();
|
||||
m_vertices.resize(name+1);
|
||||
m_vertices[name].m_name = static_cast<long>(name);
|
||||
m_nV++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
|
||||
long Graph::AddEdge(long v1, long v2)
|
||||
{
|
||||
size_t name = m_edges.size();
|
||||
m_edges.push_back(GraphEdge());
|
||||
m_edges[name].m_name = static_cast<long>(name);
|
||||
m_edges[name].m_v1 = v1;
|
||||
m_edges[name].m_v2 = v2;
|
||||
m_vertices[v1].AddEdge(static_cast<long>(name));
|
||||
m_vertices[v2].AddEdge(static_cast<long>(name));
|
||||
m_nE++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
|
||||
bool Graph::DeleteEdge(long name)
|
||||
{
|
||||
if (name < static_cast<long>(m_edges.size()))
|
||||
{
|
||||
long v1 = m_edges[name].m_v1;
|
||||
long v2 = m_edges[name].m_v2;
|
||||
m_edges[name].m_deleted = true;
|
||||
m_vertices[v1].DeleteEdge(name);
|
||||
m_vertices[v2].DeleteEdge(name);
|
||||
delete m_edges[name].m_convexHull;
|
||||
m_edges[name].m_distPoints.clear();
|
||||
m_edges[name].m_boudaryEdges.clear();
|
||||
m_edges[name].m_convexHull = 0;
|
||||
m_nE--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Graph::DeleteVertex(long name)
|
||||
{
|
||||
if (name < static_cast<long>(m_vertices.size()))
|
||||
{
|
||||
m_vertices[name].m_deleted = true;
|
||||
m_vertices[name].m_edges.clear();
|
||||
m_vertices[name].m_ancestors = std::vector<long>();
|
||||
delete m_vertices[name].m_convexHull;
|
||||
m_vertices[name].m_distPoints.clear();
|
||||
m_vertices[name].m_boudaryEdges.clear();
|
||||
m_vertices[name].m_convexHull = 0;
|
||||
m_nV--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Graph::EdgeCollapse(long v1, long v2)
|
||||
{
|
||||
long edgeToDelete = GetEdgeID(v1, v2);
|
||||
if (edgeToDelete >= 0)
|
||||
{
|
||||
// delete the edge (v1, v2)
|
||||
DeleteEdge(edgeToDelete);
|
||||
// add v2 to v1 ancestors
|
||||
m_vertices[v1].m_ancestors.push_back(v2);
|
||||
// add v2's ancestors to v1's ancestors
|
||||
m_vertices[v1].m_ancestors.insert(m_vertices[v1].m_ancestors.begin(),
|
||||
m_vertices[v2].m_ancestors.begin(),
|
||||
m_vertices[v2].m_ancestors.end());
|
||||
// update adjacency information
|
||||
std::set<long> & v1Edges = m_vertices[v1].m_edges;
|
||||
std::set<long>::const_iterator ed(m_vertices[v2].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[v2].m_edges.end());
|
||||
long b = -1;
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
if (m_edges[*ed].m_v1 == v2)
|
||||
{
|
||||
b = m_edges[*ed].m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = m_edges[*ed].m_v1;
|
||||
}
|
||||
if (GetEdgeID(v1, b) >= 0)
|
||||
{
|
||||
m_edges[*ed].m_deleted = true;
|
||||
m_vertices[b].DeleteEdge(*ed);
|
||||
m_nE--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edges[*ed].m_v1 = v1;
|
||||
m_edges[*ed].m_v2 = b;
|
||||
v1Edges.insert(*ed);
|
||||
}
|
||||
}
|
||||
// delete the vertex v2
|
||||
DeleteVertex(v2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long Graph::GetEdgeID(long v1, long v2) const
|
||||
{
|
||||
if (v1 < static_cast<long>(m_vertices.size()) && !m_vertices[v1].m_deleted)
|
||||
{
|
||||
std::set<long>::const_iterator ed(m_vertices[v1].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[v1].m_edges.end());
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
if ( (m_edges[*ed].m_v1 == v2) ||
|
||||
(m_edges[*ed].m_v2 == v2) )
|
||||
{
|
||||
return m_edges[*ed].m_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Graph::Print() const
|
||||
{
|
||||
std::cout << "-----------------------------" << std::endl;
|
||||
std::cout << "vertices (" << m_nV << ")" << std::endl;
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
const GraphVertex & currentVertex = m_vertices[v];
|
||||
if (!m_vertices[v].m_deleted)
|
||||
{
|
||||
|
||||
std::cout << currentVertex.m_name << "\t";
|
||||
std::set<long>::const_iterator ed(currentVertex.m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(currentVertex.m_edges.end());
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
std::cout << "(" << m_edges[*ed].m_v1 << "," << m_edges[*ed].m_v2 << ") ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "vertices (" << m_nE << ")" << std::endl;
|
||||
for (size_t e = 0; e < m_edges.size(); ++e)
|
||||
{
|
||||
const GraphEdge & currentEdge = m_edges[e];
|
||||
if (!m_edges[e].m_deleted)
|
||||
{
|
||||
std::cout << currentEdge.m_name << "\t("
|
||||
<< m_edges[e].m_v1 << ","
|
||||
<< m_edges[e].m_v2 << ") "<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Graph::Clear()
|
||||
{
|
||||
m_vertices.clear();
|
||||
m_edges.clear();
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
}
|
||||
|
||||
long Graph::ExtractCCs()
|
||||
{
|
||||
// all CCs to -1
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted)
|
||||
{
|
||||
m_vertices[v].m_cc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// we get the CCs
|
||||
m_nCCs = 0;
|
||||
long v2 = -1;
|
||||
std::vector<long> temp;
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted && m_vertices[v].m_cc == -1)
|
||||
{
|
||||
m_vertices[v].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.clear();
|
||||
temp.push_back(m_vertices[v].m_name);
|
||||
while (temp.size())
|
||||
{
|
||||
long vertex = temp[temp.size()-1];
|
||||
temp.pop_back();
|
||||
std::set<long>::const_iterator ed(m_vertices[vertex].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[vertex].m_edges.end());
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
if (m_edges[*ed].m_v1 == vertex)
|
||||
{
|
||||
v2 = m_edges[*ed].m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
v2 = m_edges[*ed].m_v1;
|
||||
}
|
||||
if ( !m_vertices[v2].m_deleted && m_vertices[v2].m_cc == -1)
|
||||
{
|
||||
m_vertices[v2].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.push_back(v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nCCs++;
|
||||
}
|
||||
}
|
||||
return static_cast<long>(m_nCCs);
|
||||
}
|
||||
}
|
120
Extras/HACD/hacdGraph.h
Normal file
120
Extras/HACD/hacdGraph.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_GRAPH_H
|
||||
#define HACD_GRAPH_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdVector.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
class GraphVertex;
|
||||
class GraphEdge;
|
||||
class Graph;
|
||||
class HACD;
|
||||
|
||||
class GraphVertex
|
||||
{
|
||||
public:
|
||||
bool AddEdge(long name)
|
||||
{
|
||||
m_edges.insert(name);
|
||||
return true;
|
||||
}
|
||||
bool DeleteEdge(long name);
|
||||
GraphVertex();
|
||||
~GraphVertex(){ delete m_convexHull;};
|
||||
private:
|
||||
long m_name;
|
||||
long m_cc;
|
||||
std::set<long> m_edges;
|
||||
bool m_deleted;
|
||||
std::vector<long> m_ancestors;
|
||||
std::map<long, DPoint> m_distPoints;
|
||||
|
||||
Real m_error;
|
||||
double m_surf;
|
||||
double m_volume;
|
||||
double m_perimeter;
|
||||
double m_concavity;
|
||||
ICHull * m_convexHull;
|
||||
std::set<unsigned long long> m_boudaryEdges;
|
||||
|
||||
|
||||
friend class GraphEdge;
|
||||
friend class Graph;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
class GraphEdge
|
||||
{
|
||||
public:
|
||||
GraphEdge();
|
||||
~GraphEdge(){delete m_convexHull;};
|
||||
private:
|
||||
long m_name;
|
||||
long m_v1;
|
||||
long m_v2;
|
||||
std::map<long, DPoint> m_distPoints;
|
||||
Real m_error;
|
||||
double m_surf;
|
||||
double m_volume;
|
||||
double m_perimeter;
|
||||
double m_concavity;
|
||||
ICHull * m_convexHull;
|
||||
std::set<unsigned long long> m_boudaryEdges;
|
||||
bool m_deleted;
|
||||
|
||||
|
||||
|
||||
friend class GraphVertex;
|
||||
friend class Graph;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
class Graph
|
||||
{
|
||||
public:
|
||||
size_t GetNEdges() const { return m_nE;}
|
||||
size_t GetNVertices() const { return m_nV;}
|
||||
bool EdgeCollapse(long v1, long v2);
|
||||
long AddVertex();
|
||||
long AddEdge(long v1, long v2);
|
||||
bool DeleteEdge(long name);
|
||||
bool DeleteVertex(long name);
|
||||
long GetEdgeID(long v1, long v2) const;
|
||||
void Clear();
|
||||
void Print() const;
|
||||
long ExtractCCs();
|
||||
|
||||
Graph();
|
||||
virtual ~Graph();
|
||||
void Allocate(size_t nV, size_t nE);
|
||||
|
||||
private:
|
||||
size_t m_nCCs;
|
||||
size_t m_nV;
|
||||
size_t m_nE;
|
||||
std::vector<GraphEdge> m_edges;
|
||||
std::vector<GraphVertex> m_vertices;
|
||||
|
||||
friend class HACD;
|
||||
};
|
||||
}
|
||||
#endif
|
847
Extras/HACD/hacdHACD.cpp
Normal file
847
Extras/HACD/hacdHACD.cpp
Normal file
@ -0,0 +1,847 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif //_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <sstream>
|
||||
#include "hacdGraph.h"
|
||||
#include "hacdHACD.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
bool gCancelRequest=false;
|
||||
namespace HACD
|
||||
{
|
||||
double HACD::Concavity(ICHull & ch, std::map<long, DPoint> & distPoints)
|
||||
{
|
||||
double concavity = 0.0;
|
||||
double distance = 0.0;
|
||||
std::map<long, DPoint>::iterator itDP(distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(distPoints.end());
|
||||
for(; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
if (!(itDP->second).m_computed)
|
||||
{
|
||||
if (itDP->first >= 0)
|
||||
{
|
||||
distance = ch.ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], (itDP->second).m_computed, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = ch.ComputeDistance(itDP->first, m_facePoints[-itDP->first-1], m_faceNormals[-itDP->first-1], (itDP->second).m_computed, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = (itDP->second).m_dist;
|
||||
}
|
||||
if (concavity < distance)
|
||||
{
|
||||
concavity = distance;
|
||||
}
|
||||
}
|
||||
return concavity;
|
||||
}
|
||||
|
||||
void HACD::CreateGraph()
|
||||
{
|
||||
// vertex to triangle adjacency information
|
||||
std::vector< std::set<long> > vertexToTriangles;
|
||||
vertexToTriangles.resize(m_nPoints);
|
||||
for(size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
|
||||
}
|
||||
|
||||
m_graph.Clear();
|
||||
m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
|
||||
unsigned long long tr1[3];
|
||||
unsigned long long tr2[3];
|
||||
long i1, j1, k1, i2, j2, k2;
|
||||
long t1, t2;
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
std::set<long>::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end());
|
||||
for(; it1 != itEnd; ++it1)
|
||||
{
|
||||
t1 = *it1;
|
||||
i1 = m_triangles[t1].X();
|
||||
j1 = m_triangles[t1].Y();
|
||||
k1 = m_triangles[t1].Z();
|
||||
tr1[0] = GetEdgeIndex(i1, j1);
|
||||
tr1[1] = GetEdgeIndex(j1, k1);
|
||||
tr1[2] = GetEdgeIndex(k1, i1);
|
||||
std::set<long>::const_iterator it2(it1);
|
||||
for(++it2; it2 != itEnd; ++it2)
|
||||
{
|
||||
t2 = *it2;
|
||||
i2 = m_triangles[t2].X();
|
||||
j2 = m_triangles[t2].Y();
|
||||
k2 = m_triangles[t2].Z();
|
||||
tr2[0] = GetEdgeIndex(i2, j2);
|
||||
tr2[1] = GetEdgeIndex(j2, k2);
|
||||
tr2[2] = GetEdgeIndex(k2, i2);
|
||||
int shared = 0;
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
for(int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (tr1[i] == tr2[j])
|
||||
{
|
||||
shared++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shared == 1) // two triangles are connected if they share exactly one edge
|
||||
{
|
||||
m_graph.AddEdge(t1, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_ccConnectDist >= 0.0)
|
||||
{
|
||||
m_graph.ExtractCCs();
|
||||
if (m_graph.m_nCCs > 1)
|
||||
{
|
||||
std::vector< std::set<long> > cc2V;
|
||||
cc2V.resize(m_graph.m_nCCs);
|
||||
long cc;
|
||||
for(size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
cc = m_graph.m_vertices[t].m_cc;
|
||||
cc2V[cc].insert(m_triangles[t].X());
|
||||
cc2V[cc].insert(m_triangles[t].Y());
|
||||
cc2V[cc].insert(m_triangles[t].Z());
|
||||
}
|
||||
|
||||
for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
|
||||
{
|
||||
for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2)
|
||||
{
|
||||
std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
|
||||
for(; itV1 != itVEnd1; ++itV1)
|
||||
{
|
||||
double distC1C2 = std::numeric_limits<double>::max();
|
||||
double dist;
|
||||
t1 = -1;
|
||||
t2 = -1;
|
||||
std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
|
||||
for(; itV2 != itVEnd2; ++itV2)
|
||||
{
|
||||
dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
|
||||
if (dist < distC1C2)
|
||||
{
|
||||
distC1C2 = dist;
|
||||
t1 = *vertexToTriangles[*itV1].begin();
|
||||
|
||||
std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
|
||||
it2End(vertexToTriangles[*itV2].end());
|
||||
t2 = -1;
|
||||
for(; it2 != it2End; ++it2)
|
||||
{
|
||||
if (*it2 != t1)
|
||||
{
|
||||
t2 = *it2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (distC1C2 <= m_ccConnectDist && t1 > 0 && t2 > 0)
|
||||
{
|
||||
|
||||
m_graph.AddEdge(t1, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void HACD::InitializeDualGraph()
|
||||
{
|
||||
long i, j, k;
|
||||
Vec3<Real> u, v, w, normal;
|
||||
delete [] m_normals;
|
||||
m_normals = new Vec3<Real>[m_nPoints];
|
||||
if (m_addFacesPoints)
|
||||
{
|
||||
delete [] m_facePoints;
|
||||
delete [] m_faceNormals;
|
||||
m_facePoints = new Vec3<Real>[m_nTriangles];
|
||||
m_faceNormals = new Vec3<Real>[m_nTriangles];
|
||||
}
|
||||
memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints);
|
||||
for(unsigned long f = 0; f < m_nTriangles; f++)
|
||||
{
|
||||
if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0);
|
||||
|
||||
if (gCancelRequest)
|
||||
return;
|
||||
|
||||
i = m_triangles[f].X();
|
||||
j = m_triangles[f].Y();
|
||||
k = m_triangles[f].Z();
|
||||
|
||||
m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false;
|
||||
m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false;
|
||||
m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false;
|
||||
|
||||
ICHull * ch = new ICHull;
|
||||
m_graph.m_vertices[f].m_convexHull = ch;
|
||||
ch->AddPoint(m_points[i], i);
|
||||
ch->AddPoint(m_points[j], j);
|
||||
ch->AddPoint(m_points[k], k);
|
||||
ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints);
|
||||
|
||||
u = m_points[j] - m_points[i];
|
||||
v = m_points[k] - m_points[i];
|
||||
w = m_points[k] - m_points[j];
|
||||
normal = u ^ v;
|
||||
|
||||
m_normals[i] += normal;
|
||||
m_normals[j] += normal;
|
||||
m_normals[k] += normal;
|
||||
|
||||
m_graph.m_vertices[f].m_surf = normal.GetNorm();
|
||||
m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm();
|
||||
|
||||
normal.Normalize();
|
||||
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j));
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k));
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i));
|
||||
if(m_addFacesPoints)
|
||||
{
|
||||
m_faceNormals[f] = normal;
|
||||
m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0;
|
||||
m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f)-1].m_distOnly = true;
|
||||
}
|
||||
if (m_addExtraDistPoints)
|
||||
{// we need a kd-tree structure to accelerate this part!
|
||||
long i1, j1, k1;
|
||||
Vec3<Real> u1, v1, normal1;
|
||||
normal = -normal;
|
||||
double distance = 0.0;
|
||||
double distMin = 0.0;
|
||||
size_t faceIndex = m_nTriangles;
|
||||
Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0);
|
||||
long nhit = 0;
|
||||
for(size_t f1 = 0; f1 < m_nTriangles; f1++)
|
||||
{
|
||||
i1 = m_triangles[f1].X();
|
||||
j1 = m_triangles[f1].Y();
|
||||
k1 = m_triangles[f1].Z();
|
||||
u1 = m_points[j1] - m_points[i1];
|
||||
v1 = m_points[k1] - m_points[i1];
|
||||
normal1 = (u1 ^ v1);
|
||||
if (normal * normal1 > 0.0)
|
||||
{
|
||||
nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()),
|
||||
Vec3<double>(normal.X(), normal.Y(), normal.Z()),
|
||||
Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()),
|
||||
Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()),
|
||||
Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()),
|
||||
distance);
|
||||
if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles)))
|
||||
{
|
||||
distMin = distance;
|
||||
faceIndex = f1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (faceIndex < m_nTriangles )
|
||||
{
|
||||
i1 = m_triangles[faceIndex].X();
|
||||
j1 = m_triangles[faceIndex].Y();
|
||||
k1 = m_triangles[faceIndex].Z();
|
||||
m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true;
|
||||
m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true;
|
||||
m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true;
|
||||
if (m_addFacesPoints)
|
||||
{
|
||||
m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex)-1].m_distOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
m_normals[v].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
void HACD::NormalizeData()
|
||||
{
|
||||
if (m_nPoints == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_barycenter = m_points[0];
|
||||
Vec3<Real> min = m_points[0];
|
||||
Vec3<Real> max = m_points[0];
|
||||
Real x, y, z;
|
||||
for (size_t v = 1; v < m_nPoints ; v++)
|
||||
{
|
||||
m_barycenter += m_points[v];
|
||||
x = m_points[v].X();
|
||||
y = m_points[v].Y();
|
||||
z = m_points[v].Z();
|
||||
if ( x < min.X()) min.X() = x;
|
||||
else if ( x > max.X()) max.X() = x;
|
||||
if ( y < min.Y()) min.Y() = y;
|
||||
else if ( y > max.Y()) max.Y() = y;
|
||||
if ( z < min.Z()) min.Z() = z;
|
||||
else if ( z > max.Z()) max.Z() = z;
|
||||
}
|
||||
m_barycenter /= static_cast<Real>(m_nPoints);
|
||||
m_diag = (max-min).GetNorm();
|
||||
const Real invDiag = static_cast<Real>(2.0 * m_scale / m_diag);
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for (size_t v = 0; v < m_nPoints ; v++)
|
||||
{
|
||||
m_points[v] = (m_points[v] - m_barycenter) * invDiag;
|
||||
}
|
||||
}
|
||||
}
|
||||
void HACD::DenormalizeData()
|
||||
{
|
||||
if (m_nPoints == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
const Real diag = static_cast<Real>(m_diag / (2.0 * m_scale));
|
||||
for (size_t v = 0; v < m_nPoints ; v++)
|
||||
{
|
||||
m_points[v] = m_points[v] * diag + m_barycenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
HACD::HACD(void)
|
||||
{
|
||||
m_convexHulls = 0;
|
||||
m_triangles = 0;
|
||||
m_points = 0;
|
||||
m_normals = 0;
|
||||
m_nTriangles = 0;
|
||||
m_nPoints = 0;
|
||||
m_nClusters = 0;
|
||||
m_concavity = 0.0;
|
||||
m_diag = 1.0;
|
||||
m_barycenter = Vec3<Real>(0.0, 0.0,0.0);
|
||||
m_alpha = 0.1;
|
||||
m_beta = 0.1;
|
||||
m_nVerticesPerCH = 30;
|
||||
m_callBack = 0;
|
||||
m_addExtraDistPoints = false;
|
||||
m_addNeighboursDistPoints = false;
|
||||
m_scale = 1000.0;
|
||||
m_partition = 0;
|
||||
m_nMinClusters = 3;
|
||||
m_facePoints = 0;
|
||||
m_faceNormals = 0;
|
||||
m_ccConnectDist = 30;
|
||||
}
|
||||
HACD::~HACD(void)
|
||||
{
|
||||
delete [] m_normals;
|
||||
delete [] m_convexHulls;
|
||||
delete [] m_partition;
|
||||
delete [] m_facePoints;
|
||||
delete [] m_faceNormals;
|
||||
}
|
||||
int iteration = 0;
|
||||
void HACD::ComputeEdgeCost(size_t e)
|
||||
{
|
||||
GraphEdge & gE = m_graph.m_edges[e];
|
||||
long v1 = gE.m_v1;
|
||||
long v2 = gE.m_v2;
|
||||
|
||||
if (m_graph.m_vertices[v2].m_distPoints.size()>m_graph.m_vertices[v1].m_distPoints.size())
|
||||
{
|
||||
gE.m_v1 = v2;
|
||||
gE.m_v2 = v1;
|
||||
//std::swap<long>(v1, v2);
|
||||
std::swap(v1, v2);
|
||||
}
|
||||
GraphVertex & gV1 = m_graph.m_vertices[v1];
|
||||
GraphVertex & gV2 = m_graph.m_vertices[v2];
|
||||
|
||||
// delete old convex-hull
|
||||
delete gE.m_convexHull;
|
||||
// create the edge's convex-hull
|
||||
ICHull * ch = new ICHull;
|
||||
gE.m_convexHull = ch;
|
||||
(*ch) = (*gV1.m_convexHull);
|
||||
|
||||
// update distPoints
|
||||
gE.m_distPoints = gV1.m_distPoints;
|
||||
std::map<long, DPoint>::iterator itDP(gV2.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gV2.m_distPoints.end());
|
||||
std::map<long, DPoint>::iterator itDP1;
|
||||
|
||||
for(; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
itDP1 = gE.m_distPoints.find(itDP->first);
|
||||
if (itDP1 == gE.m_distPoints.end())
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = (itDP->second).m_distOnly;
|
||||
if ( !(itDP->second).m_distOnly )
|
||||
{
|
||||
ch->AddPoint(m_points[itDP->first], itDP->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (itDP1->second).m_distOnly && !(itDP->second).m_distOnly)
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = false;
|
||||
ch->AddPoint(m_points[itDP->first], itDP->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ch->SetDistPoints(&gE.m_distPoints);
|
||||
// create the convex-hull
|
||||
while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!!
|
||||
{
|
||||
// if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0);
|
||||
ch = new ICHull;
|
||||
CircularList<TMMVertex> & verticesCH = (gE.m_convexHull)->GetMesh().m_vertices;
|
||||
size_t nV = verticesCH.GetSize();
|
||||
long ptIndex = 0;
|
||||
verticesCH.Next();
|
||||
for(size_t v = 1; v < nV; ++v)
|
||||
{
|
||||
ptIndex = verticesCH.GetHead()->GetData().m_name;
|
||||
ch->AddPoint(m_points[ptIndex], ptIndex);
|
||||
verticesCH.Next();
|
||||
}
|
||||
delete gE.m_convexHull;
|
||||
gE.m_convexHull = ch;
|
||||
}
|
||||
double volume = 0.0;
|
||||
double concavity = 0.0;
|
||||
if (ch->IsFlat())
|
||||
{
|
||||
bool insideHull;
|
||||
std::map<long, DPoint>::iterator itDP(gE.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gE.m_distPoints.end());
|
||||
for(; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
if (itDP->first >= 0)
|
||||
{
|
||||
concavity = std::max<double>(concavity, ch->ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], insideHull, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_addNeighboursDistPoints)
|
||||
{ // add distance points from adjacent clusters
|
||||
std::set<long> eEdges;
|
||||
std::set_union(gV1.m_edges.begin(),
|
||||
gV1.m_edges.end(),
|
||||
gV2.m_edges.begin(),
|
||||
gV2.m_edges.end(),
|
||||
std::inserter( eEdges, eEdges.begin() ) );
|
||||
|
||||
std::set<long>::const_iterator ed(eEdges.begin());
|
||||
std::set<long>::const_iterator itEnd(eEdges.end());
|
||||
long a, b, c;
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
a = m_graph.m_edges[*ed].m_v1;
|
||||
b = m_graph.m_edges[*ed].m_v2;
|
||||
if ( a != v2 && a != v1)
|
||||
{
|
||||
c = a;
|
||||
}
|
||||
else if ( b != v2 && b != v1)
|
||||
{
|
||||
c = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
if ( c > 0)
|
||||
{
|
||||
GraphVertex & gVC = m_graph.m_vertices[c];
|
||||
std::map<long, DPoint>::iterator itDP(gVC.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gVC.m_distPoints.end());
|
||||
std::map<long, DPoint>::iterator itDP1;
|
||||
for(; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
itDP1 = gE.m_distPoints.find(itDP->first);
|
||||
if (itDP1 == gE.m_distPoints.end())
|
||||
{
|
||||
if (itDP->first >= 0 && itDP1 == gE.m_distPoints.end() && ch->IsInside(m_points[itDP->first]))
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = true;
|
||||
}
|
||||
else if (itDP->first < 0 && ch->IsInside(m_facePoints[-itDP->first-1]))
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
concavity = Concavity(*ch, gE.m_distPoints);
|
||||
}
|
||||
|
||||
// compute boudary edges
|
||||
double perimeter = 0.0;
|
||||
double surf = 1.0;
|
||||
if (m_alpha > 0.0)
|
||||
{
|
||||
gE.m_boudaryEdges.clear();
|
||||
std::set_symmetric_difference (gV1.m_boudaryEdges.begin(),
|
||||
gV1.m_boudaryEdges.end(),
|
||||
gV2.m_boudaryEdges.begin(),
|
||||
gV2.m_boudaryEdges.end(),
|
||||
std::inserter( gE.m_boudaryEdges,
|
||||
gE.m_boudaryEdges.begin() ) );
|
||||
|
||||
std::set<unsigned long long>::const_iterator itBE(gE.m_boudaryEdges.begin());
|
||||
std::set<unsigned long long>::const_iterator itBEEnd(gE.m_boudaryEdges.end());
|
||||
for(; itBE != itBEEnd; ++itBE)
|
||||
{
|
||||
perimeter += (m_points[static_cast<long>((*itBE) >> 32)] -
|
||||
m_points[static_cast<long>((*itBE) & 0xFFFFFFFFULL)]).GetNorm();
|
||||
}
|
||||
surf = gV1.m_surf + gV2.m_surf;
|
||||
}
|
||||
double ratio = perimeter * perimeter / (4.0 * sc_pi * surf);
|
||||
gE.m_volume = (m_beta == 0.0)?0.0:ch->ComputeVolume()/pow(m_scale, 3.0); // cluster's volume
|
||||
gE.m_surf = surf; // cluster's area
|
||||
gE.m_perimeter = perimeter; // cluster's perimeter
|
||||
gE.m_concavity = concavity; // cluster's concavity
|
||||
gE.m_error = static_cast<Real>(concavity + m_alpha * ratio + m_beta * volume); // cluster's priority
|
||||
}
|
||||
bool HACD::InitializePriorityQueue()
|
||||
{
|
||||
m_pqueue.reserve(m_graph.m_nE + 100);
|
||||
for (size_t e=0; e < m_graph.m_nE; ++e)
|
||||
{
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void HACD::Simplify()
|
||||
{
|
||||
long v1 = -1;
|
||||
long v2 = -1;
|
||||
double progressOld = -1.0;
|
||||
double progress = 0.0;
|
||||
double globalConcavity = 0.0;
|
||||
char msg[1024];
|
||||
double ptgStep = 1.0;
|
||||
while ( (globalConcavity < m_concavity) &&
|
||||
(m_graph.GetNVertices() > m_nMinClusters) &&
|
||||
(m_graph.GetNEdges() > 0))
|
||||
{
|
||||
progress = 100.0-m_graph.GetNVertices() * 100.0 / m_nTriangles;
|
||||
if (fabs(progress-progressOld) > ptgStep && m_callBack)
|
||||
{
|
||||
sprintf(msg, "%3.2f %% V = %lu \t C = %f \t \t \r", progress, static_cast<unsigned long>(m_graph.GetNVertices()), globalConcavity);
|
||||
(*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
|
||||
progressOld = progress;
|
||||
if (progress > 99.0)
|
||||
{
|
||||
ptgStep = 0.01;
|
||||
}
|
||||
else if (progress > 90.0)
|
||||
{
|
||||
ptgStep = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
GraphEdgePriorityQueue currentEdge(0,0.0);
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
done = false;
|
||||
if (m_pqueue.size() == 0)
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
currentEdge = m_pqueue.top();
|
||||
m_pqueue.pop();
|
||||
}
|
||||
while ( m_graph.m_edges[currentEdge.m_name].m_deleted ||
|
||||
m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority);
|
||||
|
||||
|
||||
if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done)
|
||||
{
|
||||
globalConcavity = std::max<double>(globalConcavity ,m_graph.m_edges[currentEdge.m_name].m_concavity);
|
||||
v1 = m_graph.m_edges[currentEdge.m_name].m_v1;
|
||||
v2 = m_graph.m_edges[currentEdge.m_name].m_v2;
|
||||
// update vertex info
|
||||
m_graph.m_vertices[v1].m_error = m_graph.m_edges[currentEdge.m_name].m_error;
|
||||
m_graph.m_vertices[v1].m_surf = m_graph.m_edges[currentEdge.m_name].m_surf;
|
||||
m_graph.m_vertices[v1].m_volume = m_graph.m_edges[currentEdge.m_name].m_volume;
|
||||
m_graph.m_vertices[v1].m_concavity = m_graph.m_edges[currentEdge.m_name].m_concavity;
|
||||
m_graph.m_vertices[v1].m_perimeter = m_graph.m_edges[currentEdge.m_name].m_perimeter;
|
||||
m_graph.m_vertices[v1].m_distPoints = m_graph.m_edges[currentEdge.m_name].m_distPoints;
|
||||
(*m_graph.m_vertices[v1].m_convexHull) = (*m_graph.m_edges[currentEdge.m_name].m_convexHull);
|
||||
(m_graph.m_vertices[v1].m_convexHull)->SetDistPoints(&(m_graph.m_vertices[v1].m_distPoints));
|
||||
m_graph.m_vertices[v1].m_boudaryEdges = m_graph.m_edges[currentEdge.m_name].m_boudaryEdges;
|
||||
|
||||
// We apply the optimal ecol
|
||||
// std::cout << "v1 " << v1 << " v2 " << v2 << std::endl;
|
||||
m_graph.EdgeCollapse(v1, v2);
|
||||
// recompute the adjacent edges costs
|
||||
std::set<long>::const_iterator itE(m_graph.m_vertices[v1].m_edges.begin()),
|
||||
itEEnd(m_graph.m_vertices[v1].m_edges.end());
|
||||
for(; itE != itEEnd; ++itE)
|
||||
{
|
||||
size_t e = *itE;
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!m_pqueue.empty())
|
||||
{
|
||||
m_pqueue.pop();
|
||||
}
|
||||
|
||||
m_cVertices.clear();
|
||||
m_nClusters = m_graph.GetNVertices();
|
||||
m_cVertices.reserve(m_nClusters);
|
||||
for (size_t p=0, v = 0; v != m_graph.m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_graph.m_vertices[v].m_deleted)
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "\t CH \t %lu \t %lf \t %lf\n", static_cast<unsigned long>(p), m_graph.m_vertices[v].m_concavity, m_graph.m_vertices[v].m_error);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_nClusters);
|
||||
p++;
|
||||
}
|
||||
m_cVertices.push_back(static_cast<long>(v));
|
||||
}
|
||||
}
|
||||
if (m_callBack)
|
||||
{
|
||||
sprintf(msg, "# clusters = %lu \t C = %f\n", static_cast<unsigned long>(m_nClusters), globalConcavity);
|
||||
(*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool HACD::Compute(bool fullCH, bool exportDistPoints)
|
||||
{
|
||||
gCancelRequest = false;
|
||||
|
||||
if ( !m_points || !m_triangles || !m_nPoints || !m_nTriangles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size_t nV = m_nTriangles;
|
||||
if (m_callBack)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "+ Mesh" << std::endl;
|
||||
msg << "\t # vertices \t" << m_nPoints << std::endl;
|
||||
msg << "\t # triangles \t" << m_nTriangles << std::endl;
|
||||
msg << "+ Parameters" << std::endl;
|
||||
msg << "\t min # of clusters \t" << m_nMinClusters << std::endl;
|
||||
msg << "\t max concavity \t" << m_concavity << std::endl;
|
||||
msg << "\t compacity weigth \t" << m_alpha << std::endl;
|
||||
msg << "\t volume weigth \t" << m_beta << std::endl;
|
||||
msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl;
|
||||
msg << "\t scale \t" << m_scale << std::endl;
|
||||
msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl;
|
||||
msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
|
||||
msg << "\t add face distance points \t" << m_addFacesPoints << std::endl;
|
||||
msg << "\t produce full convex-hulls \t" << fullCH << std::endl;
|
||||
msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl;
|
||||
(*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV);
|
||||
}
|
||||
if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV);
|
||||
NormalizeData();
|
||||
if (m_callBack) (*m_callBack)("+ Creating Graph\n", 0.0, 0.0, nV);
|
||||
CreateGraph();
|
||||
// Compute the surfaces and perimeters of all the faces
|
||||
if (m_callBack) (*m_callBack)("+ Initializing Dual Graph\n", 0.0, 0.0, nV);
|
||||
if (gCancelRequest)
|
||||
return false;
|
||||
|
||||
InitializeDualGraph();
|
||||
if (m_callBack) (*m_callBack)("+ Initializing Priority Queue\n", 0.0, 0.0, nV);
|
||||
if (gCancelRequest)
|
||||
return false;
|
||||
|
||||
InitializePriorityQueue();
|
||||
// we simplify the graph
|
||||
if (m_callBack) (*m_callBack)("+ Simplification ...\n", 0.0, 0.0, m_nTriangles);
|
||||
Simplify();
|
||||
if (m_callBack) (*m_callBack)("+ Denormalizing Data\n", 0.0, 0.0, m_nClusters);
|
||||
DenormalizeData();
|
||||
if (m_callBack) (*m_callBack)("+ Computing final convex-hulls\n", 0.0, 0.0, m_nClusters);
|
||||
delete [] m_convexHulls;
|
||||
m_convexHulls = new ICHull[m_nClusters];
|
||||
delete [] m_partition;
|
||||
m_partition = new long [m_nTriangles];
|
||||
for (size_t p = 0; p != m_cVertices.size(); ++p)
|
||||
{
|
||||
size_t v = m_cVertices[p];
|
||||
m_partition[v] = static_cast<long>(p);
|
||||
for(size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++)
|
||||
{
|
||||
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast<long>(p);
|
||||
}
|
||||
// compute the convex-hull
|
||||
const std::map<long, DPoint> & pointsCH = m_graph.m_vertices[v].m_distPoints;
|
||||
std::map<long, DPoint>::const_iterator itCH(pointsCH.begin());
|
||||
std::map<long, DPoint>::const_iterator itCHEnd(pointsCH.end());
|
||||
for(; itCH != itCHEnd; ++itCH)
|
||||
{
|
||||
if (!(itCH->second).m_distOnly)
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
|
||||
}
|
||||
}
|
||||
m_convexHulls[p].SetDistPoints(&m_graph.m_vertices[v].m_distPoints);
|
||||
if (fullCH)
|
||||
{
|
||||
m_convexHulls[p].Process();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_convexHulls[p].Process(static_cast<unsigned long>(m_nVerticesPerCH));
|
||||
}
|
||||
if (exportDistPoints)
|
||||
{
|
||||
itCH = pointsCH.begin();
|
||||
for(; itCH != itCHEnd; ++itCH)
|
||||
{
|
||||
if ((itCH->second).m_distOnly)
|
||||
{
|
||||
if (itCH->first >= 0)
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_facePoints[-itCH->first-1], itCH->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t HACD::GetNTrianglesCH(size_t numCH) const
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_convexHulls[numCH].GetMesh().GetNTriangles();
|
||||
}
|
||||
size_t HACD::GetNPointsCH(size_t numCH) const
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_convexHulls[numCH].GetMesh().GetNVertices();
|
||||
}
|
||||
|
||||
bool HACD::GetCH(size_t numCH, Vec3<Real> * const points, Vec3<long> * const triangles)
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_convexHulls[numCH].GetMesh().GetIFS(points, triangles);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HACD::Save(const char * fileName, bool uniColor, long numCluster) const
|
||||
{
|
||||
std::ofstream fout(fileName);
|
||||
if (fout.is_open())
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "Saving %s\n", fileName);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
|
||||
}
|
||||
Material mat;
|
||||
if (numCluster < 0)
|
||||
{
|
||||
for (size_t p = 0; p != m_nClusters; ++p)
|
||||
{
|
||||
if (!uniColor)
|
||||
{
|
||||
mat.m_diffuseColor.X() = mat.m_diffuseColor.Y() = mat.m_diffuseColor.Z() = 0.0;
|
||||
while (mat.m_diffuseColor.X() == mat.m_diffuseColor.Y() ||
|
||||
mat.m_diffuseColor.Z() == mat.m_diffuseColor.Y() ||
|
||||
mat.m_diffuseColor.Z() == mat.m_diffuseColor.X() )
|
||||
{
|
||||
mat.m_diffuseColor.X() = (rand()%100) / 100.0;
|
||||
mat.m_diffuseColor.Y() = (rand()%100) / 100.0;
|
||||
mat.m_diffuseColor.Z() = (rand()%100) / 100.0;
|
||||
}
|
||||
}
|
||||
m_convexHulls[p].GetMesh().SaveVRML2(fout, mat);
|
||||
}
|
||||
}
|
||||
else if (numCluster < static_cast<long>(m_cVertices.size()))
|
||||
{
|
||||
m_convexHulls[numCluster].GetMesh().SaveVRML2(fout, mat);
|
||||
}
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "Error saving %s\n", fileName);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
282
Extras/HACD/hacdHACD.h
Normal file
282
Extras/HACD/hacdHACD.h
Normal file
@ -0,0 +1,282 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_HACD_H
|
||||
#define HACD_HACD_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdVector.h"
|
||||
#include "hacdGraph.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
const double sc_pi = 3.14159265;
|
||||
class HACD;
|
||||
|
||||
// just to be able to set the capcity of the container
|
||||
|
||||
template<class _Ty, class _Container = std::vector<_Ty>, class _Pr = std::less<typename _Container::value_type> >
|
||||
class reservable_priority_queue: public std::priority_queue<_Ty, _Container, _Pr>
|
||||
{
|
||||
typedef typename std::priority_queue<_Ty, _Container, _Pr>::size_type size_type;
|
||||
public:
|
||||
reservable_priority_queue(size_type capacity = 0) { reserve(capacity); };
|
||||
void reserve(size_type capacity) { this->c.reserve(capacity); }
|
||||
size_type capacity() const { return this->c.capacity(); }
|
||||
};
|
||||
|
||||
//! priority queque element
|
||||
class GraphEdgePriorityQueue
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
//! @param name edge's id
|
||||
//! @param priority edge's priority
|
||||
GraphEdgePriorityQueue(long name, Real priority)
|
||||
{
|
||||
m_name = name;
|
||||
m_priority = priority;
|
||||
}
|
||||
//! Destructor
|
||||
~GraphEdgePriorityQueue(void){}
|
||||
private:
|
||||
long m_name; //!< edge name
|
||||
Real m_priority; //!< priority
|
||||
//! Operator < for GraphEdgePQ
|
||||
friend bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs);
|
||||
//! Operator > for GraphEdgePQ
|
||||
friend bool operator>(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs);
|
||||
friend class HACD;
|
||||
};
|
||||
inline bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
|
||||
{
|
||||
return lhs.m_priority<rhs.m_priority;
|
||||
}
|
||||
inline bool operator>(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
|
||||
{
|
||||
return lhs.m_priority>rhs.m_priority;
|
||||
}
|
||||
typedef bool (*CallBackFunction)(const char *, double, double, size_t);
|
||||
|
||||
//! Provides an implementation of the Hierarchical Approximate Convex Decomposition (HACD) technique described in "A Simple and Efficient Approach for 3D Mesh Approximate Convex Decomposition" Game Programming Gems 8 - Chapter 2.8, p.202. A short version of the chapter was published in ICIP09 and is available at ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf
|
||||
class HACD
|
||||
{
|
||||
public:
|
||||
|
||||
//! Gives the triangles partitionas an array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle
|
||||
//! @return triangles partition
|
||||
const long * const GetPartition() const { return m_partition;}
|
||||
//! Sets the scale factor
|
||||
//! @param scale scale factor
|
||||
void SetScaleFactor(double scale) { m_scale = scale;}
|
||||
//! Gives the scale factor
|
||||
//! @return scale factor
|
||||
const double GetScaleFactor() const { return m_scale;}
|
||||
//! Sets the call-back function
|
||||
//! @param callBack pointer to the call-back function
|
||||
void SetCallBack(CallBackFunction callBack) { m_callBack = callBack;}
|
||||
//! Gives the call-back function
|
||||
//! @return pointer to the call-back function
|
||||
const CallBackFunction GetCallBack() const { return m_callBack;}
|
||||
|
||||
//! Specifies whether faces points should be added when computing the concavity
|
||||
//! @param addFacesPoints true = faces points should be added
|
||||
void SetAddFacesPoints(bool addFacesPoints) { m_addFacesPoints = addFacesPoints;}
|
||||
//! Specifies wheter faces points should be added when computing the concavity
|
||||
//! @return true = faces points should be added
|
||||
const bool GetAddFacesPoints() const { return m_addFacesPoints;}
|
||||
//! Specifies whether extra points should be added when computing the concavity
|
||||
//! @param addExteraDistPoints true = extra points should be added
|
||||
void SetAddExtraDistPoints(bool addExtraDistPoints) { m_addExtraDistPoints = addExtraDistPoints;}
|
||||
//! Specifies wheter extra points should be added when computing the concavity
|
||||
//! @return true = extra points should be added
|
||||
const bool GetAddExtraDistPoints() const { return m_addExtraDistPoints;}
|
||||
//! Specifies whether extra points should be added when computing the concavity
|
||||
//! @param addExteraDistPoints true = extra points should be added
|
||||
void SetAddNeighboursDistPoints(bool addNeighboursDistPoints) { m_addNeighboursDistPoints = addNeighboursDistPoints;}
|
||||
//! Specifies wheter extra points should be added when computing the concavity
|
||||
//! @return true = extra points should be added
|
||||
const bool GetAddNeighboursDistPoints() const { return m_addNeighboursDistPoints;}
|
||||
//! Sets the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations)
|
||||
//! @param points pointer to the input points
|
||||
void SetPoints(Vec3<Real> * points) { m_points = points;}
|
||||
//! Gives the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations)
|
||||
//! @return pointer to the input points
|
||||
const Vec3<Real> * GetPoints() const { return m_points;}
|
||||
//! Sets the triangles of the input mesh.
|
||||
//! @param triangles points pointer to the input points
|
||||
void SetTriangles(Vec3<long> * triangles) { m_triangles = triangles;}
|
||||
//! Gives the triangles in the input mesh
|
||||
//! @return pointer to the input triangles
|
||||
const Vec3<long> * GetTriangles() const { return m_triangles;}
|
||||
//! Sets the number of points in the input mesh.
|
||||
//! @param nPoints number of points the input mesh
|
||||
void SetNPoints(size_t nPoints) { m_nPoints = nPoints;}
|
||||
//! Gives the number of points in the input mesh.
|
||||
//! @return number of points the input mesh
|
||||
const size_t GetNPoints() const { return m_nPoints;}
|
||||
//! Sets the number of triangles in the input mesh.
|
||||
//! @param nTriangles number of triangles in the input mesh
|
||||
void SetNTriangles(size_t nTriangles) { m_nTriangles = nTriangles;}
|
||||
//! Gives the number of triangles in the input mesh.
|
||||
//! @return number of triangles the input mesh
|
||||
const size_t GetNTriangles() const { return m_nTriangles;}
|
||||
//! Sets the minimum number of clusters to be generated.
|
||||
//! @param nClusters minimum number of clusters
|
||||
void SetNClusters(size_t nClusters) { m_nMinClusters = nClusters;}
|
||||
//! Gives the number of generated clusters.
|
||||
//! @return number of generated clusters
|
||||
const size_t GetNClusters() const { return m_nClusters;}
|
||||
//! Sets the maximum allowed concavity.
|
||||
//! @param concavity maximum concavity
|
||||
void SetConcavity(double concavity) { m_concavity = concavity;}
|
||||
//! Gives the maximum allowed concavity.
|
||||
//! @return maximum concavity
|
||||
double GetConcavity() const { return m_concavity;}
|
||||
//! Sets the maximum allowed distance to get CCs connected.
|
||||
//! @param concavity maximum distance to get CCs connected
|
||||
void SetConnectDist(double ccConnectDist) { m_ccConnectDist = ccConnectDist;}
|
||||
//! Gives the maximum allowed distance to get CCs connected.
|
||||
//! @return maximum distance to get CCs connected
|
||||
double GetConnectDist() const { return m_ccConnectDist;}
|
||||
//! Sets the volume weight.
|
||||
//! @param beta volume weight
|
||||
void SetVolumeWeight(double beta) { m_beta = beta;}
|
||||
//! Gives the volume weight.
|
||||
//! @return volume weight
|
||||
double GetVolumeWeight() const { return m_beta;}
|
||||
//! Sets the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf).
|
||||
//! @param alpha compacity weight
|
||||
void SetCompacityWeight(double alpha) { m_alpha = alpha;}
|
||||
//! Gives the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf).
|
||||
//! @return compacity weight
|
||||
double GetCompacityWeight() const { return m_alpha;}
|
||||
//! Sets the maximum number of vertices for each generated convex-hull.
|
||||
//! @param nVerticesPerCH maximum # vertices per CH
|
||||
void SetNVerticesPerCH(size_t nVerticesPerCH) { m_nVerticesPerCH = nVerticesPerCH;}
|
||||
//! Gives the maximum number of vertices for each generated convex-hull.
|
||||
//! @return maximum # vertices per CH
|
||||
const size_t GetNVerticesPerCH() const { return m_nVerticesPerCH;}
|
||||
//! Gives the number of vertices for the cluster number numCH.
|
||||
//! @return number of vertices
|
||||
size_t GetNPointsCH(size_t numCH) const;
|
||||
//! Gives the number of triangles for the cluster number numCH.
|
||||
//! @param numCH cluster's number
|
||||
//! @return number of triangles
|
||||
size_t GetNTrianglesCH(size_t numCH) const;
|
||||
//! Gives the vertices and the triangles of the cluster number numCH.
|
||||
//! @param numCH cluster's number
|
||||
//! @param points pointer to the vector of points to be filled
|
||||
//! @param triangles pointer to the vector of triangles to be filled
|
||||
//! @return true if sucess
|
||||
bool GetCH(size_t numCH, Vec3<Real> * const points, Vec3<long> * const triangles);
|
||||
//! Computes the HACD decomposition.
|
||||
//! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices
|
||||
//! @param exportDistPoints specifies wheter distance points should ne exported or not (used only for debugging).
|
||||
//! @return true if sucess
|
||||
bool Compute(bool fullCH=false, bool exportDistPoints=false);
|
||||
//! Saves the generated convex-hulls in a VRML 2.0 file.
|
||||
//! @param fileName the output file name
|
||||
//! @param uniColor specifies whether the different convex-hulls should have the same color or not
|
||||
//! @param numCluster specifies the cluster to be saved, if numCluster < 0 export all clusters
|
||||
//! @return true if sucess
|
||||
bool Save(const char * fileName, bool uniColor, long numCluster=-1) const;
|
||||
//! Shifts and scales to the data to have all the coordinates between 0.0 and 1000.0.
|
||||
void NormalizeData();
|
||||
//! Inverse the operations applied by NormalizeData().
|
||||
void DenormalizeData();
|
||||
//! Constructor.
|
||||
HACD(void);
|
||||
//! Destructor.
|
||||
~HACD(void);
|
||||
|
||||
private:
|
||||
//! Gives the edge index.
|
||||
//! @param a first vertex id
|
||||
//! @param b second vertex id
|
||||
//! @return edge's index
|
||||
static unsigned long long GetEdgeIndex(unsigned long long a, unsigned long long b)
|
||||
{
|
||||
if (a > b) return (a << 32) + b;
|
||||
else return (b << 32) + a;
|
||||
}
|
||||
//! Computes the concavity of a cluster.
|
||||
//! @param ch the cluster's convex-hull
|
||||
//! @param distPoints the cluster's points
|
||||
//! @return cluster's concavity
|
||||
double Concavity(ICHull & ch, std::map<long, DPoint> & distPoints);
|
||||
//! Computes the perimeter of a cluster.
|
||||
//! @param triIndices the cluster's triangles
|
||||
//! @param distPoints the cluster's points
|
||||
//! @return cluster's perimeter
|
||||
double ComputePerimeter(const std::vector<long> & triIndices) const;
|
||||
//! Creates the Graph by associating to each mesh triangle a vertex in the graph and to each couple of adjacent triangles an edge in the graph.
|
||||
void CreateGraph();
|
||||
//! Initializes the graph costs and computes the vertices normals
|
||||
void InitializeDualGraph();
|
||||
//! Computes the cost of an edge
|
||||
//! @param e edge's id
|
||||
void ComputeEdgeCost(size_t e);
|
||||
//! Initializes the priority queue
|
||||
//! @param fast specifies whether fast mode is used
|
||||
//! @return true if success
|
||||
bool InitializePriorityQueue();
|
||||
//! Cleans the intersection between convex-hulls
|
||||
void CleanClusters();
|
||||
//! Computes convex-hulls from partition information
|
||||
//! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices
|
||||
void ComputeConvexHulls(bool fullCH);
|
||||
//! Simplifies the graph
|
||||
//! @param fast specifies whether fast mode is used
|
||||
void Simplify();
|
||||
|
||||
private:
|
||||
double m_scale; //>! scale factor used for NormalizeData() and DenormalizeData()
|
||||
Vec3<long> * m_triangles; //>! pointer the triangles array
|
||||
Vec3<Real> * m_points; //>! pointer the points array
|
||||
Vec3<Real> * m_facePoints; //>! pointer to the faces points array
|
||||
Vec3<Real> * m_faceNormals; //>! pointer to the faces normals array
|
||||
Vec3<Real> * m_normals; //>! pointer the normals array
|
||||
size_t m_nTriangles; //>! number of triangles in the original mesh
|
||||
size_t m_nPoints; //>! number of vertices in the original mesh
|
||||
size_t m_nClusters; //>! number of clusters
|
||||
size_t m_nMinClusters; //>! minimum number of clusters
|
||||
double m_ccConnectDist; //>! maximum allowed distance to connect CCs
|
||||
double m_concavity; //>! maximum concavity
|
||||
double m_alpha; //>! compacity weigth
|
||||
double m_beta; //>! volume weigth
|
||||
double m_diag; //>! length of the BB diagonal
|
||||
Vec3<Real> m_barycenter; //>! barycenter of the mesh
|
||||
std::vector< long > m_cVertices; //>! array of vertices each belonging to a different cluster
|
||||
ICHull * m_convexHulls; //>! convex-hulls associated with the final HACD clusters
|
||||
Graph m_graph; //>! simplification graph
|
||||
size_t m_nVerticesPerCH; //>! maximum number of vertices per convex-hull
|
||||
reservable_priority_queue<GraphEdgePriorityQueue,
|
||||
std::vector<GraphEdgePriorityQueue>,
|
||||
std::greater<std::vector<GraphEdgePriorityQueue>::value_type> > m_pqueue; //!> priority queue
|
||||
HACD(const HACD & rhs);
|
||||
CallBackFunction m_callBack; //>! call-back function
|
||||
long * m_partition; //>! array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle
|
||||
bool m_addFacesPoints; //>! specifies whether to add faces points or not
|
||||
bool m_addExtraDistPoints; //>! specifies whether to add extra points for concave shapes or not
|
||||
bool m_addNeighboursDistPoints; //>! specifies whether to add extra points from adjacent clusters or not
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
1010
Extras/HACD/hacdICHull.cpp
Normal file
1010
Extras/HACD/hacdICHull.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
Extras/HACD/hacdICHull.h
Normal file
120
Extras/HACD/hacdICHull.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_ICHULL_H
|
||||
#define HACD_ICHULL_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdManifoldMesh.h"
|
||||
#include "hacdVector.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace HACD
|
||||
{
|
||||
class DPoint;
|
||||
class HACD;
|
||||
//! Incremental Convex Hull algorithm (cf. http://maven.smith.edu/~orourke/books/ftp.html ).
|
||||
enum ICHullError
|
||||
{
|
||||
ICHullErrorOK = 0,
|
||||
ICHullErrorCoplanarPoints,
|
||||
ICHullErrorNoVolume,
|
||||
ICHullErrorInconsistent,
|
||||
ICHullErrorNotEnoughPoints
|
||||
};
|
||||
class ICHull
|
||||
{
|
||||
public:
|
||||
//!
|
||||
bool IsFlat() { return m_isFlat;}
|
||||
//!
|
||||
std::map<long, DPoint> * GetDistPoints() const { return m_distPoints;}
|
||||
//!
|
||||
void SetDistPoints(std::map<long, DPoint> * distPoints) { m_distPoints = distPoints;}
|
||||
//! Returns the computed mesh
|
||||
TMMesh & GetMesh() { return m_mesh;}
|
||||
//! Add one point to the convex-hull
|
||||
bool AddPoint(const Vec3<Real> & point) {return AddPoints(&point, 1);}
|
||||
//! Add one point to the convex-hull
|
||||
bool AddPoint(const Vec3<Real> & point, long id);
|
||||
//! Add points to the convex-hull
|
||||
bool AddPoints(const Vec3<Real> * points, size_t nPoints);
|
||||
bool AddPoints(std::vector< Vec3<Real> > points);
|
||||
//!
|
||||
ICHullError Process();
|
||||
//!
|
||||
ICHullError Process(unsigned long nPointsCH);
|
||||
//!
|
||||
double ComputeVolume();
|
||||
//!
|
||||
bool IsInside(const Vec3<Real> & pt0);
|
||||
//!
|
||||
double ComputeDistance(long name, const Vec3<Real> & pt, const Vec3<Real> & normal, bool & insideHull, bool updateIncidentPoints);
|
||||
//!
|
||||
const ICHull & operator=(ICHull & rhs);
|
||||
|
||||
//! Constructor
|
||||
ICHull(void);
|
||||
//! Destructor
|
||||
virtual ~ICHull(void) {};
|
||||
|
||||
private:
|
||||
//! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up.
|
||||
ICHullError DoubleTriangle();
|
||||
//! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face.
|
||||
CircularListElement<TMMTriangle> * MakeFace(CircularListElement<TMMVertex> * v0,
|
||||
CircularListElement<TMMVertex> * v1,
|
||||
CircularListElement<TMMVertex> * v2,
|
||||
CircularListElement<TMMTriangle> * fold);
|
||||
//!
|
||||
CircularListElement<TMMTriangle> * MakeConeFace(CircularListElement<TMMEdge> * e, CircularListElement<TMMVertex> * v);
|
||||
//!
|
||||
bool ProcessPoint();
|
||||
//!
|
||||
bool ComputePointVolume(double &totalVolume, bool markVisibleFaces);
|
||||
//!
|
||||
bool FindMaxVolumePoint();
|
||||
//!
|
||||
bool CleanEdges();
|
||||
//!
|
||||
bool CleanVertices(unsigned long & addedPoints);
|
||||
//!
|
||||
bool CleanTriangles();
|
||||
//!
|
||||
bool CleanUp(unsigned long & addedPoints);
|
||||
//!
|
||||
bool MakeCCW(CircularListElement<TMMTriangle> * f,
|
||||
CircularListElement<TMMEdge> * e,
|
||||
CircularListElement<TMMVertex> * v);
|
||||
void Clear();
|
||||
private:
|
||||
static const long sc_dummyIndex;
|
||||
static const double sc_distMin;
|
||||
TMMesh m_mesh;
|
||||
std::vector<CircularListElement<TMMEdge> *> m_edgesToDelete;
|
||||
std::vector<CircularListElement<TMMEdge> *> m_edgesToUpdate;
|
||||
std::vector<CircularListElement<TMMTriangle> *> m_trianglesToDelete;
|
||||
std::map<long, DPoint> * m_distPoints;
|
||||
CircularListElement<TMMVertex> * m_dummyVertex;
|
||||
Vec3<Real> m_normal;
|
||||
bool m_isFlat;
|
||||
|
||||
|
||||
ICHull(const ICHull & rhs);
|
||||
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
577
Extras/HACD/hacdManifoldMesh.cpp
Normal file
577
Extras/HACD/hacdManifoldMesh.cpp
Normal file
@ -0,0 +1,577 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "hacdManifoldMesh.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
Material::Material(void)
|
||||
{
|
||||
m_diffuseColor.X() = 0.5;
|
||||
m_diffuseColor.Y() = 0.5;
|
||||
m_diffuseColor.Z() = 0.5;
|
||||
m_specularColor.X() = 0.5;
|
||||
m_specularColor.Y() = 0.5;
|
||||
m_specularColor.Z() = 0.5;
|
||||
m_ambientIntensity = 0.4;
|
||||
m_emissiveColor.X() = 0.0;
|
||||
m_emissiveColor.Y() = 0.0;
|
||||
m_emissiveColor.Z() = 0.0;
|
||||
m_shininess = 0.4;
|
||||
m_transparency = 0.0;
|
||||
}
|
||||
|
||||
TMMVertex::TMMVertex(void)
|
||||
{
|
||||
m_name = 0;
|
||||
m_id = 0;
|
||||
m_duplicate = 0;
|
||||
m_onHull = false;
|
||||
m_tag = false;
|
||||
}
|
||||
TMMVertex::~TMMVertex(void)
|
||||
{
|
||||
}
|
||||
TMMEdge::TMMEdge(void)
|
||||
{
|
||||
m_id = 0;
|
||||
m_triangles[0] = m_triangles[1] = m_newFace = 0;
|
||||
m_vertices[0] = m_vertices[1] = 0;
|
||||
}
|
||||
TMMEdge::~TMMEdge(void)
|
||||
{
|
||||
}
|
||||
TMMTriangle::TMMTriangle(void)
|
||||
{
|
||||
m_id = 0;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
m_edges[i] = 0;
|
||||
m_vertices[0] = 0;
|
||||
}
|
||||
m_visible = false;
|
||||
}
|
||||
TMMTriangle::~TMMTriangle(void)
|
||||
{
|
||||
}
|
||||
TMMesh::TMMesh(void)
|
||||
{
|
||||
m_barycenter = Vec3<Real>(0,0,0);
|
||||
m_diag = 1;
|
||||
}
|
||||
TMMesh::~TMMesh(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TMMesh::Print()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
std::cout << "-----------------------------" << std::endl;
|
||||
std::cout << "vertices (" << nV << ")" << std::endl;
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
const TMMVertex & currentVertex = m_vertices.GetData();
|
||||
std::cout << currentVertex.m_id << ", "
|
||||
<< currentVertex.m_pos.X() << ", "
|
||||
<< currentVertex.m_pos.Y() << ", "
|
||||
<< currentVertex.m_pos.Z() << std::endl;
|
||||
m_vertices.Next();
|
||||
}
|
||||
|
||||
|
||||
size_t nE = m_edges.GetSize();
|
||||
std::cout << "edges (" << nE << ")" << std::endl;
|
||||
for(size_t e = 0; e < nE; e++)
|
||||
{
|
||||
const TMMEdge & currentEdge = m_edges.GetData();
|
||||
const CircularListElement<TMMVertex> * v0 = currentEdge.m_vertices[0];
|
||||
const CircularListElement<TMMVertex> * v1 = currentEdge.m_vertices[1];
|
||||
const CircularListElement<TMMTriangle> * f0 = currentEdge.m_triangles[0];
|
||||
const CircularListElement<TMMTriangle> * f1 = currentEdge.m_triangles[1];
|
||||
|
||||
std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> F0 (" << f0->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< f0->GetData().m_vertices[1]->GetData().m_name << ", "
|
||||
<< f0->GetData().m_vertices[2]->GetData().m_name <<")" << std::endl;
|
||||
std::cout << "-> F1 (" << f1->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< f1->GetData().m_vertices[1]->GetData().m_name << ", "
|
||||
<< f1->GetData().m_vertices[2]->GetData().m_name << ")" << std::endl;
|
||||
m_edges.Next();
|
||||
}
|
||||
size_t nT = m_triangles.GetSize();
|
||||
std::cout << "triangles (" << nT << ")" << std::endl;
|
||||
for(size_t t = 0; t < nT; t++)
|
||||
{
|
||||
const TMMTriangle & currentTriangle = m_triangles.GetData();
|
||||
const CircularListElement<TMMVertex> * v0 = currentTriangle.m_vertices[0];
|
||||
const CircularListElement<TMMVertex> * v1 = currentTriangle.m_vertices[1];
|
||||
const CircularListElement<TMMVertex> * v2 = currentTriangle.m_vertices[2];
|
||||
const CircularListElement<TMMEdge> * e0 = currentTriangle.m_edges[0];
|
||||
const CircularListElement<TMMEdge> * e1 = currentTriangle.m_edges[1];
|
||||
const CircularListElement<TMMEdge> * e2 = currentTriangle.m_edges[2];
|
||||
|
||||
std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ", "<< v2->GetData().m_name << ")" << std::endl;
|
||||
|
||||
std::cout << "-> E0 (" << e0->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e0->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> E1 (" << e1->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e1->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> E2 (" << e2->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e2->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
m_triangles.Next();
|
||||
}
|
||||
}
|
||||
bool TMMesh::Save(const char *fileName)
|
||||
{
|
||||
std::ofstream fout(fileName);
|
||||
std::cout << "Saving " << fileName << std::endl;
|
||||
if (SaveVRML2(fout))
|
||||
{
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool TMMesh::SaveVRML2(std::ofstream &fout)
|
||||
{
|
||||
return SaveVRML2(fout, Material());
|
||||
}
|
||||
bool TMMesh::SaveVRML2(std::ofstream &fout, const Material & material)
|
||||
{
|
||||
if (fout.is_open())
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
fout <<"#VRML V2.0 utf8" << std::endl;
|
||||
fout <<"" << std::endl;
|
||||
fout <<"# Vertices: " << nV << std::endl;
|
||||
fout <<"# Triangles: " << nT << std::endl;
|
||||
fout <<"" << std::endl;
|
||||
fout <<"Group {" << std::endl;
|
||||
fout <<" children [" << std::endl;
|
||||
fout <<" Shape {" << std::endl;
|
||||
fout <<" appearance Appearance {" << std::endl;
|
||||
fout <<" material Material {" << std::endl;
|
||||
fout <<" diffuseColor " << material.m_diffuseColor.X() << " "
|
||||
<< material.m_diffuseColor.Y() << " "
|
||||
<< material.m_diffuseColor.Z() << std::endl;
|
||||
fout <<" ambientIntensity " << material.m_ambientIntensity << std::endl;
|
||||
fout <<" specularColor " << material.m_specularColor.X() << " "
|
||||
<< material.m_specularColor.Y() << " "
|
||||
<< material.m_specularColor.Z() << std::endl;
|
||||
fout <<" emissiveColor " << material.m_emissiveColor.X() << " "
|
||||
<< material.m_emissiveColor.Y() << " "
|
||||
<< material.m_emissiveColor.Z() << std::endl;
|
||||
fout <<" shininess " << material.m_shininess << std::endl;
|
||||
fout <<" transparency " << material.m_transparency << std::endl;
|
||||
fout <<" }" << std::endl;
|
||||
fout <<" }" << std::endl;
|
||||
fout <<" geometry IndexedFaceSet {" << std::endl;
|
||||
fout <<" ccw TRUE" << std::endl;
|
||||
fout <<" solid TRUE" << std::endl;
|
||||
fout <<" convex TRUE" << std::endl;
|
||||
if (GetNVertices() > 0) {
|
||||
fout <<" coord DEF co Coordinate {" << std::endl;
|
||||
fout <<" point [" << std::endl;
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
TMMVertex & currentVertex = m_vertices.GetData();
|
||||
fout <<" " << currentVertex.m_pos.X() << " "
|
||||
<< currentVertex.m_pos.Y() << " "
|
||||
<< currentVertex.m_pos.Z() << "," << std::endl;
|
||||
currentVertex.m_id = v;
|
||||
m_vertices.Next();
|
||||
}
|
||||
fout <<" ]" << std::endl;
|
||||
fout <<" }" << std::endl;
|
||||
}
|
||||
if (GetNTriangles() > 0) {
|
||||
fout <<" coordIndex [ " << std::endl;
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
TMMTriangle & currentTriangle = m_triangles.GetData();
|
||||
fout <<" " << currentTriangle.m_vertices[0]->GetData().m_id << ", "
|
||||
<< currentTriangle.m_vertices[1]->GetData().m_id << ", "
|
||||
<< currentTriangle.m_vertices[2]->GetData().m_id << ", -1," << std::endl;
|
||||
m_triangles.Next();
|
||||
}
|
||||
fout <<" ]" << std::endl;
|
||||
}
|
||||
fout <<" }" << std::endl;
|
||||
fout <<" }" << std::endl;
|
||||
fout <<" ]" << std::endl;
|
||||
fout <<"}" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void TMMesh::GetIFS(Vec3<Real> * const points, Vec3<long> * const triangles)
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
points[v] = m_vertices.GetData().m_pos;
|
||||
m_vertices.GetData().m_id = v;
|
||||
m_vertices.Next();
|
||||
}
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
TMMTriangle & currentTriangle = m_triangles.GetData();
|
||||
triangles[f].X() = static_cast<long>(currentTriangle.m_vertices[0]->GetData().m_id);
|
||||
triangles[f].Y() = static_cast<long>(currentTriangle.m_vertices[1]->GetData().m_id);
|
||||
triangles[f].Z() = static_cast<long>(currentTriangle.m_vertices[2]->GetData().m_id);
|
||||
m_triangles.Next();
|
||||
}
|
||||
}
|
||||
void TMMesh::Clear()
|
||||
{
|
||||
m_vertices.Clear();
|
||||
m_edges.Clear();
|
||||
m_triangles.Clear();
|
||||
}
|
||||
void TMMesh::Copy(TMMesh & mesh)
|
||||
{
|
||||
Clear();
|
||||
// updating the id's
|
||||
size_t nV = mesh.m_vertices.GetSize();
|
||||
size_t nE = mesh. m_edges.GetSize();
|
||||
size_t nT = mesh.m_triangles.GetSize();
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
mesh.m_vertices.GetData().m_id = v;
|
||||
mesh.m_vertices.Next();
|
||||
}
|
||||
for(size_t e = 0; e < nE; e++)
|
||||
{
|
||||
mesh.m_edges.GetData().m_id = e;
|
||||
mesh.m_edges.Next();
|
||||
|
||||
}
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
mesh.m_triangles.GetData().m_id = f;
|
||||
mesh.m_triangles.Next();
|
||||
}
|
||||
// copying data
|
||||
m_vertices = mesh.m_vertices;
|
||||
m_edges = mesh.m_edges;
|
||||
m_triangles = mesh.m_triangles;
|
||||
|
||||
// generating mapping
|
||||
CircularListElement<TMMVertex> ** vertexMap = new CircularListElement<TMMVertex> * [nV];
|
||||
CircularListElement<TMMEdge> ** edgeMap = new CircularListElement<TMMEdge> * [nE];
|
||||
CircularListElement<TMMTriangle> ** triangleMap = new CircularListElement<TMMTriangle> * [nT];
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
vertexMap[v] = m_vertices.GetHead();
|
||||
m_vertices.Next();
|
||||
}
|
||||
for(size_t e = 0; e < nE; e++)
|
||||
{
|
||||
edgeMap[e] = m_edges.GetHead();
|
||||
m_edges.Next();
|
||||
}
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
triangleMap[f] = m_triangles.GetHead();
|
||||
m_triangles.Next();
|
||||
}
|
||||
|
||||
// updating pointers
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
if (vertexMap[v]->GetData().m_duplicate)
|
||||
{
|
||||
vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
|
||||
}
|
||||
}
|
||||
for(size_t e = 0; e < nE; e++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_newFace)
|
||||
{
|
||||
edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
|
||||
}
|
||||
if (nT > 0)
|
||||
{
|
||||
for(int f = 0; f < 2; f++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_triangles[f])
|
||||
{
|
||||
edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int v = 0; v < 2; v++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_vertices[v])
|
||||
{
|
||||
edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
if (nE > 0)
|
||||
{
|
||||
for(int e = 0; e < 3; e++)
|
||||
{
|
||||
if (triangleMap[f]->GetData().m_edges[e])
|
||||
{
|
||||
triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int v = 0; v < 3; v++)
|
||||
{
|
||||
if (triangleMap[f]->GetData().m_vertices[v])
|
||||
{
|
||||
triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
delete [] vertexMap;
|
||||
delete [] edgeMap;
|
||||
delete [] triangleMap;
|
||||
|
||||
}
|
||||
long IntersectRayTriangle(const Vec3<double> & P0, const Vec3<double> & dir,
|
||||
const Vec3<double> & V0, const Vec3<double> & V1,
|
||||
const Vec3<double> & V2, double &t)
|
||||
{
|
||||
Vec3<double> edge1, edge2, edge3;
|
||||
double det, invDet;
|
||||
edge1 = V1 - V2;
|
||||
edge2 = V2 - V0;
|
||||
Vec3<double> pvec = dir ^ edge2;
|
||||
det = edge1 * pvec;
|
||||
if (det == 0.0)
|
||||
return 0;
|
||||
invDet = 1.0/det;
|
||||
Vec3<double> tvec = P0 - V0;
|
||||
Vec3<double> qvec = tvec ^ edge1;
|
||||
t = (edge2 * qvec) * invDet;
|
||||
if (t < 0.0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
edge3 = V0 - V1;
|
||||
Vec3<double> I(P0 + t * dir);
|
||||
Vec3<double> s0 = (I-V0) ^ edge3;
|
||||
Vec3<double> s1 = (I-V1) ^ edge1;
|
||||
Vec3<double> s2 = (I-V2) ^ edge2;
|
||||
if (s0*s1 > -1e-9 && s2*s1 > -1e-9)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IntersectLineLine(const Vec3<double> & p1, const Vec3<double> & p2,
|
||||
const Vec3<double> & p3, const Vec3<double> & p4,
|
||||
Vec3<double> & pa, Vec3<double> & pb,
|
||||
double & mua, double & mub)
|
||||
{
|
||||
Vec3<double> p13,p43,p21;
|
||||
double d1343,d4321,d1321,d4343,d2121;
|
||||
double numer,denom;
|
||||
|
||||
p13.X() = p1.X() - p3.X();
|
||||
p13.Y() = p1.Y() - p3.Y();
|
||||
p13.Z() = p1.Z() - p3.Z();
|
||||
p43.X() = p4.X() - p3.X();
|
||||
p43.Y() = p4.Y() - p3.Y();
|
||||
p43.Z() = p4.Z() - p3.Z();
|
||||
if (p43.X()==0.0 && p43.Y()==0.0 && p43.Z()==0.0)
|
||||
return false;
|
||||
p21.X() = p2.X() - p1.X();
|
||||
p21.Y() = p2.Y() - p1.Y();
|
||||
p21.Z() = p2.Z() - p1.Z();
|
||||
if (p21.X()==0.0 && p21.Y()==0.0 && p21.Z()==0.0)
|
||||
return false;
|
||||
|
||||
d1343 = p13.X() * p43.X() + p13.Y() * p43.Y() + p13.Z() * p43.Z();
|
||||
d4321 = p43.X() * p21.X() + p43.Y() * p21.Y() + p43.Z() * p21.Z();
|
||||
d1321 = p13.X() * p21.X() + p13.Y() * p21.Y() + p13.Z() * p21.Z();
|
||||
d4343 = p43.X() * p43.X() + p43.Y() * p43.Y() + p43.Z() * p43.Z();
|
||||
d2121 = p21.X() * p21.X() + p21.Y() * p21.Y() + p21.Z() * p21.Z();
|
||||
|
||||
denom = d2121 * d4343 - d4321 * d4321;
|
||||
if (denom==0.0)
|
||||
return false;
|
||||
numer = d1343 * d4321 - d1321 * d4343;
|
||||
|
||||
mua = numer / denom;
|
||||
mub = (d1343 + d4321 * (mua)) / d4343;
|
||||
|
||||
pa.X() = p1.X() + mua * p21.X();
|
||||
pa.Y() = p1.Y() + mua * p21.Y();
|
||||
pa.Z() = p1.Z() + mua * p21.Z();
|
||||
pb.X() = p3.X() + mub * p43.X();
|
||||
pb.Y() = p3.Y() + mub * p43.Y();
|
||||
pb.Z() = p3.Z() + mub * p43.Z();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long IntersectRayTriangle2(const Vec3<double> & P0, const Vec3<double> & dir,
|
||||
const Vec3<double> & V0, const Vec3<double> & V1,
|
||||
const Vec3<double> & V2, double &r)
|
||||
{
|
||||
Vec3<double> u, v, n; // triangle vectors
|
||||
Vec3<double> w0, w; // ray vectors
|
||||
double a, b; // params to calc ray-plane intersect
|
||||
|
||||
// get triangle edge vectors and plane normal
|
||||
u = V1 - V0;
|
||||
v = V2 - V0;
|
||||
n = u ^ v; // cross product
|
||||
if (n.GetNorm() == 0.0) // triangle is degenerate
|
||||
return -1; // do not deal with this case
|
||||
|
||||
w0 = P0 - V0;
|
||||
a = - n * w0;
|
||||
b = n * dir;
|
||||
if (fabs(b) <= 0.0) { // ray is parallel to triangle plane
|
||||
if (a == 0.0) // ray lies in triangle plane
|
||||
return 2;
|
||||
else return 0; // ray disjoint from plane
|
||||
}
|
||||
|
||||
// get intersect point of ray with triangle plane
|
||||
r = a / b;
|
||||
if (r < 0.0) // ray goes away from triangle
|
||||
return 0; // => no intersect
|
||||
// for a segment, also test if (r > 1.0) => no intersect
|
||||
|
||||
Vec3<double> I = P0 + r * dir; // intersect point of ray and plane
|
||||
|
||||
// is I inside T?
|
||||
double uu, uv, vv, wu, wv, D;
|
||||
uu = u * u;
|
||||
uv = u * v;
|
||||
vv = v * v;
|
||||
w = I - V0;
|
||||
wu = w * u;
|
||||
wv = w * v;
|
||||
D = uv * uv - uu * vv;
|
||||
|
||||
// get and test parametric coords
|
||||
double s, t;
|
||||
s = (uv * wv - vv * wu) / D;
|
||||
if (s < 0.0 || s > 1.0) // I is outside T
|
||||
return 0;
|
||||
t = (uv * wu - uu * wv) / D;
|
||||
if (t < 0.0 || (s + t) > 1.0) // I is outside T
|
||||
return 0;
|
||||
return 1; // I is in T
|
||||
}
|
||||
|
||||
|
||||
bool TMMesh::CheckConsistancy()
|
||||
{
|
||||
size_t nE = m_edges.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
for(size_t e = 0; e < nE; e++)
|
||||
{
|
||||
for(int f = 0; f < 2; f++)
|
||||
{
|
||||
if (!m_edges.GetHead()->GetData().m_triangles[f])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_edges.Next();
|
||||
}
|
||||
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
for(int e = 0; e < 3; e++)
|
||||
{
|
||||
int found = 0;
|
||||
for(int k = 0; k < 2; k++)
|
||||
{
|
||||
if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead())
|
||||
{
|
||||
found++;
|
||||
}
|
||||
}
|
||||
if (found != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_triangles.Next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool TMMesh::Normalize()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
if (nV == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_barycenter = m_vertices.GetHead()->GetData().m_pos;
|
||||
Vec3<Real> min = m_barycenter;
|
||||
Vec3<Real> max = m_barycenter;
|
||||
Real x, y, z;
|
||||
for(size_t v = 1; v < nV; v++)
|
||||
{
|
||||
m_barycenter += m_vertices.GetHead()->GetData().m_pos;
|
||||
x = m_vertices.GetHead()->GetData().m_pos.X();
|
||||
y = m_vertices.GetHead()->GetData().m_pos.Y();
|
||||
z = m_vertices.GetHead()->GetData().m_pos.Z();
|
||||
if ( x < min.X()) min.X() = x;
|
||||
else if ( x > max.X()) max.X() = x;
|
||||
if ( y < min.Y()) min.Y() = y;
|
||||
else if ( y > max.Y()) max.Y() = y;
|
||||
if ( z < min.Z()) min.Z() = z;
|
||||
else if ( z > max.Z()) max.Z() = z;
|
||||
m_vertices.Next();
|
||||
}
|
||||
m_barycenter /= static_cast<Real>(nV);
|
||||
m_diag = static_cast<Real>(0.001 * (max-min).GetNorm());
|
||||
const Real invDiag = static_cast<Real>(1.0 / m_diag);
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
m_vertices.GetHead()->GetData().m_pos = (m_vertices.GetHead()->GetData().m_pos - m_barycenter) * invDiag;
|
||||
m_vertices.Next();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool TMMesh::Denormalize()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
if (nV == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for(size_t v = 0; v < nV; v++)
|
||||
{
|
||||
m_vertices.GetHead()->GetData().m_pos = m_vertices.GetHead()->GetData().m_pos * m_diag + m_barycenter;
|
||||
m_vertices.Next();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
250
Extras/HACD/hacdManifoldMesh.h
Normal file
250
Extras/HACD/hacdManifoldMesh.h
Normal file
@ -0,0 +1,250 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_MANIFOLD_MESH_H
|
||||
#define HACD_MANIFOLD_MESH_H
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdCircularList.h"
|
||||
#include "hacdVector.h"
|
||||
#include <set>
|
||||
namespace HACD
|
||||
{
|
||||
class TMMTriangle;
|
||||
class TMMEdge;
|
||||
class TMMesh;
|
||||
class ICHull;
|
||||
class HACD;
|
||||
|
||||
class DPoint
|
||||
{
|
||||
public:
|
||||
DPoint(Real dist=0, bool computed=false, bool distOnly=false)
|
||||
:m_dist(dist),
|
||||
m_computed(computed),
|
||||
m_distOnly(distOnly){};
|
||||
~DPoint(){};
|
||||
private:
|
||||
Real m_dist;
|
||||
bool m_computed;
|
||||
bool m_distOnly;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMesh;
|
||||
friend class GraphVertex;
|
||||
friend class GraphEdge;
|
||||
friend class Graph;
|
||||
friend class ICHull;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
//! Vertex data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMVertex
|
||||
{
|
||||
public:
|
||||
TMMVertex(void);
|
||||
~TMMVertex(void);
|
||||
|
||||
private:
|
||||
Vec3<Real> m_pos;
|
||||
long m_name;
|
||||
size_t m_id;
|
||||
CircularListElement<TMMEdge> * m_duplicate; // pointer to incident cone edge (or NULL)
|
||||
bool m_onHull;
|
||||
bool m_tag;
|
||||
TMMVertex(const TMMVertex & rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMesh;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMEdge;
|
||||
};
|
||||
|
||||
//! Edge data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMEdge
|
||||
{
|
||||
public:
|
||||
TMMEdge(void);
|
||||
~TMMEdge(void);
|
||||
private:
|
||||
size_t m_id;
|
||||
CircularListElement<TMMTriangle> * m_triangles[2];
|
||||
CircularListElement<TMMVertex> * m_vertices[2];
|
||||
CircularListElement<TMMTriangle> * m_newFace;
|
||||
|
||||
|
||||
TMMEdge(const TMMEdge & rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMVertex;
|
||||
friend class TMMesh;
|
||||
};
|
||||
|
||||
//! Triangle data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMTriangle
|
||||
{
|
||||
public:
|
||||
TMMTriangle(void);
|
||||
~TMMTriangle(void);
|
||||
private:
|
||||
size_t m_id;
|
||||
CircularListElement<TMMEdge> * m_edges[3];
|
||||
CircularListElement<TMMVertex> * m_vertices[3];
|
||||
std::set<long> m_incidentPoints;
|
||||
bool m_visible;
|
||||
|
||||
TMMTriangle(const TMMTriangle & rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMesh;
|
||||
friend class TMMVertex;
|
||||
friend class TMMEdge;
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material(void);
|
||||
~Material(void){}
|
||||
// private:
|
||||
Vec3<double> m_diffuseColor;
|
||||
double m_ambientIntensity;
|
||||
Vec3<double> m_specularColor;
|
||||
Vec3<double> m_emissiveColor;
|
||||
double m_shininess;
|
||||
double m_transparency;
|
||||
|
||||
friend class TMMesh;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
//! triangular manifold mesh data structure.
|
||||
class TMMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! Returns the number of vertices>
|
||||
inline size_t GetNVertices() const { return m_vertices.GetSize();}
|
||||
//! Returns the number of edges
|
||||
inline size_t GetNEdges() const { return m_edges.GetSize();}
|
||||
//! Returns the number of triangles
|
||||
inline size_t GetNTriangles() const { return m_triangles.GetSize();}
|
||||
//! Returns the vertices circular list
|
||||
inline const CircularList<TMMVertex> & GetVertices() const { return m_vertices;}
|
||||
//! Returns the edges circular list
|
||||
inline const CircularList<TMMEdge> & GetEdges() const { return m_edges;}
|
||||
//! Returns the triangles circular list
|
||||
inline const CircularList<TMMTriangle> & GetTriangles() const { return m_triangles;}
|
||||
//! Returns the vertices circular list
|
||||
inline CircularList<TMMVertex> & GetVertices() { return m_vertices;}
|
||||
//! Returns the edges circular list
|
||||
inline CircularList<TMMEdge> & GetEdges() { return m_edges;}
|
||||
//! Returns the triangles circular list
|
||||
inline CircularList<TMMTriangle> & GetTriangles() { return m_triangles;}
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMVertex> * AddVertex() {return m_vertices.Add();}
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMEdge> * AddEdge() {return m_edges.Add();}
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMTriangle> * AddTriangle() {return m_triangles.Add();}
|
||||
//! Print mesh information
|
||||
void Print();
|
||||
//!
|
||||
void GetIFS(Vec3<Real> * const points, Vec3<long> * const triangles);
|
||||
//! Save mesh
|
||||
bool Save(const char *fileName);
|
||||
//! Save mesh to VRML 2.0 format
|
||||
bool SaveVRML2(std::ofstream &fout);
|
||||
//! Save mesh to VRML 2.0 format
|
||||
bool SaveVRML2(std::ofstream &fout, const Material & material);
|
||||
//!
|
||||
void Clear();
|
||||
//!
|
||||
void Copy(TMMesh & mesh);
|
||||
//!
|
||||
bool CheckConsistancy();
|
||||
//!
|
||||
bool Normalize();
|
||||
//!
|
||||
bool Denormalize();
|
||||
//! Constructor
|
||||
TMMesh(void);
|
||||
//! Destructor
|
||||
virtual ~TMMesh(void);
|
||||
|
||||
private:
|
||||
CircularList<TMMVertex> m_vertices;
|
||||
CircularList<TMMEdge> m_edges;
|
||||
CircularList<TMMTriangle> m_triangles;
|
||||
Real m_diag; //>! length of the BB diagonal
|
||||
Vec3<Real> m_barycenter; //>! barycenter of the mesh
|
||||
|
||||
// not defined
|
||||
TMMesh(const TMMesh & rhs);
|
||||
friend class ICHull;
|
||||
friend class HACD;
|
||||
};
|
||||
//! IntersectRayTriangle(): intersect a ray with a 3D triangle
|
||||
//! Input: a ray R, and a triangle T
|
||||
//! Output: *I = intersection point (when it exists)
|
||||
//! 0 = disjoint (no intersect)
|
||||
//! 1 = intersect in unique point I1
|
||||
long IntersectRayTriangle( const Vec3<double> & P0, const Vec3<double> & dir,
|
||||
const Vec3<double> & V0, const Vec3<double> & V1,
|
||||
const Vec3<double> & V2, double &t);
|
||||
|
||||
// intersect_RayTriangle(): intersect a ray with a 3D triangle
|
||||
// Input: a ray R, and a triangle T
|
||||
// Output: *I = intersection point (when it exists)
|
||||
// Return: -1 = triangle is degenerate (a segment or point)
|
||||
// 0 = disjoint (no intersect)
|
||||
// 1 = intersect in unique point I1
|
||||
// 2 = are in the same plane
|
||||
long IntersectRayTriangle2(const Vec3<double> & P0, const Vec3<double> & dir,
|
||||
const Vec3<double> & V0, const Vec3<double> & V1,
|
||||
const Vec3<double> & V2, double &r);
|
||||
|
||||
/*
|
||||
Calculate the line segment PaPb that is the shortest route between
|
||||
two lines P1P2 and P3P4. Calculate also the values of mua and mub where
|
||||
Pa = P1 + mua (P2 - P1)
|
||||
Pb = P3 + mub (P4 - P3)
|
||||
Return FALSE if no solution exists.
|
||||
*/
|
||||
bool IntersectLineLine(const Vec3<double> & p1, const Vec3<double> & p2,
|
||||
const Vec3<double> & p3, const Vec3<double> & p4,
|
||||
Vec3<double> & pa, Vec3<double> & pb,
|
||||
double & mua, double &mub);
|
||||
}
|
||||
#endif
|
67
Extras/HACD/hacdVector.h
Normal file
67
Extras/HACD/hacdVector.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_VECTOR_H
|
||||
#define HACD_VECTOR_H
|
||||
#include<math.h>
|
||||
#include<iostream>
|
||||
#include "hacdVersion.h"
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
typedef double Real;
|
||||
//! Vector dim 3.
|
||||
template < typename T > class Vec3
|
||||
{
|
||||
public:
|
||||
T & X();
|
||||
T & Y();
|
||||
T & Z();
|
||||
const T & X() const;
|
||||
const T & Y() const;
|
||||
const T & Z() const;
|
||||
void Normalize();
|
||||
T GetNorm() const;
|
||||
void operator= (const Vec3 & rhs);
|
||||
void operator+=(const Vec3 & rhs);
|
||||
void operator-=(const Vec3 & rhs);
|
||||
void operator-=(T a);
|
||||
void operator+=(T a);
|
||||
void operator/=(T a);
|
||||
void operator*=(T a);
|
||||
Vec3 operator^ (const Vec3 & rhs) const;
|
||||
T operator* (const Vec3 & rhs) const;
|
||||
Vec3 operator+ (const Vec3 & rhs) const;
|
||||
Vec3 operator- (const Vec3 & rhs) const;
|
||||
Vec3 operator- () const;
|
||||
Vec3 operator* (T rhs) const;
|
||||
Vec3 operator/ (T rhs) const;
|
||||
Vec3();
|
||||
Vec3(T a);
|
||||
Vec3(T x, T y, T z);
|
||||
Vec3(const Vec3 & rhs);
|
||||
/*virtual*/ ~Vec3(void);
|
||||
|
||||
private:
|
||||
T m_data[3];
|
||||
};
|
||||
template<typename T>
|
||||
const bool Colinear(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c);
|
||||
template<typename T>
|
||||
const T Volume(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c, const Vec3<T> & d);
|
||||
|
||||
}
|
||||
#include "hacdVector.inl" // template implementation
|
||||
#endif
|
178
Extras/HACD/hacdVector.inl
Normal file
178
Extras/HACD/hacdVector.inl
Normal file
@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
#ifndef HACD_VECTOR_INL
|
||||
#define HACD_VECTOR_INL
|
||||
namespace HACD
|
||||
{
|
||||
template <typename T>
|
||||
inline Vec3<T> operator*(T lhs, const Vec3<T> & rhs)
|
||||
{
|
||||
return Vec3<T>(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z());
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::X()
|
||||
{
|
||||
return m_data[0];
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::Y()
|
||||
{
|
||||
return m_data[1];
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::Z()
|
||||
{
|
||||
return m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::X() const
|
||||
{
|
||||
return m_data[0];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::Y() const
|
||||
{
|
||||
return m_data[1];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::Z() const
|
||||
{
|
||||
return m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::Normalize()
|
||||
{
|
||||
T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
|
||||
if (n != 0.0) (*this) /= n;
|
||||
}
|
||||
template <typename T>
|
||||
inline T Vec3<T>::GetNorm() const
|
||||
{
|
||||
return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator= (const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] = rhs.m_data[0];
|
||||
this->m_data[1] = rhs.m_data[1];
|
||||
this->m_data[2] = rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator+=(const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] += rhs.m_data[0];
|
||||
this->m_data[1] += rhs.m_data[1];
|
||||
this->m_data[2] += rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator-=(const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] -= rhs.m_data[0];
|
||||
this->m_data[1] -= rhs.m_data[1];
|
||||
this->m_data[2] -= rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator-=(T a)
|
||||
{
|
||||
this->m_data[0] -= a;
|
||||
this->m_data[1] -= a;
|
||||
this->m_data[2] -= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator+=(T a)
|
||||
{
|
||||
this->m_data[0] += a;
|
||||
this->m_data[1] += a;
|
||||
this->m_data[2] += a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator/=(T a)
|
||||
{
|
||||
this->m_data[0] /= a;
|
||||
this->m_data[1] /= a;
|
||||
this->m_data[2] /= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator*=(T a)
|
||||
{
|
||||
this->m_data[0] *= a;
|
||||
this->m_data[1] *= a;
|
||||
this->m_data[2] *= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator^ (const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1],
|
||||
m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2],
|
||||
m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]);
|
||||
}
|
||||
template <typename T>
|
||||
inline T Vec3<T>::operator*(const Vec3<T> & rhs) const
|
||||
{
|
||||
return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator+(const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator-(const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]) ;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator-() const
|
||||
{
|
||||
return Vec3<T>(-m_data[0],-m_data[1],-m_data[2]) ;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator*(T rhs) const
|
||||
{
|
||||
return Vec3<T>(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator/ (T rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(T a)
|
||||
{
|
||||
m_data[0] = m_data[1] = m_data[2] = a;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(T x, T y, T z)
|
||||
{
|
||||
m_data[0] = x;
|
||||
m_data[1] = y;
|
||||
m_data[2] = z;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(const Vec3 & rhs)
|
||||
{
|
||||
m_data[0] = rhs.m_data[0];
|
||||
m_data[1] = rhs.m_data[1];
|
||||
m_data[2] = rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::~Vec3(void){};
|
||||
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3() {}
|
||||
|
||||
template<typename T>
|
||||
inline const bool Colinear(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c)
|
||||
{
|
||||
return ((c.Z() - a.Z()) * (b.Y() - a.Y()) - (b.Z() - a.Z()) * (c.Y() - a.Y()) == 0.0 /*EPS*/) &&
|
||||
((b.Z() - a.Z()) * (c.X() - a.X()) - (b.X() - a.X()) * (c.Z() - a.Z()) == 0.0 /*EPS*/) &&
|
||||
((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X()) == 0.0 /*EPS*/);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T Volume(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c, const Vec3<T> & d)
|
||||
{
|
||||
return (a-d) * ((b-d) ^ (c-d));
|
||||
}
|
||||
}
|
||||
#endif //HACD_VECTOR_INL
|
20
Extras/HACD/hacdVersion.h
Normal file
20
Extras/HACD/hacdVersion.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_VERSION_H
|
||||
#define HACD_VERSION_H
|
||||
#define HACD_VERSION_MAJOR 0
|
||||
#define HACD_VERSION_MINOR 0
|
||||
#endif
|
9
Extras/HACD/premake4.lua
Normal file
9
Extras/HACD/premake4.lua
Normal file
@ -0,0 +1,9 @@
|
||||
project "HACD"
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {"."}
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
95
Extras/Makefile.am
Normal file
95
Extras/Makefile.am
Normal file
@ -0,0 +1,95 @@
|
||||
noinst_LIBRARIES = libgimpactutils.a libconvexdecomposition.a libHACD.a libglui.a
|
||||
|
||||
libglui_a_CXXFLAGS = ${CXXFLAGS} -Iglui
|
||||
libglui_a_SOURCES =\
|
||||
glui/glui_spinner.cpp\
|
||||
glui/glui_treepanel.cpp\
|
||||
glui/arcball.cpp\
|
||||
glui/glui_scrollbar.cpp\
|
||||
glui/glui_filebrowser.cpp\
|
||||
glui/glui_node.cpp\
|
||||
glui/glui_edittext.cpp\
|
||||
glui/glui_statictext.cpp\
|
||||
glui/glui_bitmaps.cpp\
|
||||
glui/algebra3.cpp\
|
||||
glui/glui_string.cpp\
|
||||
glui/glui_button.cpp\
|
||||
glui/glui_add_controls.cpp\
|
||||
glui/glui_control.cpp\
|
||||
glui/glui.cpp\
|
||||
glui/glui_listbox.cpp\
|
||||
glui/glui_checkbox.cpp\
|
||||
glui/glui_commandline.cpp\
|
||||
glui/glui_textbox.cpp\
|
||||
glui/glui_column.cpp\
|
||||
glui/glui_mouse_iaction.cpp\
|
||||
glui/glui_radio.cpp\
|
||||
glui/glui_translation.cpp\
|
||||
glui/glui_tree.cpp\
|
||||
glui/glui_rotation.cpp\
|
||||
glui/glui_panel.cpp\
|
||||
glui/glui_rollout.cpp\
|
||||
glui/glui_separator.cpp\
|
||||
glui/glui_bitmap_img_data.cpp\
|
||||
glui/quaternion.cpp\
|
||||
glui/glui_window.cpp\
|
||||
glui/glui_list.cpp\
|
||||
glui/GL/glui.h\
|
||||
glui/quaternion.h\
|
||||
glui/glui_internal.h\
|
||||
glui/glui_internal_control.h\
|
||||
glui/arcball.h\
|
||||
glui/algebra3.h
|
||||
|
||||
libconvexdecomposition_a_CXXFLAGS = ${CXXFLAGS} -IConvexDecomposition/ -I../src
|
||||
libconvexdecomposition_a_SOURCES =\
|
||||
ConvexDecomposition/concavity.cpp\
|
||||
ConvexDecomposition/ConvexDecomposition.cpp\
|
||||
ConvexDecomposition/vlookup.cpp\
|
||||
ConvexDecomposition/bestfit.cpp\
|
||||
ConvexDecomposition/ConvexBuilder.cpp\
|
||||
ConvexDecomposition/cd_hull.cpp\
|
||||
ConvexDecomposition/raytri.cpp\
|
||||
ConvexDecomposition/splitplane.cpp\
|
||||
ConvexDecomposition/float_math.cpp\
|
||||
ConvexDecomposition/planetri.cpp\
|
||||
ConvexDecomposition/cd_wavefront.cpp\
|
||||
ConvexDecomposition/bestfitobb.cpp\
|
||||
ConvexDecomposition/meshvolume.cpp\
|
||||
ConvexDecomposition/fitsphere.cpp\
|
||||
ConvexDecomposition/fitsphere.h\
|
||||
ConvexDecomposition/vlookup.h\
|
||||
ConvexDecomposition/concavity.h\
|
||||
ConvexDecomposition/ConvexDecomposition.h\
|
||||
ConvexDecomposition/bestfit.h\
|
||||
ConvexDecomposition/cd_vector.h\
|
||||
ConvexDecomposition/ConvexBuilder.h\
|
||||
ConvexDecomposition/cd_hull.h\
|
||||
ConvexDecomposition/raytri.h\
|
||||
ConvexDecomposition/splitplane.h\
|
||||
ConvexDecomposition/float_math.h\
|
||||
ConvexDecomposition/planetri.h\
|
||||
ConvexDecomposition/cd_wavefront.h\
|
||||
ConvexDecomposition/bestfitobb.h\
|
||||
ConvexDecomposition/meshvolume.h
|
||||
|
||||
libHACD_a_CXXFLAGS = ${CXXFLAGS} -IHACD/ -I../src
|
||||
libHACD_a_SOURCES =\
|
||||
HACD/hacdGraph.cpp\
|
||||
HACD/hacdHACD.cpp\
|
||||
HACD/hacdICHull.cpp\
|
||||
HACD/hacdManifoldMesh.cpp\
|
||||
HACD/hacdCircularList.h\
|
||||
HACD/hacdGraph.h\
|
||||
HACD/hacdHACD.h\
|
||||
HACD/hacdICHull.h\
|
||||
HACD/hacdManifoldMesh.h\
|
||||
HACD/hacdVector.h\
|
||||
HACD/hacdVersion.h\
|
||||
HACD/hacdCircularList.inl\
|
||||
HACD/hacdVector.inl
|
||||
|
||||
|
||||
libgimpactutils_a_CXXFLAGS = ${CXXFLAGS} -I../src -IGIMPACTUtils -IConvexDecomposition
|
||||
libgimpactutils_a_SOURCES = GIMPACTUtils/btGImpactConvexDecompositionShape.cpp GIMPACTUtils/btGImpactConvexDecompositionShape.h
|
||||
|
7
Extras/Serialize/BlenderSerialize/CMakeLists.txt
Normal file
7
Extras/Serialize/BlenderSerialize/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BlenderSerialize
|
||||
)
|
||||
|
||||
ADD_LIBRARY(BlenderSerialize dna249.cpp dna249-64bit.cpp bBlenderFile.cpp bBlenderFile.h bMain.cpp bMain.h )
|
225
Extras/Serialize/BlenderSerialize/bBlenderFile.cpp
Normal file
225
Extras/Serialize/BlenderSerialize/bBlenderFile.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "bBlenderFile.h"
|
||||
#include "bMain.h"
|
||||
#include "bDefines.h"
|
||||
#include "bDNA.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// 32 && 64 bit versions
|
||||
extern unsigned char DNAstr[];
|
||||
extern int DNAlen;
|
||||
|
||||
extern unsigned char DNAstr64[];
|
||||
extern int DNAlen64;
|
||||
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
bBlenderFile::bBlenderFile(const char* fileName)
|
||||
:bFile(fileName, "BLENDER")
|
||||
{
|
||||
mMain= new bMain(this, fileName, mVersion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bBlenderFile::bBlenderFile(char *memoryBuffer, int len)
|
||||
:bFile(memoryBuffer,len, "BLENDER"),
|
||||
mMain(0)
|
||||
{
|
||||
mMain= new bMain(this, "memoryBuf", mVersion);
|
||||
}
|
||||
|
||||
|
||||
bBlenderFile::~bBlenderFile()
|
||||
{
|
||||
delete mMain;
|
||||
}
|
||||
|
||||
|
||||
bMain* bBlenderFile::getMain()
|
||||
{
|
||||
return mMain;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bBlenderFile::parseData()
|
||||
{
|
||||
// printf ("Building datablocks\n");
|
||||
// printf ("Chunk size = %d\n",CHUNK_HEADER_LEN);
|
||||
// printf ("File chunk size = %d\n", ChunkUtils::getOffset(mFlags));
|
||||
|
||||
const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
|
||||
|
||||
|
||||
|
||||
char *dataPtr = mFileBuffer+mDataStart;
|
||||
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = 0;
|
||||
|
||||
|
||||
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
//dataPtr += ChunkUtils::getOffset(mFlags);
|
||||
char *dataPtrHead = 0;
|
||||
|
||||
while (dataChunk.code != DNA1)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
// one behind
|
||||
if (dataChunk.code == SDNA) break;
|
||||
//if (dataChunk.code == DNA1) break;
|
||||
|
||||
// same as (BHEAD+DATA dependency)
|
||||
dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
|
||||
char *id = readStruct(dataPtrHead, dataChunk);
|
||||
|
||||
// lookup maps
|
||||
if (id)
|
||||
{
|
||||
m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
|
||||
|
||||
m_chunks.push_back(dataChunk);
|
||||
// block it
|
||||
bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
|
||||
if (listID)
|
||||
listID->push_back((bStructHandle*)id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == GLOB)
|
||||
{
|
||||
m_glob = (bStructHandle*) id;
|
||||
}
|
||||
|
||||
// next please!
|
||||
dataPtr += seek;
|
||||
|
||||
seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
if (seek < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void bBlenderFile::addDataBlock(char* dataBlock)
|
||||
{
|
||||
mMain->addDatablock(dataBlock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 32 && 64 bit versions
|
||||
extern unsigned char DNAstr[];
|
||||
extern int DNAlen;
|
||||
|
||||
//unsigned char DNAstr[]={0};
|
||||
//int DNAlen=0;
|
||||
|
||||
|
||||
extern unsigned char DNAstr64[];
|
||||
extern int DNAlen64;
|
||||
|
||||
|
||||
void bBlenderFile::writeDNA(FILE* fp)
|
||||
{
|
||||
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = DNA1;
|
||||
dataChunk.dna_nr = 0;
|
||||
dataChunk.nr = 1;
|
||||
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
dataChunk.len = DNAlen64;
|
||||
dataChunk.oldPtr = DNAstr64;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(DNAstr64, DNAlen64,1,fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataChunk.len = DNAlen;
|
||||
dataChunk.oldPtr = DNAstr;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(DNAstr, DNAlen,1,fp);
|
||||
}
|
||||
}
|
||||
|
||||
void bBlenderFile::parse(int verboseMode)
|
||||
{
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
parseInternal(verboseMode,(char*)DNAstr64,DNAlen64);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseInternal(verboseMode,(char*)DNAstr,DNAlen);
|
||||
}
|
||||
}
|
||||
|
||||
// experimental
|
||||
int bBlenderFile::write(const char* fileName, bool fixupPointers)
|
||||
{
|
||||
FILE *fp = fopen(fileName, "wb");
|
||||
if (fp)
|
||||
{
|
||||
char header[SIZEOFBLENDERHEADER] ;
|
||||
memcpy(header, m_headerString, 7);
|
||||
int endian= 1;
|
||||
endian= ((char*)&endian)[0];
|
||||
|
||||
if (endian)
|
||||
{
|
||||
header[7] = '_';
|
||||
} else
|
||||
{
|
||||
header[7] = '-';
|
||||
}
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
header[8]='V';
|
||||
} else
|
||||
{
|
||||
header[8]='v';
|
||||
}
|
||||
|
||||
header[9] = '2';
|
||||
header[10] = '4';
|
||||
header[11] = '9';
|
||||
|
||||
fwrite(header,SIZEOFBLENDERHEADER,1,fp);
|
||||
|
||||
writeChunks(fp, fixupPointers);
|
||||
|
||||
writeDNA(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
} else
|
||||
{
|
||||
printf("Error: cannot open file %s for writing\n",fileName);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
63
Extras/Serialize/BlenderSerialize/bBlenderFile.h
Normal file
63
Extras/Serialize/BlenderSerialize/bBlenderFile.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef B_BLENDER_FILE_H
|
||||
#define B_BLENDER_FILE_H
|
||||
|
||||
|
||||
#include "bFile.h"
|
||||
|
||||
namespace bParse {
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class bBlenderFile : public bFile
|
||||
{
|
||||
|
||||
protected:
|
||||
bMain* mMain;
|
||||
|
||||
bStructHandle* m_glob;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
bBlenderFile(const char* fileName);
|
||||
|
||||
bBlenderFile(char *memoryBuffer, int len);
|
||||
|
||||
virtual ~bBlenderFile();
|
||||
|
||||
bMain* getMain();
|
||||
|
||||
virtual void addDataBlock(char* dataBlock);
|
||||
|
||||
bStructHandle* getFileGlobal()
|
||||
{
|
||||
return m_glob;
|
||||
}
|
||||
|
||||
// experimental
|
||||
virtual int write(const char* fileName, bool fixupPointers = false);
|
||||
|
||||
virtual void parse(int verboseMode);
|
||||
|
||||
virtual void parseData();
|
||||
|
||||
virtual void writeDNA(FILE* fp);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif //B_BLENDER_FILE_H
|
392
Extras/Serialize/BlenderSerialize/bMain.cpp
Normal file
392
Extras/Serialize/BlenderSerialize/bMain.cpp
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "bMain.h"
|
||||
#include "bBlenderFile.h"
|
||||
#include "bDefines.h"
|
||||
#include "bChunk.h"
|
||||
#include "bDNA.h"
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bMain::bMain(bBlenderFile *filePtr, const char *baseName, int fileVersion)
|
||||
: mFP(filePtr),
|
||||
mVersion(fileVersion),
|
||||
mName(baseName)
|
||||
{
|
||||
mData.insert(ID_SCE,bListBasePtr());
|
||||
mData.insert(ID_LI,bListBasePtr());
|
||||
mData.insert(ID_OB,bListBasePtr());
|
||||
mData.insert(ID_ME,bListBasePtr());
|
||||
mData.insert(ID_CU,bListBasePtr());
|
||||
mData.insert(ID_MB,bListBasePtr());
|
||||
mData.insert(ID_MA,bListBasePtr());
|
||||
mData.insert(ID_TE,bListBasePtr());
|
||||
mData.insert(ID_IM,bListBasePtr());
|
||||
mData.insert(ID_WV,bListBasePtr());
|
||||
mData.insert(ID_LT,bListBasePtr());
|
||||
mData.insert(ID_LA,bListBasePtr());
|
||||
mData.insert(ID_CA,bListBasePtr());
|
||||
mData.insert(ID_IP,bListBasePtr());
|
||||
mData.insert(ID_KE,bListBasePtr());
|
||||
mData.insert(ID_WO,bListBasePtr());
|
||||
mData.insert(ID_SCR,bListBasePtr());
|
||||
mData.insert(ID_VF,bListBasePtr());
|
||||
mData.insert(ID_TXT,bListBasePtr());
|
||||
mData.insert(ID_SO,bListBasePtr());
|
||||
mData.insert(ID_GR,bListBasePtr());
|
||||
mData.insert(ID_AR,bListBasePtr());
|
||||
mData.insert(ID_AC,bListBasePtr());
|
||||
mData.insert(ID_NT,bListBasePtr());
|
||||
mData.insert(ID_BR,bListBasePtr());
|
||||
mData.insert(ID_SCRIPT, bListBasePtr());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bMain::~bMain()
|
||||
{
|
||||
// allocated data blocks!
|
||||
|
||||
int sz = mPool.size();
|
||||
for (int i=0;i<sz;i++)
|
||||
{
|
||||
delete [] mPool[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bMain::getVersion()
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
const char *bMain::getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bMain::addDatablock(void *allocated)
|
||||
{
|
||||
assert(allocated);
|
||||
mPool.push_back((bStructHandle*)allocated);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
void bMain::linkList(void *listBasePtr)
|
||||
{
|
||||
|
||||
struct ListBase // local Blender::ListBase
|
||||
{
|
||||
void *first;
|
||||
void *last;
|
||||
};
|
||||
|
||||
struct Link // local Blender::Link
|
||||
{
|
||||
void *next;
|
||||
void *prev;
|
||||
};
|
||||
|
||||
|
||||
ListBase *base = (ListBase*)listBasePtr;
|
||||
|
||||
if (!base || !base->first)
|
||||
return;
|
||||
|
||||
base->first = mFP->findLibPointer(base->first);
|
||||
if (!base->first)
|
||||
{
|
||||
base->last = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void *prev = 0;
|
||||
Link *l = (Link*)base->first;
|
||||
while (l)
|
||||
{
|
||||
l->next = mFP->findLibPointer(l->next);
|
||||
l->prev = l->next;
|
||||
prev = l->next;
|
||||
l = (Link*)l->next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr* bMain::getListBasePtr(int listBaseCode)
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(listBaseCode);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::_findCode(int code)
|
||||
{
|
||||
|
||||
bListBasePtr* lbPtr = mData.find(code);
|
||||
return lbPtr;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScene()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLibrary()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LI);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getObject()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_OB);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMesh()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_ME);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getCurve()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_CU);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMball()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_MB);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMat()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_MA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getTex()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_TE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getImage()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_IM);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getWave()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_WV);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLatt()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLamp()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getCamera()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_CA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getIpo()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_IP);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getKey()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_KE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getWorld()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_WO);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScreen()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScript()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCRIPT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getVfont()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_VF);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getText()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_TXT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getSound()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SO);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getGroup()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_GR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getArmature()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_AR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getAction()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_AC);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getNodetree()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_NT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getBrush()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_BR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//eof
|
110
Extras/Serialize/BlenderSerialize/bMain.h
Normal file
110
Extras/Serialize/BlenderSerialize/bMain.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef __BMAIN_H__
|
||||
#define __BMAIN_H__
|
||||
|
||||
#include "bCommon.h"
|
||||
#include "bChunk.h"
|
||||
#include "LinearMath/btHashMap.h"
|
||||
|
||||
|
||||
namespace bParse
|
||||
{
|
||||
class bDNA;
|
||||
|
||||
class bBlenderFile;
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace bParse {
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
|
||||
typedef btHashMap<btHashInt,bListBasePtr> bMainDataMap;
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class bMain
|
||||
{
|
||||
//private:
|
||||
public:
|
||||
bBlenderFile* mFP;
|
||||
bListBasePtr mPool;
|
||||
|
||||
int mVersion;
|
||||
const char* mName;
|
||||
|
||||
bMainDataMap mData;
|
||||
|
||||
|
||||
|
||||
|
||||
bListBasePtr *_findCode(int code);
|
||||
|
||||
public:
|
||||
bMain(bBlenderFile *filePtr, const char *baseName, int fileVersion);
|
||||
~bMain();
|
||||
|
||||
int getVersion();
|
||||
const char *getName();
|
||||
|
||||
bListBasePtr *getListBasePtr(int listBaseCode);
|
||||
|
||||
|
||||
bListBasePtr *getScene();
|
||||
bListBasePtr *getLibrary();
|
||||
bListBasePtr *getObject();
|
||||
bListBasePtr *getMesh();
|
||||
bListBasePtr *getCurve();
|
||||
bListBasePtr *getMball();
|
||||
bListBasePtr *getMat();
|
||||
bListBasePtr *getTex();
|
||||
bListBasePtr *getImage();
|
||||
bListBasePtr *getWave();
|
||||
bListBasePtr *getLatt();
|
||||
bListBasePtr *getLamp();
|
||||
bListBasePtr *getCamera();
|
||||
bListBasePtr *getIpo();
|
||||
bListBasePtr *getKey();
|
||||
bListBasePtr *getWorld();
|
||||
bListBasePtr *getScreen();
|
||||
bListBasePtr *getScript();
|
||||
bListBasePtr *getVfont();
|
||||
bListBasePtr *getText();
|
||||
bListBasePtr *getSound();
|
||||
bListBasePtr *getGroup();
|
||||
bListBasePtr *getArmature();
|
||||
bListBasePtr *getAction();
|
||||
bListBasePtr *getNodetree();
|
||||
bListBasePtr *getBrush();
|
||||
|
||||
|
||||
|
||||
// tracking allocated memory
|
||||
void addDatablock(void *allocated);
|
||||
|
||||
|
||||
// --
|
||||
|
||||
void linkList(void *listBasePtr);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif//__BMAIN_H__
|
1411
Extras/Serialize/BlenderSerialize/dna249-64bit.cpp
Normal file
1411
Extras/Serialize/BlenderSerialize/dna249-64bit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1411
Extras/Serialize/BlenderSerialize/dna249.cpp
Normal file
1411
Extras/Serialize/BlenderSerialize/dna249.cpp
Normal file
File diff suppressed because it is too large
Load Diff
49
Extras/Serialize/BulletFileLoader/CMakeLists.txt
Normal file
49
Extras/Serialize/BulletFileLoader/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
SET(BulletFileLoader_SRCS
|
||||
bChunk.cpp
|
||||
bDNA.cpp
|
||||
bFile.cpp
|
||||
btBulletFile.cpp
|
||||
)
|
||||
|
||||
SET(BulletFileLoader_HDRS
|
||||
bChunk.h
|
||||
bCommon.h
|
||||
bDefines.h
|
||||
bDNA.h
|
||||
bFile.h
|
||||
btBulletFile.h
|
||||
)
|
||||
|
||||
ADD_LIBRARY(BulletFileLoader ${BulletFileLoader_SRCS} ${BulletFileLoader_HDRS})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletFileLoader LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletFileLoader DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletFileLoader DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES PUBLIC_HEADER "${BulletFileLoader_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
1228
Extras/Serialize/BulletFileLoader/autogenerated/bullet.h
Normal file
1228
Extras/Serialize/BulletFileLoader/autogenerated/bullet.h
Normal file
File diff suppressed because it is too large
Load Diff
75
Extras/Serialize/BulletFileLoader/bChunk.cpp
Normal file
75
Extras/Serialize/BulletFileLoader/bChunk.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "bChunk.h"
|
||||
#include "bDefines.h"
|
||||
#include "bFile.h"
|
||||
|
||||
#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
short ChunkUtils::swapShort(short sht)
|
||||
{
|
||||
SWITCH_SHORT(sht);
|
||||
return sht;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int ChunkUtils::swapInt(int inte)
|
||||
{
|
||||
SWITCH_INT(inte);
|
||||
return inte;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
long64 ChunkUtils::swapLong64(long64 lng)
|
||||
{
|
||||
SWITCH_LONGINT(lng);
|
||||
return lng;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int ChunkUtils::getOffset(int flags)
|
||||
{
|
||||
// if the file is saved in a
|
||||
// different format, get the
|
||||
// file's chunk size
|
||||
int res = CHUNK_HEADER_LEN;
|
||||
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
if (flags &FD_BITS_VARIES)
|
||||
res = sizeof(bChunkPtr4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags &FD_BITS_VARIES)
|
||||
res = sizeof(bChunkPtr8);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//eof
|
92
Extras/Serialize/BulletFileLoader/bChunk.h
Normal file
92
Extras/Serialize/BulletFileLoader/bChunk.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef __BCHUNK_H__
|
||||
#define __BCHUNK_H__
|
||||
|
||||
#if defined (_WIN32) && ! defined (__MINGW32__)
|
||||
#define long64 __int64
|
||||
#elif defined (__MINGW32__)
|
||||
#include <stdint.h>
|
||||
#define long64 int64_t
|
||||
#else
|
||||
#define long64 long long
|
||||
#endif
|
||||
|
||||
|
||||
namespace bParse {
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class bChunkPtr4
|
||||
{
|
||||
public:
|
||||
bChunkPtr4(){}
|
||||
int code;
|
||||
int len;
|
||||
union
|
||||
{
|
||||
int m_uniqueInt;
|
||||
};
|
||||
int dna_nr;
|
||||
int nr;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class bChunkPtr8
|
||||
{
|
||||
public:
|
||||
bChunkPtr8(){}
|
||||
int code, len;
|
||||
union
|
||||
{
|
||||
long64 oldPrev;
|
||||
int m_uniqueInts[2];
|
||||
};
|
||||
int dna_nr, nr;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class bChunkInd
|
||||
{
|
||||
public:
|
||||
bChunkInd(){}
|
||||
int code, len;
|
||||
void *oldPtr;
|
||||
int dna_nr, nr;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class ChunkUtils
|
||||
{
|
||||
public:
|
||||
|
||||
// file chunk offset
|
||||
static int getOffset(int flags);
|
||||
|
||||
// endian utils
|
||||
static short swapShort(short sht);
|
||||
static int swapInt(int inte);
|
||||
static long64 swapLong64(long64 lng);
|
||||
|
||||
};
|
||||
|
||||
|
||||
const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
|
||||
const bool VOID_IS_8 = ((sizeof(void*)==8));
|
||||
}
|
||||
|
||||
#endif//__BCHUNK_H__
|
39
Extras/Serialize/BulletFileLoader/bCommon.h
Normal file
39
Extras/Serialize/BulletFileLoader/bCommon.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef __BCOMMON_H__
|
||||
#define __BCOMMON_H__
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
//#include "bLog.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btHashMap.h"
|
||||
|
||||
namespace bParse {
|
||||
|
||||
class bMain;
|
||||
class bFileData;
|
||||
class bFile;
|
||||
class bDNA;
|
||||
|
||||
// delete void* undefined
|
||||
typedef struct bStructHandle {int unused;}bStructHandle;
|
||||
typedef btAlignedObjectArray<bStructHandle*> bListBasePtr;
|
||||
typedef btHashMap<btHashPtr, bStructHandle*> bPtrMap;
|
||||
}
|
||||
|
||||
|
||||
#endif//__BCOMMON_H__
|
644
Extras/Serialize/BulletFileLoader/bDNA.cpp
Normal file
644
Extras/Serialize/BulletFileLoader/bDNA.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "bDNA.h"
|
||||
#include "bChunk.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//this define will force traversal of structures, to check backward (and forward) compatibility
|
||||
//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
|
||||
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bDNA::bDNA()
|
||||
: mPtrLen(0)
|
||||
{
|
||||
// --
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bDNA::~bDNA()
|
||||
{
|
||||
// --
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bool bDNA::lessThan(bDNA *file)
|
||||
{
|
||||
return ( m_Names.size() < file->m_Names.size());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
char *bDNA::getName(int ind)
|
||||
{
|
||||
assert(ind <= (int)m_Names.size());
|
||||
return m_Names[ind].m_name;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
char *bDNA::getType(int ind)
|
||||
{
|
||||
assert(ind<= (int)mTypes.size());
|
||||
return mTypes[ind];
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
short *bDNA::getStruct(int ind)
|
||||
{
|
||||
assert(ind <= (int)mStructs.size());
|
||||
return mStructs[ind];
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
short bDNA::getLength(int ind)
|
||||
{
|
||||
assert(ind <= (int)mTlens.size());
|
||||
return mTlens[ind];
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bDNA::getReverseType(short type)
|
||||
{
|
||||
|
||||
int* intPtr = mStructReverse.find(type);
|
||||
if (intPtr)
|
||||
return *intPtr;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bDNA::getReverseType(const char *type)
|
||||
{
|
||||
|
||||
btHashString key(type);
|
||||
int* valuePtr = mTypeLookup.find(key);
|
||||
if (valuePtr)
|
||||
return *valuePtr;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bDNA::getNumStructs()
|
||||
{
|
||||
return (int)mStructs.size();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bool bDNA::flagNotEqual(int dna_nr)
|
||||
{
|
||||
assert(dna_nr <= (int)mCMPFlags.size());
|
||||
return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bool bDNA::flagEqual(int dna_nr)
|
||||
{
|
||||
assert(dna_nr <= (int)mCMPFlags.size());
|
||||
int flag = mCMPFlags[dna_nr];
|
||||
return flag == FDF_STRUCT_EQU;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bool bDNA::flagNone(int dna_nr)
|
||||
{
|
||||
assert(dna_nr <= (int)mCMPFlags.size());
|
||||
return mCMPFlags[dna_nr] == FDF_NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bDNA::getPointerSize()
|
||||
{
|
||||
return mPtrLen;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bDNA::initRecurseCmpFlags(int iter)
|
||||
{
|
||||
// iter is FDF_STRUCT_NEQU
|
||||
|
||||
short *oldStrc = mStructs[iter];
|
||||
short type = oldStrc[0];
|
||||
|
||||
for (int i=0; i<(int)mStructs.size(); i++)
|
||||
{
|
||||
if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
|
||||
{
|
||||
short *curStruct = mStructs[i];
|
||||
int eleLen = curStruct[1];
|
||||
curStruct+=2;
|
||||
|
||||
for (int j=0; j<eleLen; j++, curStruct+=2)
|
||||
{
|
||||
if (curStruct[0] == type)
|
||||
{
|
||||
//char *name = m_Names[curStruct[1]].m_name;
|
||||
//if (name[0] != '*')
|
||||
if (m_Names[curStruct[1]].m_isPointer)
|
||||
{
|
||||
mCMPFlags[i] = FDF_STRUCT_NEQU;
|
||||
initRecurseCmpFlags(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bDNA::initCmpFlags(bDNA *memDNA)
|
||||
{
|
||||
|
||||
// compare the file to memory
|
||||
// this ptr should be the file data
|
||||
|
||||
|
||||
assert(!m_Names.size() == 0 && "SDNA empty!");
|
||||
mCMPFlags.resize(mStructs.size(), FDF_NONE);
|
||||
|
||||
|
||||
|
||||
int i;
|
||||
for ( i=0; i<(int)mStructs.size(); i++)
|
||||
{
|
||||
short *oldStruct = mStructs[i];
|
||||
|
||||
int oldLookup = getReverseType(oldStruct[0]);
|
||||
if (oldLookup == -1)
|
||||
{
|
||||
mCMPFlags[i] = FDF_NONE;
|
||||
continue;
|
||||
}
|
||||
//char* typeName = mTypes[oldStruct[0]];
|
||||
|
||||
//#define SLOW_FORWARD_COMPATIBLE 1
|
||||
#ifdef SLOW_FORWARD_COMPATIBLE
|
||||
char* typeName = mTypes[oldLookup];
|
||||
int newLookup = memDNA->getReverseType(typeName);
|
||||
if (newLookup == -1)
|
||||
{
|
||||
mCMPFlags[i] = FDF_NONE;
|
||||
continue;
|
||||
}
|
||||
short *curStruct = memDNA->mStructs[newLookup];
|
||||
#else
|
||||
// memory for file
|
||||
|
||||
if (oldLookup < memDNA->mStructs.size())
|
||||
{
|
||||
short *curStruct = memDNA->mStructs[oldLookup];
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// rebuild...
|
||||
mCMPFlags[i] = FDF_STRUCT_NEQU;
|
||||
|
||||
#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
|
||||
|
||||
if (curStruct[1] == oldStruct[1])
|
||||
{
|
||||
// type len same ...
|
||||
if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
|
||||
{
|
||||
bool isSame = true;
|
||||
int elementLength = oldStruct[1];
|
||||
|
||||
|
||||
curStruct+=2;
|
||||
oldStruct+=2;
|
||||
|
||||
|
||||
for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
|
||||
{
|
||||
// type the same
|
||||
//const char* typeFileDNA = mTypes[oldStruct[0]];
|
||||
//const char* typeMemDNA = mTypes[curStruct[0]];
|
||||
if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
|
||||
{
|
||||
isSame=false;
|
||||
break;
|
||||
}
|
||||
|
||||
// name the same
|
||||
if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
|
||||
{
|
||||
isSame=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// flag valid ==
|
||||
if (isSame)
|
||||
mCMPFlags[i] = FDF_STRUCT_EQU;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// recurse in
|
||||
for ( i=0; i<(int)mStructs.size(); i++)
|
||||
{
|
||||
if (mCMPFlags[i] == FDF_STRUCT_NEQU)
|
||||
initRecurseCmpFlags(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int name_is_array(char* name, int* dim1, int* dim2) {
|
||||
int len = strlen(name);
|
||||
/*fprintf(stderr,"[%s]",name);*/
|
||||
/*if (len >= 1) {
|
||||
if (name[len-1] != ']')
|
||||
return 1;
|
||||
}
|
||||
return 0;*/
|
||||
char *bp;
|
||||
int num;
|
||||
if (dim1) {
|
||||
*dim1 = 1;
|
||||
}
|
||||
if (dim2) {
|
||||
*dim2 = 1;
|
||||
}
|
||||
bp = strchr(name, '[');
|
||||
if (!bp) {
|
||||
return 0;
|
||||
}
|
||||
num = 0;
|
||||
while (++bp < name+len-1) {
|
||||
const char c = *bp;
|
||||
if (c == ']') {
|
||||
break;
|
||||
}
|
||||
if (c <= '9' && c >= '0') {
|
||||
num *= 10;
|
||||
num += (c - '0');
|
||||
} else {
|
||||
printf("array parse error.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (dim2) {
|
||||
*dim2 = num;
|
||||
}
|
||||
|
||||
/* find second dim, if any. */
|
||||
bp = strchr(bp, '[');
|
||||
if (!bp) {
|
||||
return 1; /* at least we got the first dim. */
|
||||
}
|
||||
num = 0;
|
||||
while (++bp < name+len-1) {
|
||||
const char c = *bp;
|
||||
if (c == ']') {
|
||||
break;
|
||||
}
|
||||
if (c <= '9' && c >= '0') {
|
||||
num *= 10;
|
||||
num += (c - '0');
|
||||
} else {
|
||||
printf("array2 parse error.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (dim1) {
|
||||
if (dim2) {
|
||||
*dim1 = *dim2;
|
||||
*dim2 = num;
|
||||
} else {
|
||||
*dim1 = num;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bDNA::init(char *data, int len, bool swap)
|
||||
{
|
||||
int *intPtr=0;short *shtPtr=0;
|
||||
char *cp = 0;int dataLen =0;long nr=0;
|
||||
intPtr = (int*)data;
|
||||
|
||||
/*
|
||||
SDNA (4 bytes) (magic number)
|
||||
NAME (4 bytes)
|
||||
<nr> (4 bytes) amount of names (int)
|
||||
<string>
|
||||
<string>
|
||||
*/
|
||||
|
||||
if (strncmp(data, "SDNA", 4)==0)
|
||||
{
|
||||
// skip ++ NAME
|
||||
intPtr++; intPtr++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Parse names
|
||||
if (swap)
|
||||
{
|
||||
*intPtr = ChunkUtils::swapInt(*intPtr);
|
||||
}
|
||||
dataLen = *intPtr;
|
||||
intPtr++;
|
||||
|
||||
cp = (char*)intPtr;
|
||||
int i;
|
||||
for ( i=0; i<dataLen; i++)
|
||||
{
|
||||
bNameInfo info;
|
||||
info.m_name = cp;
|
||||
info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
|
||||
name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
|
||||
m_Names.push_back(info);
|
||||
while (*cp)cp++;
|
||||
cp++;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
nr= (long)cp;
|
||||
//long mask=3;
|
||||
nr= ((nr+3)&~3)-nr;
|
||||
while (nr--)
|
||||
{
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
TYPE (4 bytes)
|
||||
<nr> amount of types (int)
|
||||
<string>
|
||||
<string>
|
||||
*/
|
||||
|
||||
intPtr = (int*)cp;
|
||||
assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
|
||||
|
||||
if (swap)
|
||||
{
|
||||
*intPtr = ChunkUtils::swapInt(*intPtr);
|
||||
}
|
||||
dataLen = *intPtr;
|
||||
intPtr++;
|
||||
|
||||
cp = (char*)intPtr;
|
||||
for ( i=0; i<dataLen; i++)
|
||||
{
|
||||
mTypes.push_back(cp);
|
||||
while (*cp)cp++;
|
||||
cp++;
|
||||
}
|
||||
|
||||
{
|
||||
nr= (long)cp;
|
||||
// long mask=3;
|
||||
nr= ((nr+3)&~3)-nr;
|
||||
while (nr--)
|
||||
{
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
TLEN (4 bytes)
|
||||
<len> (short) the lengths of types
|
||||
<len>
|
||||
*/
|
||||
|
||||
// Parse type lens
|
||||
intPtr = (int*)cp;
|
||||
assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
|
||||
|
||||
dataLen = (int)mTypes.size();
|
||||
|
||||
shtPtr = (short*)intPtr;
|
||||
for ( i=0; i<dataLen; i++, shtPtr++)
|
||||
{
|
||||
if (swap)
|
||||
shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
|
||||
mTlens.push_back(shtPtr[0]);
|
||||
}
|
||||
|
||||
if (dataLen & 1) shtPtr++;
|
||||
|
||||
/*
|
||||
STRC (4 bytes)
|
||||
<nr> amount of structs (int)
|
||||
<typenr>
|
||||
<nr_of_elems>
|
||||
<typenr>
|
||||
<namenr>
|
||||
<typenr>
|
||||
<namenr>
|
||||
*/
|
||||
|
||||
intPtr = (int*)shtPtr;
|
||||
cp = (char*)intPtr;
|
||||
assert(strncmp(cp, "STRC", 4)==0); intPtr++;
|
||||
|
||||
if (swap)
|
||||
{
|
||||
*intPtr = ChunkUtils::swapInt(*intPtr);
|
||||
}
|
||||
dataLen = *intPtr;
|
||||
intPtr++;
|
||||
|
||||
|
||||
shtPtr = (short*)intPtr;
|
||||
for ( i=0; i<dataLen; i++)
|
||||
{
|
||||
mStructs.push_back (shtPtr);
|
||||
if (swap)
|
||||
{
|
||||
shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
|
||||
shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
|
||||
|
||||
int len = shtPtr[1];
|
||||
shtPtr+= 2;
|
||||
|
||||
for (int a=0; a<len; a++, shtPtr+=2)
|
||||
{
|
||||
shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
|
||||
shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
shtPtr+= (2*shtPtr[1])+2;
|
||||
}
|
||||
|
||||
|
||||
// build reverse lookups
|
||||
for ( i=0; i<(int)mStructs.size(); i++)
|
||||
{
|
||||
short *strc = mStructs.at(i);
|
||||
if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
|
||||
{
|
||||
mPtrLen = mTlens[strc[0]]/2;
|
||||
}
|
||||
|
||||
mStructReverse.insert(strc[0], i);
|
||||
mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bDNA::getArraySize(char* string)
|
||||
{
|
||||
int ret = 1;
|
||||
int len = strlen(string);
|
||||
|
||||
|
||||
char* next = 0;
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
char c = string[i];
|
||||
|
||||
if (c == '[')
|
||||
next = &string[i+1];
|
||||
else if (c==']')
|
||||
if (next)
|
||||
ret *= atoi(next);
|
||||
}
|
||||
|
||||
// print (string << ' ' << ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void bDNA::dumpTypeDefinitions()
|
||||
{
|
||||
int i;
|
||||
|
||||
int numTypes = mTypes.size();
|
||||
|
||||
for (i=0;i<numTypes;i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for ( i=0; i<(int)mStructs.size(); i++)
|
||||
{
|
||||
int totalBytes=0;
|
||||
short *oldStruct = mStructs[i];
|
||||
|
||||
int oldLookup = getReverseType(oldStruct[0]);
|
||||
if (oldLookup == -1)
|
||||
{
|
||||
mCMPFlags[i] = FDF_NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
short* newStruct = mStructs[oldLookup];
|
||||
char* typeName = mTypes[newStruct[0]];
|
||||
printf("%3d: %s ",i,typeName);
|
||||
|
||||
//char *name = mNames[oldStruct[1]];
|
||||
int len = oldStruct[1];
|
||||
printf(" (%d fields) ",len);
|
||||
oldStruct+=2;
|
||||
|
||||
printf("{");
|
||||
int j;
|
||||
for (j=0; j<len; ++j,oldStruct+=2) {
|
||||
const char* name = m_Names[oldStruct[1]].m_name;
|
||||
printf("%s %s", mTypes[oldStruct[0]],name);
|
||||
int elemNumBytes= 0;
|
||||
int arrayDimensions = getArraySizeNew(oldStruct[1]);
|
||||
|
||||
if (m_Names[oldStruct[1]].m_isPointer)
|
||||
{
|
||||
elemNumBytes = VOID_IS_8 ? 8 : 4;
|
||||
} else
|
||||
{
|
||||
elemNumBytes = getLength(oldStruct[0]);
|
||||
}
|
||||
printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
|
||||
|
||||
if (j == len-1) {
|
||||
printf(";}");
|
||||
} else {
|
||||
printf("; ");
|
||||
}
|
||||
totalBytes+=elemNumBytes*arrayDimensions;
|
||||
}
|
||||
printf("\ntotalBytes=%d\n\n",totalBytes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* dump out display of types and their sizes */
|
||||
for (i=0; i<bf->types_count; ++i) {
|
||||
/* if (!bf->types[i].is_struct)*/
|
||||
{
|
||||
printf("%3d: sizeof(%s%s)=%d",
|
||||
i,
|
||||
bf->types[i].is_struct ? "struct " : "atomic ",
|
||||
bf->types[i].name, bf->types[i].size);
|
||||
if (bf->types[i].is_struct) {
|
||||
int j;
|
||||
printf(", %d fields: { ", bf->types[i].fieldtypes_count);
|
||||
for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
|
||||
printf("%s %s",
|
||||
bf->types[bf->types[i].fieldtypes[j]].name,
|
||||
bf->names[bf->types[i].fieldnames[j]]);
|
||||
if (j == bf->types[i].fieldtypes_count-1) {
|
||||
printf(";}");
|
||||
} else {
|
||||
printf("; ");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//eof
|
||||
|
||||
|
110
Extras/Serialize/BulletFileLoader/bDNA.h
Normal file
110
Extras/Serialize/BulletFileLoader/bDNA.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef __BDNA_H__
|
||||
#define __BDNA_H__
|
||||
|
||||
|
||||
#include "bCommon.h"
|
||||
|
||||
namespace bParse {
|
||||
|
||||
struct bNameInfo
|
||||
{
|
||||
char* m_name;
|
||||
bool m_isPointer;
|
||||
int m_dim0;
|
||||
int m_dim1;
|
||||
};
|
||||
|
||||
class bDNA
|
||||
{
|
||||
public:
|
||||
bDNA();
|
||||
~bDNA();
|
||||
|
||||
void init(char *data, int len, bool swap=false);
|
||||
|
||||
int getArraySize(char* str);
|
||||
int getArraySizeNew(short name)
|
||||
{
|
||||
const bNameInfo& nameInfo = m_Names[name];
|
||||
return nameInfo.m_dim0*nameInfo.m_dim1;
|
||||
}
|
||||
int getElementSize(short type, short name)
|
||||
{
|
||||
const bNameInfo& nameInfo = m_Names[name];
|
||||
int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1;
|
||||
return size;
|
||||
}
|
||||
|
||||
int getNumNames() const
|
||||
{
|
||||
return m_Names.size();
|
||||
}
|
||||
|
||||
char *getName(int ind);
|
||||
char *getType(int ind);
|
||||
short *getStruct(int ind);
|
||||
short getLength(int ind);
|
||||
int getReverseType(short type);
|
||||
int getReverseType(const char *type);
|
||||
|
||||
|
||||
int getNumStructs();
|
||||
|
||||
//
|
||||
bool lessThan(bDNA* other);
|
||||
|
||||
void initCmpFlags(bDNA *memDNA);
|
||||
bool flagNotEqual(int dna_nr);
|
||||
bool flagEqual(int dna_nr);
|
||||
bool flagNone(int dna_nr);
|
||||
|
||||
|
||||
int getPointerSize();
|
||||
|
||||
void dumpTypeDefinitions();
|
||||
|
||||
|
||||
private:
|
||||
enum FileDNAFlags
|
||||
{
|
||||
FDF_NONE=0,
|
||||
FDF_STRUCT_NEQU,
|
||||
FDF_STRUCT_EQU
|
||||
};
|
||||
|
||||
void initRecurseCmpFlags(int i);
|
||||
|
||||
btAlignedObjectArray<int> mCMPFlags;
|
||||
|
||||
btAlignedObjectArray<bNameInfo> m_Names;
|
||||
btAlignedObjectArray<char*> mTypes;
|
||||
btAlignedObjectArray<short*> mStructs;
|
||||
btAlignedObjectArray<short> mTlens;
|
||||
btHashMap<btHashInt, int> mStructReverse;
|
||||
btHashMap<btHashString,int> mTypeLookup;
|
||||
|
||||
int mPtrLen;
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif//__BDNA_H__
|
140
Extras/Serialize/BulletFileLoader/bDefines.h
Normal file
140
Extras/Serialize/BulletFileLoader/bDefines.h
Normal file
@ -0,0 +1,140 @@
|
||||
/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef __B_DEFINES_H__
|
||||
#define __B_DEFINES_H__
|
||||
|
||||
|
||||
// MISC defines, see BKE_global.h, BKE_utildefines.h
|
||||
#define SIZEOFBLENDERHEADER 12
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
|
||||
# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
|
||||
#else
|
||||
# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
|
||||
# define MAKE_ID2(c, d) ( (c)<<8 | (d) )
|
||||
# define MOST_SIG_BYTE 0
|
||||
# define BBIG_ENDIAN
|
||||
#else
|
||||
# define MAKE_ID2(c, d) ( (d)<<8 | (c) )
|
||||
# define MOST_SIG_BYTE 1
|
||||
# define BLITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define ID_SCE MAKE_ID2('S', 'C')
|
||||
#define ID_LI MAKE_ID2('L', 'I')
|
||||
#define ID_OB MAKE_ID2('O', 'B')
|
||||
#define ID_ME MAKE_ID2('M', 'E')
|
||||
#define ID_CU MAKE_ID2('C', 'U')
|
||||
#define ID_MB MAKE_ID2('M', 'B')
|
||||
#define ID_MA MAKE_ID2('M', 'A')
|
||||
#define ID_TE MAKE_ID2('T', 'E')
|
||||
#define ID_IM MAKE_ID2('I', 'M')
|
||||
#define ID_IK MAKE_ID2('I', 'K')
|
||||
#define ID_WV MAKE_ID2('W', 'V')
|
||||
#define ID_LT MAKE_ID2('L', 'T')
|
||||
#define ID_SE MAKE_ID2('S', 'E')
|
||||
#define ID_LF MAKE_ID2('L', 'F')
|
||||
#define ID_LA MAKE_ID2('L', 'A')
|
||||
#define ID_CA MAKE_ID2('C', 'A')
|
||||
#define ID_IP MAKE_ID2('I', 'P')
|
||||
#define ID_KE MAKE_ID2('K', 'E')
|
||||
#define ID_WO MAKE_ID2('W', 'O')
|
||||
#define ID_SCR MAKE_ID2('S', 'R')
|
||||
#define ID_VF MAKE_ID2('V', 'F')
|
||||
#define ID_TXT MAKE_ID2('T', 'X')
|
||||
#define ID_SO MAKE_ID2('S', 'O')
|
||||
#define ID_SAMPLE MAKE_ID2('S', 'A')
|
||||
#define ID_GR MAKE_ID2('G', 'R')
|
||||
#define ID_ID MAKE_ID2('I', 'D')
|
||||
#define ID_AR MAKE_ID2('A', 'R')
|
||||
#define ID_AC MAKE_ID2('A', 'C')
|
||||
#define ID_SCRIPT MAKE_ID2('P', 'Y')
|
||||
#define ID_FLUIDSIM MAKE_ID2('F', 'S')
|
||||
#define ID_NT MAKE_ID2('N', 'T')
|
||||
#define ID_BR MAKE_ID2('B', 'R')
|
||||
|
||||
|
||||
#define ID_SEQ MAKE_ID2('S', 'Q')
|
||||
#define ID_CO MAKE_ID2('C', 'O')
|
||||
#define ID_PO MAKE_ID2('A', 'C')
|
||||
#define ID_NLA MAKE_ID2('N', 'L')
|
||||
|
||||
#define ID_VS MAKE_ID2('V', 'S')
|
||||
#define ID_VN MAKE_ID2('V', 'N')
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define FORM MAKE_ID('F','O','R','M')
|
||||
#define DDG1 MAKE_ID('3','D','G','1')
|
||||
#define DDG2 MAKE_ID('3','D','G','2')
|
||||
#define DDG3 MAKE_ID('3','D','G','3')
|
||||
#define DDG4 MAKE_ID('3','D','G','4')
|
||||
#define GOUR MAKE_ID('G','O','U','R')
|
||||
#define BLEN MAKE_ID('B','L','E','N')
|
||||
#define DER_ MAKE_ID('D','E','R','_')
|
||||
#define V100 MAKE_ID('V','1','0','0')
|
||||
#define DATA MAKE_ID('D','A','T','A')
|
||||
#define GLOB MAKE_ID('G','L','O','B')
|
||||
#define IMAG MAKE_ID('I','M','A','G')
|
||||
#define TEST MAKE_ID('T','E','S','T')
|
||||
#define USER MAKE_ID('U','S','E','R')
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define DNA1 MAKE_ID('D','N','A','1')
|
||||
#define REND MAKE_ID('R','E','N','D')
|
||||
#define ENDB MAKE_ID('E','N','D','B')
|
||||
#define NAME MAKE_ID('N','A','M','E')
|
||||
#define SDNA MAKE_ID('S','D','N','A')
|
||||
#define TYPE MAKE_ID('T','Y','P','E')
|
||||
#define TLEN MAKE_ID('T','L','E','N')
|
||||
#define STRC MAKE_ID('S','T','R','C')
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define SWITCH_INT(a) { \
|
||||
char s_i, *p_i; \
|
||||
p_i= (char *)&(a); \
|
||||
s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
|
||||
s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define SWITCH_SHORT(a) { \
|
||||
char s_i, *p_i; \
|
||||
p_i= (char *)&(a); \
|
||||
s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define SWITCH_LONGINT(a) { \
|
||||
char s_i, *p_i; \
|
||||
p_i= (char *)&(a); \
|
||||
s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
|
||||
s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
|
||||
s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
|
||||
s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
|
||||
|
||||
#endif//__B_DEFINES_H__
|
1757
Extras/Serialize/BulletFileLoader/bFile.cpp
Normal file
1757
Extras/Serialize/BulletFileLoader/bFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
165
Extras/Serialize/BulletFileLoader/bFile.h
Normal file
165
Extras/Serialize/BulletFileLoader/bFile.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef __BFILE_H__
|
||||
#define __BFILE_H__
|
||||
|
||||
#include "bCommon.h"
|
||||
#include "bChunk.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace bParse {
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
enum bFileFlags
|
||||
{
|
||||
FD_INVALID =0,
|
||||
FD_OK =1,
|
||||
FD_VOID_IS_8 =2,
|
||||
FD_ENDIAN_SWAP =4,
|
||||
FD_FILE_64 =8,
|
||||
FD_BITS_VARIES =16,
|
||||
FD_VERSION_VARIES = 32,
|
||||
FD_DOUBLE_PRECISION =64,
|
||||
FD_BROKEN_DNA = 128
|
||||
};
|
||||
|
||||
enum bFileVerboseMode
|
||||
{
|
||||
FD_VERBOSE_EXPORT_XML = 1,
|
||||
FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
|
||||
FD_VERBOSE_DUMP_CHUNKS = 4,
|
||||
FD_VERBOSE_DUMP_FILE_INFO=8,
|
||||
};
|
||||
// ----------------------------------------------------- //
|
||||
class bFile
|
||||
{
|
||||
protected:
|
||||
|
||||
char m_headerString[7];
|
||||
|
||||
bool mOwnsBuffer;
|
||||
char* mFileBuffer;
|
||||
int mFileLen;
|
||||
int mVersion;
|
||||
|
||||
|
||||
bPtrMap mLibPointers;
|
||||
|
||||
int mDataStart;
|
||||
bDNA* mFileDNA;
|
||||
bDNA* mMemoryDNA;
|
||||
|
||||
btAlignedObjectArray<char*> m_pointerFixupArray;
|
||||
btAlignedObjectArray<char*> m_pointerPtrFixupArray;
|
||||
|
||||
btAlignedObjectArray<bChunkInd> m_chunks;
|
||||
btHashMap<btHashPtr, bChunkInd> m_chunkPtrPtrMap;
|
||||
|
||||
//
|
||||
|
||||
bPtrMap mDataPointers;
|
||||
|
||||
|
||||
int mFlags;
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// buffer offset util
|
||||
int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
|
||||
void safeSwapPtr(char *dst, const char *src);
|
||||
|
||||
virtual void parseHeader();
|
||||
|
||||
virtual void parseData() = 0;
|
||||
|
||||
void resolvePointersMismatch();
|
||||
void resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode);
|
||||
|
||||
int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
|
||||
//void swapPtr(char *dst, char *src);
|
||||
|
||||
void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
|
||||
void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers);
|
||||
char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
|
||||
|
||||
|
||||
void swap(char *head, class bChunkInd& ch, bool ignoreEndianFlag);
|
||||
void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
|
||||
void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
|
||||
void swapLen(char *dataPtr);
|
||||
void swapDNA(char* ptr);
|
||||
|
||||
|
||||
char* readStruct(char *head, class bChunkInd& chunk);
|
||||
char *getAsString(int code);
|
||||
|
||||
void parseInternal(int verboseMode, char* memDna,int memDnaLength);
|
||||
|
||||
public:
|
||||
bFile(const char *filename, const char headerString[7]);
|
||||
|
||||
//todo: make memoryBuffer const char
|
||||
//bFile( const char *memoryBuffer, int len);
|
||||
bFile( char *memoryBuffer, int len, const char headerString[7]);
|
||||
virtual ~bFile();
|
||||
|
||||
bDNA* getFileDNA()
|
||||
{
|
||||
return mFileDNA;
|
||||
}
|
||||
|
||||
virtual void addDataBlock(char* dataBlock) = 0;
|
||||
|
||||
int getFlags() const
|
||||
{
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
bPtrMap& getLibPointers()
|
||||
{
|
||||
return mLibPointers;
|
||||
}
|
||||
|
||||
void* findLibPointer(void *ptr);
|
||||
|
||||
bool ok();
|
||||
|
||||
virtual void parse(int verboseMode) = 0;
|
||||
|
||||
virtual int write(const char* fileName, bool fixupPointers=false) = 0;
|
||||
|
||||
virtual void writeChunks(FILE* fp, bool fixupPointers );
|
||||
|
||||
virtual void writeDNA(FILE* fp) = 0;
|
||||
|
||||
void updateOldPointers();
|
||||
void resolvePointers(int verboseMode);
|
||||
|
||||
void dumpChunks(bDNA* dna);
|
||||
|
||||
int getVersion() const
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
//pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
|
||||
void preSwap();
|
||||
void writeFile(const char* fileName);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif//__BFILE_H__
|
423
Extras/Serialize/BulletFileLoader/btBulletFile.cpp
Normal file
423
Extras/Serialize/BulletFileLoader/btBulletFile.cpp
Normal file
@ -0,0 +1,423 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btBulletFile.h"
|
||||
#include "bDefines.h"
|
||||
#include "bDNA.h"
|
||||
|
||||
#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// 32 && 64 bit versions
|
||||
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
#ifdef _WIN64
|
||||
extern char sBulletDNAstr64[];
|
||||
extern int sBulletDNAlen64;
|
||||
#else
|
||||
extern char sBulletDNAstr[];
|
||||
extern int sBulletDNAlen;
|
||||
#endif //_WIN64
|
||||
#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
|
||||
extern char sBulletDNAstr64[];
|
||||
extern int sBulletDNAlen64;
|
||||
extern char sBulletDNAstr[];
|
||||
extern int sBulletDNAlen;
|
||||
|
||||
#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
btBulletFile::btBulletFile()
|
||||
:bFile("", "BULLET ")
|
||||
{
|
||||
mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
|
||||
|
||||
m_DnaCopy = 0;
|
||||
|
||||
|
||||
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
#ifdef _WIN64
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
|
||||
mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64);
|
||||
#else//_WIN64
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
|
||||
mMemoryDNA->init(m_DnaCopy,sBulletDNAlen);
|
||||
#endif//_WIN64
|
||||
#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
m_DnaCopy = (char*) btAlignedAlloc(sBulletDNAlen64,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
|
||||
mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DnaCopy =(char*) btAlignedAlloc(sBulletDNAlen,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
|
||||
mMemoryDNA->init(m_DnaCopy,sBulletDNAlen);
|
||||
}
|
||||
#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
}
|
||||
|
||||
|
||||
|
||||
btBulletFile::btBulletFile(const char* fileName)
|
||||
:bFile(fileName, "BULLET ")
|
||||
{
|
||||
m_DnaCopy = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
btBulletFile::btBulletFile(char *memoryBuffer, int len)
|
||||
:bFile(memoryBuffer,len, "BULLET ")
|
||||
{
|
||||
m_DnaCopy = 0;
|
||||
}
|
||||
|
||||
|
||||
btBulletFile::~btBulletFile()
|
||||
{
|
||||
if (m_DnaCopy)
|
||||
btAlignedFree(m_DnaCopy);
|
||||
|
||||
|
||||
while (m_dataBlocks.size())
|
||||
{
|
||||
char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1];
|
||||
delete[] dataBlock;
|
||||
m_dataBlocks.pop_back();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void btBulletFile::parseData()
|
||||
{
|
||||
// printf ("Building datablocks");
|
||||
// printf ("Chunk size = %d",CHUNK_HEADER_LEN);
|
||||
// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
|
||||
|
||||
const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
|
||||
|
||||
//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
|
||||
|
||||
|
||||
mDataStart = 12;
|
||||
|
||||
char *dataPtr = mFileBuffer+mDataStart;
|
||||
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = 0;
|
||||
|
||||
|
||||
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
|
||||
|
||||
if (mFlags &FD_ENDIAN_SWAP)
|
||||
swapLen(dataPtr);
|
||||
|
||||
//dataPtr += ChunkUtils::getOffset(mFlags);
|
||||
char *dataPtrHead = 0;
|
||||
|
||||
while (dataChunk.code != DNA1)
|
||||
{
|
||||
if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) )
|
||||
{
|
||||
|
||||
// one behind
|
||||
if (dataChunk.code == SDNA) break;
|
||||
//if (dataChunk.code == DNA1) break;
|
||||
|
||||
// same as (BHEAD+DATA dependency)
|
||||
dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
|
||||
if (dataChunk.dna_nr>=0)
|
||||
{
|
||||
char *id = readStruct(dataPtrHead, dataChunk);
|
||||
|
||||
// lookup maps
|
||||
if (id)
|
||||
{
|
||||
m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
|
||||
|
||||
m_chunks.push_back(dataChunk);
|
||||
// block it
|
||||
//bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
|
||||
//if (listID)
|
||||
// listID->push_back((bStructHandle*)id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_SOFTBODY_CODE)
|
||||
{
|
||||
m_softBodies.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_RIGIDBODY_CODE)
|
||||
{
|
||||
m_rigidBodies.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_DYNAMICSWORLD_CODE)
|
||||
{
|
||||
m_dynamicsWorldInfo.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_CONSTRAINT_CODE)
|
||||
{
|
||||
m_constraints.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_QUANTIZED_BVH_CODE)
|
||||
{
|
||||
m_bvhs.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_TRIANLGE_INFO_MAP)
|
||||
{
|
||||
m_triangleInfoMaps.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_COLLISIONOBJECT_CODE)
|
||||
{
|
||||
m_collisionObjects.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_SHAPE_CODE)
|
||||
{
|
||||
m_collisionShapes.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
// if (dataChunk.code == GLOB)
|
||||
// {
|
||||
// m_glob = (bStructHandle*) id;
|
||||
// }
|
||||
} else
|
||||
{
|
||||
printf("unknown chunk\n");
|
||||
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
|
||||
}
|
||||
} else
|
||||
{
|
||||
printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n");
|
||||
}
|
||||
|
||||
|
||||
dataPtr += seek;
|
||||
|
||||
seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
if (mFlags &FD_ENDIAN_SWAP)
|
||||
swapLen(dataPtr);
|
||||
|
||||
if (seek < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btBulletFile::addDataBlock(char* dataBlock)
|
||||
{
|
||||
m_dataBlocks.push_back(dataBlock);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btBulletFile::writeDNA(FILE* fp)
|
||||
{
|
||||
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = DNA1;
|
||||
dataChunk.dna_nr = 0;
|
||||
dataChunk.nr = 1;
|
||||
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
dataChunk.len = sBulletDNAlen64;
|
||||
dataChunk.oldPtr = sBulletDNAstr64;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp);
|
||||
#else
|
||||
btAssert(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef _WIN64
|
||||
dataChunk.len = sBulletDNAlen;
|
||||
dataChunk.oldPtr = sBulletDNAstr;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(sBulletDNAstr, sBulletDNAlen,1,fp);
|
||||
#else//_WIN64
|
||||
btAssert(0);
|
||||
#endif//_WIN64
|
||||
}
|
||||
#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
dataChunk.len = sBulletDNAlen64;
|
||||
dataChunk.oldPtr = sBulletDNAstr64;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataChunk.len = sBulletDNAlen;
|
||||
dataChunk.oldPtr = sBulletDNAstr;
|
||||
fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
|
||||
fwrite(sBulletDNAstr, sBulletDNAlen,1,fp);
|
||||
}
|
||||
#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
}
|
||||
|
||||
|
||||
void btBulletFile::parse(int verboseMode)
|
||||
{
|
||||
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
|
||||
if (m_DnaCopy)
|
||||
delete m_DnaCopy;
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
|
||||
parseInternal(verboseMode,(char*)sBulletDNAstr64,sBulletDNAlen64);
|
||||
#else
|
||||
btAssert(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef _WIN64
|
||||
|
||||
if (m_DnaCopy)
|
||||
delete m_DnaCopy;
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
|
||||
parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen);
|
||||
#else
|
||||
btAssert(0);
|
||||
#endif
|
||||
}
|
||||
#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
if (m_DnaCopy)
|
||||
delete m_DnaCopy;
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
|
||||
parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen64);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_DnaCopy)
|
||||
delete m_DnaCopy;
|
||||
m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
|
||||
memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
|
||||
parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen);
|
||||
}
|
||||
#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
|
||||
|
||||
//the parsing will convert to cpu endian
|
||||
mFlags &=~FD_ENDIAN_SWAP;
|
||||
|
||||
int littleEndian= 1;
|
||||
littleEndian= ((char*)&littleEndian)[0];
|
||||
|
||||
mFileBuffer[8] = littleEndian?'v':'V';
|
||||
|
||||
}
|
||||
|
||||
// experimental
|
||||
int btBulletFile::write(const char* fileName, bool fixupPointers)
|
||||
{
|
||||
FILE *fp = fopen(fileName, "wb");
|
||||
if (fp)
|
||||
{
|
||||
char header[SIZEOFBLENDERHEADER] ;
|
||||
memcpy(header, m_headerString, 7);
|
||||
int endian= 1;
|
||||
endian= ((char*)&endian)[0];
|
||||
|
||||
if (endian)
|
||||
{
|
||||
header[7] = '_';
|
||||
} else
|
||||
{
|
||||
header[7] = '-';
|
||||
}
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
header[8]='V';
|
||||
} else
|
||||
{
|
||||
header[8]='v';
|
||||
}
|
||||
|
||||
header[9] = '2';
|
||||
header[10] = '7';
|
||||
header[11] = '5';
|
||||
|
||||
fwrite(header,SIZEOFBLENDERHEADER,1,fp);
|
||||
|
||||
writeChunks(fp, fixupPointers);
|
||||
|
||||
writeDNA(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
} else
|
||||
{
|
||||
printf("Error: cannot open file %s for writing\n",fileName);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btBulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code)
|
||||
{
|
||||
|
||||
bParse::bChunkInd dataChunk;
|
||||
dataChunk.code = code;
|
||||
dataChunk.nr = 1;
|
||||
dataChunk.len = len;
|
||||
dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
|
||||
dataChunk.oldPtr = oldPtr;
|
||||
|
||||
///Perform structure size validation
|
||||
short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr);
|
||||
int elemBytes;
|
||||
elemBytes= mMemoryDNA->getLength(structInfo[0]);
|
||||
// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
|
||||
assert(len==elemBytes);
|
||||
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
|
||||
m_chunks.push_back(dataChunk);
|
||||
}
|
83
Extras/Serialize/BulletFileLoader/btBulletFile.h
Normal file
83
Extras/Serialize/BulletFileLoader/btBulletFile.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_BULLET_FILE_H
|
||||
#define BT_BULLET_FILE_H
|
||||
|
||||
|
||||
#include "bFile.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "bDefines.h"
|
||||
|
||||
#include "LinearMath/btSerializer.h"
|
||||
|
||||
|
||||
|
||||
namespace bParse {
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
class btBulletFile : public bFile
|
||||
{
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
char* m_DnaCopy;
|
||||
|
||||
public:
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_softBodies;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_rigidBodies;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_collisionObjects;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_collisionShapes;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_constraints;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_bvhs;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
|
||||
|
||||
btAlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
|
||||
|
||||
btAlignedObjectArray<char*> m_dataBlocks;
|
||||
btBulletFile();
|
||||
|
||||
btBulletFile(const char* fileName);
|
||||
|
||||
btBulletFile(char *memoryBuffer, int len);
|
||||
|
||||
virtual ~btBulletFile();
|
||||
|
||||
virtual void addDataBlock(char* dataBlock);
|
||||
|
||||
|
||||
// experimental
|
||||
virtual int write(const char* fileName, bool fixupPointers=false);
|
||||
|
||||
virtual void parse(int verboseMode);
|
||||
|
||||
virtual void parseData();
|
||||
|
||||
virtual void writeDNA(FILE* fp);
|
||||
|
||||
void addStruct(const char* structType,void* data, int len, void* oldPtr, int code);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif //BT_BULLET_FILE_H
|
12
Extras/Serialize/BulletFileLoader/premake4.lua
Normal file
12
Extras/Serialize/BulletFileLoader/premake4.lua
Normal file
@ -0,0 +1,12 @@
|
||||
project "BulletFileLoader"
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {
|
||||
"../../../src"
|
||||
}
|
||||
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
40
Extras/Serialize/BulletWorldImporter/CMakeLists.txt
Normal file
40
Extras/Serialize/BulletWorldImporter/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
|
||||
)
|
||||
|
||||
ADD_LIBRARY(
|
||||
BulletWorldImporter
|
||||
btBulletWorldImporter.cpp
|
||||
btBulletWorldImporter.h
|
||||
btWorldImporter.cpp
|
||||
btWorldImporter.h
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletWorldImporter BulletDynamics BulletCollision BulletFileLoader LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletWorldImporter DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletWorldImporter DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES PUBLIC_HEADER "btBulletWorldImporter.h")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
362
Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp
Normal file
362
Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btBulletWorldImporter.h"
|
||||
#include "../BulletFileLoader/btBulletFile.h"
|
||||
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "BulletCollision/Gimpact/btGImpactShape.h"
|
||||
|
||||
|
||||
|
||||
//#define USE_INTERNAL_EDGE_UTILITY
|
||||
#ifdef USE_INTERNAL_EDGE_UTILITY
|
||||
#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
|
||||
#endif //USE_INTERNAL_EDGE_UTILITY
|
||||
|
||||
btBulletWorldImporter::btBulletWorldImporter(btDynamicsWorld* world)
|
||||
:btWorldImporter(world)
|
||||
{
|
||||
}
|
||||
|
||||
btBulletWorldImporter::~btBulletWorldImporter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool btBulletWorldImporter::loadFile( const char* fileName, const char* preSwapFilenameOut)
|
||||
{
|
||||
bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName);
|
||||
|
||||
|
||||
bool result = loadFileFromMemory(bulletFile2);
|
||||
//now you could save the file in 'native' format using
|
||||
//bulletFile2->writeFile("native.bullet");
|
||||
if (result)
|
||||
{
|
||||
if (preSwapFilenameOut)
|
||||
{
|
||||
bulletFile2->preSwap();
|
||||
bulletFile2->writeFile(preSwapFilenameOut);
|
||||
}
|
||||
|
||||
}
|
||||
delete bulletFile2;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool btBulletWorldImporter::loadFileFromMemory( char* memoryBuffer, int len)
|
||||
{
|
||||
bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(memoryBuffer,len);
|
||||
|
||||
bool result = loadFileFromMemory(bulletFile2);
|
||||
|
||||
delete bulletFile2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool btBulletWorldImporter::loadFileFromMemory( bParse::btBulletFile* bulletFile2)
|
||||
{
|
||||
bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
|
||||
|
||||
if (ok)
|
||||
bulletFile2->parse(m_verboseMode);
|
||||
else
|
||||
return false;
|
||||
|
||||
if (m_verboseMode & bParse::FD_VERBOSE_DUMP_CHUNKS)
|
||||
{
|
||||
bulletFile2->dumpChunks(bulletFile2->getFileDNA());
|
||||
}
|
||||
|
||||
return convertAllObjects(bulletFile2);
|
||||
|
||||
}
|
||||
|
||||
bool btBulletWorldImporter::convertAllObjects( bParse::btBulletFile* bulletFile2)
|
||||
{
|
||||
|
||||
m_shapeMap.clear();
|
||||
m_bodyMap.clear();
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0;i<bulletFile2->m_bvhs.size();i++)
|
||||
{
|
||||
btOptimizedBvh* bvh = createOptimizedBvh();
|
||||
|
||||
if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
|
||||
{
|
||||
btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i];
|
||||
bvh->deSerializeDouble(*bvhData);
|
||||
} else
|
||||
{
|
||||
btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i];
|
||||
bvh->deSerializeFloat(*bvhData);
|
||||
}
|
||||
m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
|
||||
{
|
||||
btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
|
||||
btCollisionShape* shape = convertCollisionShape(shapeData);
|
||||
if (shape)
|
||||
{
|
||||
// printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
|
||||
m_shapeMap.insert(shapeData,shape);
|
||||
}
|
||||
|
||||
if (shape&& shapeData->m_name)
|
||||
{
|
||||
char* newname = duplicateName(shapeData->m_name);
|
||||
m_objectNameMap.insert(shape,newname);
|
||||
m_nameShapeMap.insert(newname,shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i=0;i<bulletFile2->m_dynamicsWorldInfo.size();i++)
|
||||
{
|
||||
if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
|
||||
{
|
||||
btDynamicsWorldDoubleData* solverInfoData = (btDynamicsWorldDoubleData*)bulletFile2->m_dynamicsWorldInfo[i];
|
||||
btContactSolverInfo solverInfo;
|
||||
|
||||
btVector3 gravity;
|
||||
gravity.deSerializeDouble(solverInfoData->m_gravity);
|
||||
|
||||
solverInfo.m_tau = btScalar(solverInfoData->m_solverInfo.m_tau);
|
||||
solverInfo.m_damping = btScalar(solverInfoData->m_solverInfo.m_damping);
|
||||
solverInfo.m_friction = btScalar(solverInfoData->m_solverInfo.m_friction);
|
||||
solverInfo.m_timeStep = btScalar(solverInfoData->m_solverInfo.m_timeStep);
|
||||
|
||||
solverInfo.m_restitution = btScalar(solverInfoData->m_solverInfo.m_restitution);
|
||||
solverInfo.m_maxErrorReduction = btScalar(solverInfoData->m_solverInfo.m_maxErrorReduction);
|
||||
solverInfo.m_sor = btScalar(solverInfoData->m_solverInfo.m_sor);
|
||||
solverInfo.m_erp = btScalar(solverInfoData->m_solverInfo.m_erp);
|
||||
|
||||
solverInfo.m_erp2 = btScalar(solverInfoData->m_solverInfo.m_erp2);
|
||||
solverInfo.m_globalCfm = btScalar(solverInfoData->m_solverInfo.m_globalCfm);
|
||||
solverInfo.m_splitImpulsePenetrationThreshold = btScalar(solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold);
|
||||
solverInfo.m_splitImpulseTurnErp = btScalar(solverInfoData->m_solverInfo.m_splitImpulseTurnErp);
|
||||
|
||||
solverInfo.m_linearSlop = btScalar(solverInfoData->m_solverInfo.m_linearSlop);
|
||||
solverInfo.m_warmstartingFactor = btScalar(solverInfoData->m_solverInfo.m_warmstartingFactor);
|
||||
solverInfo.m_maxGyroscopicForce = btScalar(solverInfoData->m_solverInfo.m_maxGyroscopicForce);
|
||||
solverInfo.m_singleAxisRollingFrictionThreshold = btScalar(solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold);
|
||||
|
||||
solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
|
||||
solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
|
||||
solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
|
||||
solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
|
||||
|
||||
solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;
|
||||
|
||||
setDynamicsWorldInfo(gravity,solverInfo);
|
||||
} else
|
||||
{
|
||||
btDynamicsWorldFloatData* solverInfoData = (btDynamicsWorldFloatData*)bulletFile2->m_dynamicsWorldInfo[i];
|
||||
btContactSolverInfo solverInfo;
|
||||
|
||||
btVector3 gravity;
|
||||
gravity.deSerializeFloat(solverInfoData->m_gravity);
|
||||
|
||||
solverInfo.m_tau = solverInfoData->m_solverInfo.m_tau;
|
||||
solverInfo.m_damping = solverInfoData->m_solverInfo.m_damping;
|
||||
solverInfo.m_friction = solverInfoData->m_solverInfo.m_friction;
|
||||
solverInfo.m_timeStep = solverInfoData->m_solverInfo.m_timeStep;
|
||||
|
||||
solverInfo.m_restitution = solverInfoData->m_solverInfo.m_restitution;
|
||||
solverInfo.m_maxErrorReduction = solverInfoData->m_solverInfo.m_maxErrorReduction;
|
||||
solverInfo.m_sor = solverInfoData->m_solverInfo.m_sor;
|
||||
solverInfo.m_erp = solverInfoData->m_solverInfo.m_erp;
|
||||
|
||||
solverInfo.m_erp2 = solverInfoData->m_solverInfo.m_erp2;
|
||||
solverInfo.m_globalCfm = solverInfoData->m_solverInfo.m_globalCfm;
|
||||
solverInfo.m_splitImpulsePenetrationThreshold = solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold;
|
||||
solverInfo.m_splitImpulseTurnErp = solverInfoData->m_solverInfo.m_splitImpulseTurnErp;
|
||||
|
||||
solverInfo.m_linearSlop = solverInfoData->m_solverInfo.m_linearSlop;
|
||||
solverInfo.m_warmstartingFactor = solverInfoData->m_solverInfo.m_warmstartingFactor;
|
||||
solverInfo.m_maxGyroscopicForce = solverInfoData->m_solverInfo.m_maxGyroscopicForce;
|
||||
solverInfo.m_singleAxisRollingFrictionThreshold = solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold;
|
||||
|
||||
solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
|
||||
solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
|
||||
solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
|
||||
solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
|
||||
|
||||
solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;
|
||||
|
||||
setDynamicsWorldInfo(gravity,solverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i=0;i<bulletFile2->m_rigidBodies.size();i++)
|
||||
{
|
||||
if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
|
||||
{
|
||||
btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
|
||||
convertRigidBodyDouble(colObjData);
|
||||
} else
|
||||
{
|
||||
btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
|
||||
convertRigidBodyFloat(colObjData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (i=0;i<bulletFile2->m_collisionObjects.size();i++)
|
||||
{
|
||||
if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
|
||||
{
|
||||
btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i];
|
||||
btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
|
||||
if (shapePtr && *shapePtr)
|
||||
{
|
||||
btTransform startTransform;
|
||||
colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
|
||||
startTransform.deSerializeDouble(colObjData->m_worldTransform);
|
||||
|
||||
btCollisionShape* shape = (btCollisionShape*)*shapePtr;
|
||||
btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
|
||||
body->setFriction(btScalar(colObjData->m_friction));
|
||||
body->setRestitution(btScalar(colObjData->m_restitution));
|
||||
|
||||
#ifdef USE_INTERNAL_EDGE_UTILITY
|
||||
if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
||||
{
|
||||
btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
|
||||
if (trimesh->getTriangleInfoMap())
|
||||
{
|
||||
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
|
||||
}
|
||||
}
|
||||
#endif //USE_INTERNAL_EDGE_UTILITY
|
||||
m_bodyMap.insert(colObjData,body);
|
||||
} else
|
||||
{
|
||||
printf("error: no shape found\n");
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i];
|
||||
btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
|
||||
if (shapePtr && *shapePtr)
|
||||
{
|
||||
btTransform startTransform;
|
||||
colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
|
||||
startTransform.deSerializeFloat(colObjData->m_worldTransform);
|
||||
|
||||
btCollisionShape* shape = (btCollisionShape*)*shapePtr;
|
||||
btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
|
||||
|
||||
#ifdef USE_INTERNAL_EDGE_UTILITY
|
||||
if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
|
||||
{
|
||||
btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
|
||||
if (trimesh->getTriangleInfoMap())
|
||||
{
|
||||
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
|
||||
}
|
||||
}
|
||||
#endif //USE_INTERNAL_EDGE_UTILITY
|
||||
m_bodyMap.insert(colObjData,body);
|
||||
} else
|
||||
{
|
||||
printf("error: no shape found\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (i=0;i<bulletFile2->m_constraints.size();i++)
|
||||
{
|
||||
btTypedConstraintData2* constraintData = (btTypedConstraintData2*)bulletFile2->m_constraints[i];
|
||||
btTypedConstraintFloatData* singleC = (btTypedConstraintFloatData*)bulletFile2->m_constraints[i];
|
||||
btTypedConstraintDoubleData* doubleC = (btTypedConstraintDoubleData*)bulletFile2->m_constraints[i];
|
||||
|
||||
btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA);
|
||||
btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB);
|
||||
|
||||
btRigidBody* rbA = 0;
|
||||
btRigidBody* rbB = 0;
|
||||
|
||||
if (colAptr)
|
||||
{
|
||||
rbA = btRigidBody::upcast(*colAptr);
|
||||
if (!rbA)
|
||||
rbA = &getFixedBody();
|
||||
}
|
||||
if (colBptr)
|
||||
{
|
||||
rbB = btRigidBody::upcast(*colBptr);
|
||||
if (!rbB)
|
||||
rbB = &getFixedBody();
|
||||
}
|
||||
if (!rbA && !rbB)
|
||||
continue;
|
||||
|
||||
bool isDoublePrecisionData = (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)!=0;
|
||||
|
||||
if (isDoublePrecisionData)
|
||||
{
|
||||
if (bulletFile2->getVersion()>=282)
|
||||
{
|
||||
btTypedConstraintDoubleData* dc = (btTypedConstraintDoubleData*)constraintData;
|
||||
convertConstraintDouble(dc, rbA,rbB, bulletFile2->getVersion());
|
||||
} else
|
||||
{
|
||||
//double-precision constraints were messed up until 2.82, try to recover data...
|
||||
|
||||
btTypedConstraintData* oldData = (btTypedConstraintData*)constraintData;
|
||||
|
||||
convertConstraintBackwardsCompatible281(oldData, rbA,rbB, bulletFile2->getVersion());
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btTypedConstraintFloatData* dc = (btTypedConstraintFloatData*)constraintData;
|
||||
convertConstraintFloat(dc, rbA,rbB, bulletFile2->getVersion());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
68
Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h
Normal file
68
Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BULLET_WORLD_IMPORTER_H
|
||||
#define BULLET_WORLD_IMPORTER_H
|
||||
|
||||
|
||||
#include "btWorldImporter.h"
|
||||
|
||||
|
||||
class btBulletFile;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace bParse
|
||||
{
|
||||
class btBulletFile;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///The btBulletWorldImporter is a starting point to import .bullet files.
|
||||
///note that not all data is converted yet. You are expected to override or modify this class.
|
||||
///See Bullet/Demos/SerializeDemo for a derived class that extract btSoftBody objects too.
|
||||
class btBulletWorldImporter : public btWorldImporter
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btBulletWorldImporter(btDynamicsWorld* world=0);
|
||||
|
||||
virtual ~btBulletWorldImporter();
|
||||
|
||||
///if you pass a valid preSwapFilenameOut, it will save a new file with a different endianness
|
||||
///this pre-swapped file can be loaded without swapping on a target platform of different endianness
|
||||
bool loadFile(const char* fileName, const char* preSwapFilenameOut=0);
|
||||
|
||||
///the memoryBuffer might be modified (for example if endian swaps are necessary)
|
||||
bool loadFileFromMemory(char *memoryBuffer, int len);
|
||||
|
||||
bool loadFileFromMemory(bParse::btBulletFile* file);
|
||||
|
||||
//call make sure bulletFile2 has been parsed, either using btBulletFile::parse or btBulletWorldImporter::loadFileFromMemory
|
||||
virtual bool convertAllObjects(bParse::btBulletFile* file);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BULLET_WORLD_IMPORTER_H
|
||||
|
1922
Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp
Normal file
1922
Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
212
Extras/Serialize/BulletWorldImporter/btWorldImporter.h
Normal file
212
Extras/Serialize/BulletWorldImporter/btWorldImporter.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_WORLD_IMPORTER_H
|
||||
#define BT_WORLD_IMPORTER_H
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btHashMap.h"
|
||||
|
||||
class btCollisionShape;
|
||||
class btCollisionObject;
|
||||
class btRigidBody;
|
||||
class btTypedConstraint;
|
||||
class btDynamicsWorld;
|
||||
struct ConstraintInput;
|
||||
class btRigidBodyColladaInfo;
|
||||
struct btCollisionShapeData;
|
||||
class btTriangleIndexVertexArray;
|
||||
class btStridingMeshInterface;
|
||||
struct btStridingMeshInterfaceData;
|
||||
class btGImpactMeshShape;
|
||||
class btOptimizedBvh;
|
||||
struct btTriangleInfoMap;
|
||||
class btBvhTriangleMeshShape;
|
||||
class btPoint2PointConstraint;
|
||||
class btHingeConstraint;
|
||||
class btConeTwistConstraint;
|
||||
class btGeneric6DofConstraint;
|
||||
class btGeneric6DofSpringConstraint;
|
||||
class btSliderConstraint;
|
||||
class btGearConstraint;
|
||||
struct btContactSolverInfo;
|
||||
struct btTypedConstraintData;
|
||||
struct btTypedConstraintFloatData;
|
||||
struct btTypedConstraintDoubleData;
|
||||
|
||||
struct btRigidBodyDoubleData;
|
||||
struct btRigidBodyFloatData;
|
||||
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
#define btRigidBodyData btRigidBodyDoubleData
|
||||
#else
|
||||
#define btRigidBodyData btRigidBodyFloatData
|
||||
#endif//BT_USE_DOUBLE_PRECISION
|
||||
|
||||
|
||||
class btWorldImporter
|
||||
{
|
||||
protected:
|
||||
btDynamicsWorld* m_dynamicsWorld;
|
||||
|
||||
int m_verboseMode;
|
||||
|
||||
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
|
||||
btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
|
||||
btAlignedObjectArray<btTypedConstraint*> m_allocatedConstraints;
|
||||
btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
|
||||
btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
|
||||
btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
|
||||
btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
|
||||
|
||||
btAlignedObjectArray<char*> m_allocatedNames;
|
||||
|
||||
btAlignedObjectArray<int*> m_indexArrays;
|
||||
btAlignedObjectArray<short int*> m_shortIndexArrays;
|
||||
btAlignedObjectArray<unsigned char*> m_charIndexArrays;
|
||||
|
||||
btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
|
||||
btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
|
||||
|
||||
|
||||
btHashMap<btHashPtr,btOptimizedBvh*> m_bvhMap;
|
||||
btHashMap<btHashPtr,btTriangleInfoMap*> m_timMap;
|
||||
|
||||
btHashMap<btHashString,btCollisionShape*> m_nameShapeMap;
|
||||
btHashMap<btHashString,btRigidBody*> m_nameBodyMap;
|
||||
btHashMap<btHashString,btTypedConstraint*> m_nameConstraintMap;
|
||||
btHashMap<btHashPtr,const char*> m_objectNameMap;
|
||||
|
||||
btHashMap<btHashPtr,btCollisionShape*> m_shapeMap;
|
||||
btHashMap<btHashPtr,btCollisionObject*> m_bodyMap;
|
||||
|
||||
|
||||
//methods
|
||||
|
||||
static btRigidBody& getFixedBody();
|
||||
|
||||
char* duplicateName(const char* name);
|
||||
|
||||
btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData );
|
||||
|
||||
void convertConstraintBackwardsCompatible281(btTypedConstraintData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion);
|
||||
void convertConstraintFloat(btTypedConstraintFloatData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion);
|
||||
void convertConstraintDouble(btTypedConstraintDoubleData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion);
|
||||
void convertRigidBodyFloat(btRigidBodyFloatData* colObjData);
|
||||
void convertRigidBodyDouble( btRigidBodyDoubleData* colObjData);
|
||||
|
||||
public:
|
||||
|
||||
btWorldImporter(btDynamicsWorld* world);
|
||||
|
||||
virtual ~btWorldImporter();
|
||||
|
||||
///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
|
||||
///make sure you don't use the dynamics world containing objects after you call this method
|
||||
virtual void deleteAllData();
|
||||
|
||||
void setVerboseMode(int verboseMode)
|
||||
{
|
||||
m_verboseMode = verboseMode;
|
||||
}
|
||||
|
||||
int getVerboseMode() const
|
||||
{
|
||||
return m_verboseMode;
|
||||
}
|
||||
|
||||
// query for data
|
||||
int getNumCollisionShapes() const;
|
||||
btCollisionShape* getCollisionShapeByIndex(int index);
|
||||
int getNumRigidBodies() const;
|
||||
btCollisionObject* getRigidBodyByIndex(int index) const;
|
||||
int getNumConstraints() const;
|
||||
btTypedConstraint* getConstraintByIndex(int index) const;
|
||||
int getNumBvhs() const;
|
||||
btOptimizedBvh* getBvhByIndex(int index) const;
|
||||
int getNumTriangleInfoMaps() const;
|
||||
btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
|
||||
|
||||
// queris involving named objects
|
||||
btCollisionShape* getCollisionShapeByName(const char* name);
|
||||
btRigidBody* getRigidBodyByName(const char* name);
|
||||
btTypedConstraint* getConstraintByName(const char* name);
|
||||
const char* getNameForPointer(const void* ptr) const;
|
||||
|
||||
///those virtuals are called by load and can be overridden by the user
|
||||
|
||||
virtual void setDynamicsWorldInfo(const btVector3& gravity, const btContactSolverInfo& solverInfo);
|
||||
|
||||
//bodies
|
||||
virtual btRigidBody* createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
|
||||
virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
|
||||
|
||||
///shapes
|
||||
|
||||
virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
|
||||
virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
|
||||
virtual btCollisionShape* createSphereShape(btScalar radius);
|
||||
virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
|
||||
virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
|
||||
virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
|
||||
|
||||
virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
|
||||
virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
|
||||
virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
|
||||
virtual btCollisionShape* createConeShapeX(btScalar radius,btScalar height);
|
||||
virtual btCollisionShape* createConeShapeY(btScalar radius,btScalar height);
|
||||
virtual btCollisionShape* createConeShapeZ(btScalar radius,btScalar height);
|
||||
virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
|
||||
virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
|
||||
virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
|
||||
virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
|
||||
virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
|
||||
|
||||
virtual class btConvexHullShape* createConvexHullShape();
|
||||
virtual class btCompoundShape* createCompoundShape();
|
||||
virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape);
|
||||
|
||||
virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres);
|
||||
|
||||
virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
|
||||
|
||||
///acceleration and connectivity structures
|
||||
virtual btOptimizedBvh* createOptimizedBvh();
|
||||
virtual btTriangleInfoMap* createTriangleInfoMap();
|
||||
|
||||
///constraints
|
||||
virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB);
|
||||
virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA);
|
||||
virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA=false);
|
||||
virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA=false);
|
||||
virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
|
||||
virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
|
||||
virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
|
||||
virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
|
||||
virtual btGeneric6DofSpringConstraint* createGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
|
||||
virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
|
||||
virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
|
||||
virtual btGearConstraint* createGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //BT_WORLD_IMPORTER_H
|
13
Extras/Serialize/BulletWorldImporter/premake4.lua
Normal file
13
Extras/Serialize/BulletWorldImporter/premake4.lua
Normal file
@ -0,0 +1,13 @@
|
||||
project "BulletWorldImporter"
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {
|
||||
"../BulletFileLoader",
|
||||
"../../../src"
|
||||
}
|
||||
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
47
Extras/Serialize/BulletXmlWorldImporter/CMakeLists.txt
Normal file
47
Extras/Serialize/BulletXmlWorldImporter/CMakeLists.txt
Normal file
@ -0,0 +1,47 @@
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter
|
||||
)
|
||||
|
||||
ADD_LIBRARY(
|
||||
BulletXmlWorldImporter
|
||||
btBulletXmlWorldImporter.cpp
|
||||
btBulletXmlWorldImporter.h
|
||||
string_split.cpp
|
||||
string_split.h
|
||||
tinyxml.cpp
|
||||
tinyxml.h
|
||||
tinystr.cpp
|
||||
tinystr.h
|
||||
tinyxmlerror.cpp
|
||||
tinyxmlparser.cpp
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletXmlWorldImporter PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletXmlWorldImporter PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletXmlWorldImporter BulletWorldImporter BulletDynamics BulletCollision BulletFileLoader LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletXmlWorldImporter DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletXmlWorldImporter DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletXmlWorldImporter PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletXmlWorldImporter PROPERTIES PUBLIC_HEADER "btBulletXmlWorldImporter.h")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
@ -0,0 +1,871 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btBulletXmlWorldImporter.h"
|
||||
#include "tinyxml.h"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "string_split.h"
|
||||
|
||||
|
||||
btBulletXmlWorldImporter::btBulletXmlWorldImporter(btDynamicsWorld* world)
|
||||
:btWorldImporter(world),
|
||||
m_fileVersion(-1),
|
||||
m_fileOk(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
btBulletXmlWorldImporter::~btBulletXmlWorldImporter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int get_double_attribute_by_name(const TiXmlElement* pElement, const char* attribName,double* value)
|
||||
{
|
||||
if ( !pElement )
|
||||
return 0;
|
||||
|
||||
const TiXmlAttribute* pAttrib=pElement->FirstAttribute();
|
||||
while (pAttrib)
|
||||
{
|
||||
if (pAttrib->Name()==attribName)
|
||||
if (pAttrib->QueryDoubleValue(value)==TIXML_SUCCESS)
|
||||
return 1;
|
||||
pAttrib=pAttrib->Next();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_int_attribute_by_name(const TiXmlElement* pElement, const char* attribName,int* value)
|
||||
{
|
||||
if ( !pElement )
|
||||
return 0;
|
||||
|
||||
const TiXmlAttribute* pAttrib=pElement->FirstAttribute();
|
||||
while (pAttrib)
|
||||
{
|
||||
if (!strcmp(pAttrib->Name(),attribName))
|
||||
if (pAttrib->QueryIntValue(value)==TIXML_SUCCESS)
|
||||
return 1;
|
||||
// if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
|
||||
pAttrib=pAttrib->Next();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stringToFloatArray(const std::string& string, btAlignedObjectArray<float>& floats)
|
||||
{
|
||||
btAlignedObjectArray<std::string> pieces;
|
||||
|
||||
bullet_utils::split( pieces, string, " ");
|
||||
for ( int i = 0; i < pieces.size(); ++i)
|
||||
{
|
||||
assert(pieces[i]!="");
|
||||
floats.push_back((float)atof(pieces[i].c_str()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static btVector3FloatData TextToVector3Data(const char* txt)
|
||||
{
|
||||
btAssert(txt);
|
||||
btAlignedObjectArray<float> floats;
|
||||
stringToFloatArray(txt, floats);
|
||||
assert(floats.size()==4);
|
||||
|
||||
btVector3FloatData vec4;
|
||||
vec4.m_floats[0] = floats[0];
|
||||
vec4.m_floats[1] = floats[1];
|
||||
vec4.m_floats[2] = floats[2];
|
||||
vec4.m_floats[3] = floats[3];
|
||||
return vec4;
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeVector3FloatData(TiXmlNode* pParent,btAlignedObjectArray<btVector3FloatData>& vectors)
|
||||
{
|
||||
TiXmlNode* flNode = pParent->FirstChild("m_floats");
|
||||
btAssert(flNode);
|
||||
while (flNode && flNode->FirstChild())
|
||||
{
|
||||
TiXmlText* pText = flNode->FirstChild()->ToText();
|
||||
// printf("value = %s\n",pText->Value());
|
||||
btVector3FloatData vec4 = TextToVector3Data(pText->Value());
|
||||
vectors.push_back(vec4);
|
||||
flNode = flNode->NextSibling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#define SET_INT_VALUE(xmlnode, targetdata, argname) \
|
||||
btAssert((xmlnode)->FirstChild(#argname) && (xmlnode)->FirstChild(#argname)->ToElement());\
|
||||
if ((xmlnode)->FirstChild(#argname) && (xmlnode)->FirstChild(#argname)->ToElement())\
|
||||
(targetdata)->argname= (int)atof(xmlnode->FirstChild(#argname)->ToElement()->GetText());
|
||||
|
||||
|
||||
#define SET_FLOAT_VALUE(xmlnode, targetdata, argname) \
|
||||
btAssert((xmlnode)->FirstChild(#argname) && (xmlnode)->FirstChild(#argname)->ToElement());\
|
||||
if ((xmlnode)->FirstChild(#argname) && (xmlnode)->FirstChild(#argname)->ToElement())\
|
||||
(targetdata)->argname= (float)atof(xmlnode->FirstChild(#argname)->ToElement()->GetText());
|
||||
|
||||
|
||||
#define SET_POINTER_VALUE(xmlnode, targetdata, argname, pointertype) \
|
||||
{\
|
||||
TiXmlNode* node = xmlnode->FirstChild(#argname);\
|
||||
btAssert(node);\
|
||||
if (node)\
|
||||
{\
|
||||
const char* txt = (node)->ToElement()->GetText();\
|
||||
(targetdata).argname= (pointertype) (int) atof(txt);\
|
||||
}\
|
||||
}
|
||||
|
||||
#define SET_VECTOR4_VALUE(xmlnode, targetdata, argname) \
|
||||
{\
|
||||
TiXmlNode* flNode = xmlnode->FirstChild(#argname);\
|
||||
btAssert(flNode);\
|
||||
if (flNode && flNode->FirstChild())\
|
||||
{\
|
||||
const char* txt= flNode->FirstChild()->ToElement()->GetText();\
|
||||
btVector3FloatData vec4 = TextToVector3Data(txt);\
|
||||
(targetdata)->argname.m_floats[0] = vec4.m_floats[0];\
|
||||
(targetdata)->argname.m_floats[1] = vec4.m_floats[1];\
|
||||
(targetdata)->argname.m_floats[2] = vec4.m_floats[2];\
|
||||
(targetdata)->argname.m_floats[3] = vec4.m_floats[3];\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
#define SET_MATRIX33_VALUE(n, targetdata, argname) \
|
||||
{\
|
||||
TiXmlNode* xmlnode = n->FirstChild(#argname);\
|
||||
btAssert(xmlnode);\
|
||||
if (xmlnode)\
|
||||
{\
|
||||
TiXmlNode* eleNode = xmlnode->FirstChild("m_el");\
|
||||
btAssert(eleNode);\
|
||||
if (eleNode&& eleNode->FirstChild())\
|
||||
{\
|
||||
const char* txt= eleNode->FirstChild()->ToElement()->GetText();\
|
||||
btVector3FloatData vec4 = TextToVector3Data(txt);\
|
||||
(targetdata)->argname.m_el[0].m_floats[0] = vec4.m_floats[0];\
|
||||
(targetdata)->argname.m_el[0].m_floats[1] = vec4.m_floats[1];\
|
||||
(targetdata)->argname.m_el[0].m_floats[2] = vec4.m_floats[2];\
|
||||
(targetdata)->argname.m_el[0].m_floats[3] = vec4.m_floats[3];\
|
||||
\
|
||||
TiXmlNode* n1 = eleNode->FirstChild()->NextSibling();\
|
||||
btAssert(n1);\
|
||||
if (n1)\
|
||||
{\
|
||||
const char* txt= n1->ToElement()->GetText();\
|
||||
btVector3FloatData vec4 = TextToVector3Data(txt);\
|
||||
(targetdata)->argname.m_el[1].m_floats[0] = vec4.m_floats[0];\
|
||||
(targetdata)->argname.m_el[1].m_floats[1] = vec4.m_floats[1];\
|
||||
(targetdata)->argname.m_el[1].m_floats[2] = vec4.m_floats[2];\
|
||||
(targetdata)->argname.m_el[1].m_floats[3] = vec4.m_floats[3];\
|
||||
\
|
||||
TiXmlNode* n2 = n1->NextSibling();\
|
||||
btAssert(n2);\
|
||||
if (n2)\
|
||||
{\
|
||||
const char* txt= n2->ToElement()->GetText();\
|
||||
btVector3FloatData vec4 = TextToVector3Data(txt);\
|
||||
(targetdata)->argname.m_el[2].m_floats[0] = vec4.m_floats[0];\
|
||||
(targetdata)->argname.m_el[2].m_floats[1] = vec4.m_floats[1];\
|
||||
(targetdata)->argname.m_el[2].m_floats[2] = vec4.m_floats[2];\
|
||||
(targetdata)->argname.m_el[2].m_floats[3] = vec4.m_floats[3];\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define SET_TRANSFORM_VALUE(n, targetdata, argname) \
|
||||
{\
|
||||
TiXmlNode* trNode = n->FirstChild(#argname);\
|
||||
btAssert(trNode);\
|
||||
if (trNode)\
|
||||
{\
|
||||
SET_VECTOR4_VALUE(trNode,&(targetdata)->argname,m_origin)\
|
||||
SET_MATRIX33_VALUE(trNode, &(targetdata)->argname,m_basis)\
|
||||
}\
|
||||
}\
|
||||
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeCollisionShapeData(TiXmlNode* pParent, btCollisionShapeData* colShapeData)
|
||||
{
|
||||
SET_INT_VALUE(pParent,colShapeData,m_shapeType)
|
||||
colShapeData->m_name = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeConvexHullShapeData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
btConvexHullShapeData* convexHullData = (btConvexHullShapeData*)btAlignedAlloc(sizeof(btConvexHullShapeData), 16);
|
||||
|
||||
TiXmlNode* xmlConvexInt = pParent->FirstChild("m_convexInternalShapeData");
|
||||
btAssert(xmlConvexInt);
|
||||
|
||||
TiXmlNode* xmlColShape = xmlConvexInt ->FirstChild("m_collisionShapeData");
|
||||
btAssert(xmlColShape);
|
||||
|
||||
deSerializeCollisionShapeData(xmlColShape,&convexHullData->m_convexInternalShapeData.m_collisionShapeData);
|
||||
|
||||
SET_FLOAT_VALUE(xmlConvexInt,&convexHullData->m_convexInternalShapeData,m_collisionMargin)
|
||||
SET_VECTOR4_VALUE(xmlConvexInt,&convexHullData->m_convexInternalShapeData,m_localScaling)
|
||||
SET_VECTOR4_VALUE(xmlConvexInt,&convexHullData->m_convexInternalShapeData,m_implicitShapeDimensions)
|
||||
|
||||
SET_POINTER_VALUE(pParent,*convexHullData,m_unscaledPointsFloatPtr,btVector3FloatData*);
|
||||
SET_POINTER_VALUE(pParent,*convexHullData,m_unscaledPointsDoublePtr,btVector3DoubleData*);
|
||||
SET_INT_VALUE(pParent,convexHullData,m_numUnscaledPoints);
|
||||
|
||||
m_collisionShapeData.push_back((btCollisionShapeData*)convexHullData);
|
||||
m_pointerLookup.insert((void*)ptr,convexHullData);
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeCompoundShapeChildData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
int numChildren = 0;
|
||||
btAlignedObjectArray<btCompoundShapeChildData>* compoundChildArrayPtr = new btAlignedObjectArray<btCompoundShapeChildData>;
|
||||
{
|
||||
TiXmlNode* transNode = pParent->FirstChild("m_transform");
|
||||
TiXmlNode* colShapeNode = pParent->FirstChild("m_childShape");
|
||||
TiXmlNode* marginNode = pParent->FirstChild("m_childMargin");
|
||||
TiXmlNode* childTypeNode = pParent->FirstChild("m_childShapeType");
|
||||
|
||||
int i=0;
|
||||
while (transNode && colShapeNode && marginNode && childTypeNode)
|
||||
{
|
||||
compoundChildArrayPtr->expandNonInitializing();
|
||||
SET_VECTOR4_VALUE (transNode,&compoundChildArrayPtr->at(i).m_transform,m_origin)
|
||||
SET_MATRIX33_VALUE(transNode,&compoundChildArrayPtr->at(i).m_transform,m_basis)
|
||||
|
||||
const char* txt = (colShapeNode)->ToElement()->GetText();
|
||||
compoundChildArrayPtr->at(i).m_childShape = (btCollisionShapeData*) (int) atof(txt);
|
||||
|
||||
btAssert(childTypeNode->ToElement());
|
||||
if (childTypeNode->ToElement())
|
||||
{
|
||||
compoundChildArrayPtr->at(i).m_childShapeType = (int)atof(childTypeNode->ToElement()->GetText());
|
||||
}
|
||||
|
||||
btAssert(marginNode->ToElement());
|
||||
if (marginNode->ToElement())
|
||||
{
|
||||
compoundChildArrayPtr->at(i).m_childMargin = (float)atof(marginNode->ToElement()->GetText());
|
||||
}
|
||||
|
||||
transNode = transNode->NextSibling("m_transform");
|
||||
colShapeNode = colShapeNode->NextSibling("m_childShape");
|
||||
marginNode = marginNode->NextSibling("m_childMargin");
|
||||
childTypeNode = childTypeNode->NextSibling("m_childShapeType");
|
||||
i++;
|
||||
}
|
||||
|
||||
numChildren = i;
|
||||
|
||||
}
|
||||
|
||||
btAssert(numChildren);
|
||||
if (numChildren)
|
||||
{
|
||||
m_compoundShapeChildDataArrays.push_back(compoundChildArrayPtr);
|
||||
btCompoundShapeChildData* cd = &compoundChildArrayPtr->at(0);
|
||||
m_pointerLookup.insert((void*)ptr,cd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeCompoundShapeData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
btCompoundShapeData* compoundData = (btCompoundShapeData*) btAlignedAlloc(sizeof(btCompoundShapeData),16);
|
||||
|
||||
TiXmlNode* xmlColShape = pParent ->FirstChild("m_collisionShapeData");
|
||||
btAssert(xmlColShape);
|
||||
deSerializeCollisionShapeData(xmlColShape,&compoundData->m_collisionShapeData);
|
||||
|
||||
SET_INT_VALUE(pParent, compoundData,m_numChildShapes);
|
||||
|
||||
TiXmlNode* xmlShapeData = pParent->FirstChild("m_collisionShapeData");
|
||||
btAssert(xmlShapeData );
|
||||
|
||||
{
|
||||
TiXmlNode* node = pParent->FirstChild("m_childShapePtr");\
|
||||
btAssert(node);
|
||||
while (node)
|
||||
{
|
||||
const char* txt = (node)->ToElement()->GetText();
|
||||
compoundData->m_childShapePtr = (btCompoundShapeChildData*) (int) atof(txt);
|
||||
node = node->NextSibling("m_childShapePtr");
|
||||
}
|
||||
//SET_POINTER_VALUE(xmlColShape, *compoundData,m_childShapePtr,btCompoundShapeChildData*);
|
||||
|
||||
}
|
||||
SET_FLOAT_VALUE(pParent, compoundData,m_collisionMargin);
|
||||
|
||||
m_collisionShapeData.push_back((btCollisionShapeData*)compoundData);
|
||||
m_pointerLookup.insert((void*)ptr,compoundData);
|
||||
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeStaticPlaneShapeData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) btAlignedAlloc(sizeof(btStaticPlaneShapeData),16);
|
||||
|
||||
TiXmlNode* xmlShapeData = pParent->FirstChild("m_collisionShapeData");
|
||||
btAssert(xmlShapeData );
|
||||
deSerializeCollisionShapeData(xmlShapeData,&planeData->m_collisionShapeData);
|
||||
|
||||
SET_VECTOR4_VALUE(pParent, planeData,m_localScaling);
|
||||
SET_VECTOR4_VALUE(pParent, planeData,m_planeNormal);
|
||||
SET_FLOAT_VALUE(pParent, planeData,m_planeConstant);
|
||||
|
||||
m_collisionShapeData.push_back((btCollisionShapeData*)planeData);
|
||||
m_pointerLookup.insert((void*)ptr,planeData);
|
||||
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeDynamicsWorldData(TiXmlNode* pParent)
|
||||
{
|
||||
btContactSolverInfo solverInfo;
|
||||
//btVector3 gravity(0,0,0);
|
||||
|
||||
//setDynamicsWorldInfo(gravity,solverInfo);
|
||||
|
||||
//gravity and world info
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeConvexInternalShapeData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr=0;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
|
||||
btConvexInternalShapeData* convexShape = (btConvexInternalShapeData*) btAlignedAlloc(sizeof(btConvexInternalShapeData),16);
|
||||
memset(convexShape,0,sizeof(btConvexInternalShapeData));
|
||||
|
||||
TiXmlNode* xmlShapeData = pParent->FirstChild("m_collisionShapeData");
|
||||
btAssert(xmlShapeData );
|
||||
|
||||
deSerializeCollisionShapeData(xmlShapeData,&convexShape->m_collisionShapeData);
|
||||
|
||||
|
||||
SET_FLOAT_VALUE(pParent,convexShape,m_collisionMargin)
|
||||
SET_VECTOR4_VALUE(pParent,convexShape,m_localScaling)
|
||||
SET_VECTOR4_VALUE(pParent,convexShape,m_implicitShapeDimensions)
|
||||
|
||||
m_collisionShapeData.push_back((btCollisionShapeData*)convexShape);
|
||||
m_pointerLookup.insert((void*)ptr,convexShape);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
enum btTypedConstraintType
|
||||
{
|
||||
POINT2POINT_CONSTRAINT_TYPE=3,
|
||||
HINGE_CONSTRAINT_TYPE,
|
||||
CONETWIST_CONSTRAINT_TYPE,
|
||||
// D6_CONSTRAINT_TYPE,
|
||||
SLIDER_CONSTRAINT_TYPE,
|
||||
CONTACT_CONSTRAINT_TYPE,
|
||||
D6_SPRING_CONSTRAINT_TYPE,
|
||||
GEAR_CONSTRAINT_TYPE,
|
||||
MAX_CONSTRAINT_TYPE
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeGeneric6DofConstraintData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr=0;
|
||||
get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr);
|
||||
|
||||
btGeneric6DofConstraintData2* dof6Data = (btGeneric6DofConstraintData2*)btAlignedAlloc(sizeof(btGeneric6DofConstraintData2),16);
|
||||
|
||||
|
||||
TiXmlNode* n = pParent->FirstChild("m_typeConstraintData");
|
||||
if (n)
|
||||
{
|
||||
SET_POINTER_VALUE(n,dof6Data->m_typeConstraintData,m_rbA,btRigidBodyData*);
|
||||
SET_POINTER_VALUE(n,dof6Data->m_typeConstraintData,m_rbB,btRigidBodyData*);
|
||||
dof6Data->m_typeConstraintData.m_name = 0;//tbd
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_objectType);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_userConstraintType);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_userConstraintId);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_needsFeedback);
|
||||
SET_FLOAT_VALUE(n,&dof6Data->m_typeConstraintData,m_appliedImpulse);
|
||||
SET_FLOAT_VALUE(n,&dof6Data->m_typeConstraintData,m_dbgDrawSize);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_disableCollisionsBetweenLinkedBodies);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_overrideNumSolverIterations);
|
||||
SET_FLOAT_VALUE(n,&dof6Data->m_typeConstraintData,m_breakingImpulseThreshold);
|
||||
SET_INT_VALUE(n,&dof6Data->m_typeConstraintData,m_isEnabled);
|
||||
|
||||
}
|
||||
|
||||
SET_TRANSFORM_VALUE( pParent, dof6Data, m_rbAFrame);
|
||||
SET_TRANSFORM_VALUE( pParent, dof6Data, m_rbBFrame);
|
||||
SET_VECTOR4_VALUE(pParent, dof6Data, m_linearUpperLimit);
|
||||
SET_VECTOR4_VALUE(pParent, dof6Data, m_linearLowerLimit);
|
||||
SET_VECTOR4_VALUE(pParent, dof6Data, m_angularUpperLimit);
|
||||
SET_VECTOR4_VALUE(pParent, dof6Data, m_angularLowerLimit);
|
||||
SET_INT_VALUE(pParent, dof6Data,m_useLinearReferenceFrameA);
|
||||
SET_INT_VALUE(pParent, dof6Data,m_useOffsetForConstraintFrame);
|
||||
|
||||
m_constraintData.push_back((btTypedConstraintData2*)dof6Data);
|
||||
m_pointerLookup.insert((void*)ptr,dof6Data);
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::deSerializeRigidBodyFloatData(TiXmlNode* pParent)
|
||||
{
|
||||
int ptr=0;
|
||||
if (!get_int_attribute_by_name(pParent->ToElement(),"pointer",&ptr))
|
||||
{
|
||||
m_fileOk = false;
|
||||
return;
|
||||
}
|
||||
|
||||
btRigidBodyData* rbData = (btRigidBodyData*)btAlignedAlloc(sizeof(btRigidBodyData),16);
|
||||
|
||||
TiXmlNode* n = pParent->FirstChild("m_collisionObjectData");
|
||||
|
||||
if (n)
|
||||
{
|
||||
SET_POINTER_VALUE(n,rbData->m_collisionObjectData,m_collisionShape, void*);
|
||||
SET_TRANSFORM_VALUE(n,&rbData->m_collisionObjectData,m_worldTransform);
|
||||
SET_TRANSFORM_VALUE(n,&rbData->m_collisionObjectData,m_interpolationWorldTransform);
|
||||
SET_VECTOR4_VALUE(n,&rbData->m_collisionObjectData,m_interpolationLinearVelocity)
|
||||
SET_VECTOR4_VALUE(n,&rbData->m_collisionObjectData,m_interpolationAngularVelocity)
|
||||
SET_VECTOR4_VALUE(n,&rbData->m_collisionObjectData,m_anisotropicFriction)
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_contactProcessingThreshold);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_deactivationTime);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_friction);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_restitution);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_hitFraction);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_ccdSweptSphereRadius);
|
||||
SET_FLOAT_VALUE(n,&rbData->m_collisionObjectData,m_ccdMotionThreshold);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_hasAnisotropicFriction);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_collisionFlags);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_islandTag1);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_companionId);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_activationState1);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_internalType);
|
||||
SET_INT_VALUE(n,&rbData->m_collisionObjectData,m_checkCollideWith);
|
||||
}
|
||||
|
||||
// SET_VECTOR4_VALUE(pParent,rbData,m_linearVelocity);
|
||||
|
||||
SET_MATRIX33_VALUE(pParent,rbData,m_invInertiaTensorWorld);
|
||||
|
||||
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_linearVelocity)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_angularVelocity)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_angularFactor)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_linearFactor)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_gravity)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_gravity_acceleration )
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_invInertiaLocal)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_totalTorque)
|
||||
SET_VECTOR4_VALUE(pParent,rbData,m_totalForce)
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_inverseMass);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_linearDamping);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_angularDamping);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_additionalDampingFactor);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_additionalLinearDampingThresholdSqr);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_additionalAngularDampingThresholdSqr);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_additionalAngularDampingFactor);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_angularSleepingThreshold);
|
||||
SET_FLOAT_VALUE(pParent,rbData,m_linearSleepingThreshold);
|
||||
SET_INT_VALUE(pParent,rbData,m_additionalDamping);
|
||||
|
||||
|
||||
m_rigidBodyData.push_back(rbData);
|
||||
m_pointerLookup.insert((void*)ptr,rbData);
|
||||
|
||||
// rbData->m_collisionObjectData.m_collisionShape = (void*) (int)atof(txt);
|
||||
}
|
||||
|
||||
/*
|
||||
TETRAHEDRAL_SHAPE_PROXYTYPE,
|
||||
CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
|
||||
,
|
||||
CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
|
||||
CUSTOM_POLYHEDRAL_SHAPE_TYPE,
|
||||
//implicit convex shapes
|
||||
IMPLICIT_CONVEX_SHAPES_START_HERE,
|
||||
SPHERE_SHAPE_PROXYTYPE,
|
||||
MULTI_SPHERE_SHAPE_PROXYTYPE,
|
||||
CAPSULE_SHAPE_PROXYTYPE,
|
||||
CONE_SHAPE_PROXYTYPE,
|
||||
CONVEX_SHAPE_PROXYTYPE,
|
||||
CYLINDER_SHAPE_PROXYTYPE,
|
||||
UNIFORM_SCALING_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
|
||||
BOX_2D_SHAPE_PROXYTYPE,
|
||||
CONVEX_2D_SHAPE_PROXYTYPE,
|
||||
CUSTOM_CONVEX_SHAPE_TYPE,
|
||||
//concave shapes
|
||||
CONCAVE_SHAPES_START_HERE,
|
||||
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
||||
TRIANGLE_MESH_SHAPE_PROXYTYPE,
|
||||
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
|
||||
///used for demo integration FAST/Swift collision library and Bullet
|
||||
FAST_CONCAVE_MESH_PROXYTYPE,
|
||||
//terrain
|
||||
TERRAIN_SHAPE_PROXYTYPE,
|
||||
///Used for GIMPACT Trimesh integration
|
||||
GIMPACT_SHAPE_PROXYTYPE,
|
||||
///Multimaterial mesh
|
||||
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
|
||||
|
||||
,
|
||||
,
|
||||
CUSTOM_CONCAVE_SHAPE_TYPE,
|
||||
CONCAVE_SHAPES_END_HERE,
|
||||
|
||||
,
|
||||
|
||||
SOFTBODY_SHAPE_PROXYTYPE,
|
||||
HFFLUID_SHAPE_PROXYTYPE,
|
||||
HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
|
||||
INVALID_SHAPE_PROXYTYPE,
|
||||
|
||||
MAX_BROADPHASE_COLLISION_TYPES
|
||||
*/
|
||||
|
||||
void btBulletXmlWorldImporter::fixupConstraintData(btTypedConstraintData2* tcd)
|
||||
{
|
||||
if (tcd->m_rbA)
|
||||
{
|
||||
btRigidBodyData** ptrptr = (btRigidBodyData**)m_pointerLookup.find(tcd->m_rbA);
|
||||
btAssert(ptrptr);
|
||||
tcd->m_rbA = ptrptr? *ptrptr : 0;
|
||||
}
|
||||
if (tcd->m_rbB)
|
||||
{
|
||||
btRigidBodyData** ptrptr = (btRigidBodyData**)m_pointerLookup.find(tcd->m_rbB);
|
||||
btAssert(ptrptr);
|
||||
tcd->m_rbB = ptrptr? *ptrptr : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::fixupCollisionDataPointers(btCollisionShapeData* shapeData)
|
||||
{
|
||||
|
||||
switch (shapeData->m_shapeType)
|
||||
{
|
||||
|
||||
case COMPOUND_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btCompoundShapeData* compound = (btCompoundShapeData*) shapeData;
|
||||
|
||||
void** cdptr = m_pointerLookup.find((void*)compound->m_childShapePtr);
|
||||
btCompoundShapeChildData** c = (btCompoundShapeChildData**)cdptr;
|
||||
btAssert(c);
|
||||
if (c)
|
||||
{
|
||||
compound->m_childShapePtr = *c;
|
||||
} else
|
||||
{
|
||||
compound->m_childShapePtr = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btConvexHullShapeData* convexData = (btConvexHullShapeData*)shapeData;
|
||||
btVector3FloatData** ptrptr = (btVector3FloatData**)m_pointerLookup.find((void*)convexData->m_unscaledPointsFloatPtr);
|
||||
btAssert(ptrptr);
|
||||
if (ptrptr)
|
||||
{
|
||||
convexData->m_unscaledPointsFloatPtr = *ptrptr;
|
||||
} else
|
||||
{
|
||||
convexData->m_unscaledPointsFloatPtr = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
case TRIANGLE_SHAPE_PROXYTYPE:
|
||||
case STATIC_PLANE_PROXYTYPE:
|
||||
case EMPTY_SHAPE_PROXYTYPE:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
btAssert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btBulletXmlWorldImporter::auto_serialize_root_level_children(TiXmlNode* pParent)
|
||||
{
|
||||
int numChildren = 0;
|
||||
btAssert(pParent);
|
||||
if (pParent)
|
||||
{
|
||||
TiXmlNode*pChild;
|
||||
for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling(), numChildren++)
|
||||
{
|
||||
// printf("child Name=%s\n", pChild->Value());
|
||||
if (!strcmp(pChild->Value(),"btVector3FloatData"))
|
||||
{
|
||||
int ptr;
|
||||
get_int_attribute_by_name(pChild->ToElement(),"pointer",&ptr);
|
||||
|
||||
btAlignedObjectArray<btVector3FloatData> v;
|
||||
deSerializeVector3FloatData(pChild,v);
|
||||
int numVectors = v.size();
|
||||
btVector3FloatData* vectors= (btVector3FloatData*) btAlignedAlloc(sizeof(btVector3FloatData)*numVectors,16);
|
||||
for (int i=0;i<numVectors;i++)
|
||||
vectors[i] = v[i];
|
||||
m_floatVertexArrays.push_back(vectors);
|
||||
m_pointerLookup.insert((void*)ptr,vectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btGeneric6DofConstraintData"))
|
||||
{
|
||||
deSerializeGeneric6DofConstraintData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btStaticPlaneShapeData"))
|
||||
{
|
||||
deSerializeStaticPlaneShapeData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btCompoundShapeData"))
|
||||
{
|
||||
deSerializeCompoundShapeData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btCompoundShapeChildData"))
|
||||
{
|
||||
deSerializeCompoundShapeChildData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btConvexHullShapeData"))
|
||||
{
|
||||
deSerializeConvexHullShapeData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(pChild->Value(),"btDynamicsWorldFloatData"))
|
||||
{
|
||||
deSerializeDynamicsWorldData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(pChild->Value(),"btConvexInternalShapeData"))
|
||||
{
|
||||
deSerializeConvexInternalShapeData(pChild);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(pChild->Value(),"btRigidBodyFloatData"))
|
||||
{
|
||||
deSerializeRigidBodyFloatData(pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
//printf("Error: btBulletXmlWorldImporter doesn't support %s yet\n", pChild->Value());
|
||||
// btAssert(0);
|
||||
}
|
||||
}
|
||||
|
||||
///=================================================================
|
||||
///fixup pointers in various places, in the right order
|
||||
|
||||
//fixup compoundshape child data
|
||||
for (int i=0;i<m_compoundShapeChildDataArrays.size();i++)
|
||||
{
|
||||
btAlignedObjectArray<btCompoundShapeChildData>* childDataArray = m_compoundShapeChildDataArrays[i];
|
||||
for (int c=0;c<childDataArray->size();c++)
|
||||
{
|
||||
btCompoundShapeChildData* childData = &childDataArray->at(c);
|
||||
btCollisionShapeData** ptrptr = (btCollisionShapeData**)m_pointerLookup[childData->m_childShape];
|
||||
btAssert(ptrptr);
|
||||
if (ptrptr)
|
||||
{
|
||||
childData->m_childShape = *ptrptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<this->m_collisionShapeData.size();i++)
|
||||
{
|
||||
btCollisionShapeData* shapeData = m_collisionShapeData[i];
|
||||
fixupCollisionDataPointers(shapeData);
|
||||
|
||||
}
|
||||
|
||||
///now fixup pointers
|
||||
for (int i=0;i<m_rigidBodyData.size();i++)
|
||||
{
|
||||
btRigidBodyData* rbData = m_rigidBodyData[i];
|
||||
|
||||
void** ptrptr = m_pointerLookup.find(rbData->m_collisionObjectData.m_collisionShape);
|
||||
//btAssert(ptrptr);
|
||||
rbData->m_collisionObjectData.m_broadphaseHandle = 0;
|
||||
rbData->m_collisionObjectData.m_rootCollisionShape = 0;
|
||||
rbData->m_collisionObjectData.m_name = 0;//tbd
|
||||
if (ptrptr)
|
||||
{
|
||||
rbData->m_collisionObjectData.m_collisionShape = *ptrptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i=0;i<m_constraintData.size();i++)
|
||||
{
|
||||
btTypedConstraintData2* tcd = m_constraintData[i];
|
||||
fixupConstraintData(tcd);
|
||||
|
||||
}
|
||||
///=================================================================
|
||||
///convert data into Bullet data in the right order
|
||||
|
||||
///convert collision shapes
|
||||
for (int i=0;i<this->m_collisionShapeData.size();i++)
|
||||
{
|
||||
btCollisionShapeData* shapeData = m_collisionShapeData[i];
|
||||
btCollisionShape* shape = convertCollisionShape(shapeData);
|
||||
if (shape)
|
||||
{
|
||||
m_shapeMap.insert(shapeData,shape);
|
||||
}
|
||||
if (shape&& shapeData->m_name)
|
||||
{
|
||||
char* newname = duplicateName(shapeData->m_name);
|
||||
m_objectNameMap.insert(shape,newname);
|
||||
m_nameShapeMap.insert(newname,shape);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<m_rigidBodyData.size();i++)
|
||||
{
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
convertRigidBodyDouble(m_rigidBodyData[i]);
|
||||
#else
|
||||
convertRigidBodyFloat(m_rigidBodyData[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int i=0;i<m_constraintData.size();i++)
|
||||
{
|
||||
btTypedConstraintData2* tcd = m_constraintData[i];
|
||||
bool isDoublePrecision = false;
|
||||
btRigidBody* rbA = 0;
|
||||
btRigidBody* rbB = 0;
|
||||
{
|
||||
btCollisionObject** ptrptr = m_bodyMap.find(tcd->m_rbA);
|
||||
if (ptrptr)
|
||||
{
|
||||
rbA = btRigidBody::upcast(*ptrptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
btCollisionObject** ptrptr = m_bodyMap.find(tcd->m_rbB);
|
||||
if (ptrptr)
|
||||
{
|
||||
rbB = btRigidBody::upcast(*ptrptr);
|
||||
}
|
||||
}
|
||||
if (rbA || rbB)
|
||||
{
|
||||
btAssert(0);//todo
|
||||
//convertConstraint(tcd,rbA,rbB,isDoublePrecision, m_fileVersion);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void btBulletXmlWorldImporter::auto_serialize(TiXmlNode* pParent)
|
||||
{
|
||||
// TiXmlElement* root = pParent->FirstChildElement("bullet_physics");
|
||||
if (pParent)
|
||||
{
|
||||
TiXmlNode*pChild;
|
||||
for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
|
||||
{
|
||||
if (pChild->Type()==TiXmlNode::TINYXML_ELEMENT)
|
||||
{
|
||||
// printf("root Name=%s\n", pChild->Value());
|
||||
auto_serialize_root_level_children(pChild);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
printf("ERROR: no bullet_physics element\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool btBulletXmlWorldImporter::loadFile(const char* fileName)
|
||||
{
|
||||
TiXmlDocument doc(fileName);
|
||||
|
||||
bool loadOkay = doc.LoadFile();
|
||||
//dump_to_stdout(&doc,0);
|
||||
|
||||
|
||||
if (loadOkay)
|
||||
{
|
||||
if (get_int_attribute_by_name(doc.FirstChildElement()->ToElement(),"version", &m_fileVersion))
|
||||
{
|
||||
if (m_fileVersion==281)
|
||||
{
|
||||
m_fileOk = true;
|
||||
int itemcount;
|
||||
get_int_attribute_by_name(doc.FirstChildElement()->ToElement(),"itemcount", &itemcount);
|
||||
|
||||
auto_serialize(&doc);
|
||||
return m_fileOk;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_BULLET_XML_WORLD_IMPORTER_H
|
||||
#define BT_BULLET_XML_WORLD_IMPORTER_H
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
|
||||
class btDynamicsWorld;
|
||||
class TiXmlNode;
|
||||
struct btConvexInternalShapeData;
|
||||
struct btCollisionShapeData;
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
struct btRigidBodyDoubleData;
|
||||
struct btTypedConstraintDoubleData;
|
||||
#define btRigidBodyData btRigidBodyDoubleData
|
||||
#define btTypedConstraintData2 btTypedConstraintDoubleData
|
||||
#else
|
||||
struct btRigidBodyFloatData;
|
||||
struct btTypedConstraintFloatData;
|
||||
#define btTypedConstraintData2 btTypedConstraintFloatData
|
||||
#define btRigidBodyData btRigidBodyFloatData
|
||||
#endif//BT_USE_DOUBLE_PRECISION
|
||||
|
||||
|
||||
struct btCompoundShapeChildData;
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "btWorldImporter.h"
|
||||
|
||||
class btBulletXmlWorldImporter : public btWorldImporter
|
||||
{
|
||||
|
||||
protected:
|
||||
btAlignedObjectArray<btCollisionShapeData*> m_collisionShapeData;
|
||||
btAlignedObjectArray<btAlignedObjectArray<btCompoundShapeChildData>* > m_compoundShapeChildDataArrays;
|
||||
btAlignedObjectArray<btRigidBodyData*> m_rigidBodyData;
|
||||
btAlignedObjectArray<btTypedConstraintData2*> m_constraintData;
|
||||
btHashMap<btHashPtr,void*> m_pointerLookup;
|
||||
int m_fileVersion;
|
||||
bool m_fileOk;
|
||||
|
||||
void auto_serialize_root_level_children(TiXmlNode* pParent);
|
||||
void auto_serialize(TiXmlNode* pParent);
|
||||
|
||||
void deSerializeVector3FloatData(TiXmlNode* pParent,btAlignedObjectArray<btVector3FloatData>& vectors);
|
||||
|
||||
void fixupCollisionDataPointers(btCollisionShapeData* shapeData);
|
||||
void fixupConstraintData(btTypedConstraintData2* tcd);
|
||||
|
||||
//collision shapes data
|
||||
void deSerializeCollisionShapeData(TiXmlNode* pParent,btCollisionShapeData* colShapeData);
|
||||
void deSerializeConvexInternalShapeData(TiXmlNode* pParent);
|
||||
void deSerializeStaticPlaneShapeData(TiXmlNode* pParent);
|
||||
void deSerializeCompoundShapeData(TiXmlNode* pParent);
|
||||
void deSerializeCompoundShapeChildData(TiXmlNode* pParent);
|
||||
void deSerializeConvexHullShapeData(TiXmlNode* pParent);
|
||||
void deSerializeDynamicsWorldData(TiXmlNode* parent);
|
||||
|
||||
///bodies
|
||||
void deSerializeRigidBodyFloatData(TiXmlNode* pParent);
|
||||
|
||||
///constraints
|
||||
void deSerializeGeneric6DofConstraintData(TiXmlNode* pParent);
|
||||
|
||||
public:
|
||||
btBulletXmlWorldImporter(btDynamicsWorld* world);
|
||||
|
||||
virtual ~btBulletXmlWorldImporter();
|
||||
|
||||
bool loadFile(const char* fileName);
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_BULLET_XML_WORLD_IMPORTER_H
|
14
Extras/Serialize/BulletXmlWorldImporter/premake4.lua
Normal file
14
Extras/Serialize/BulletXmlWorldImporter/premake4.lua
Normal file
@ -0,0 +1,14 @@
|
||||
project "BulletXmlWorldImporter"
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {
|
||||
"../BulletWorldImporter",
|
||||
"../BulletFileLoader",
|
||||
"../../../src"
|
||||
}
|
||||
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
250
Extras/Serialize/BulletXmlWorldImporter/string_split.cpp
Normal file
250
Extras/Serialize/BulletXmlWorldImporter/string_split.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
//#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "string_split.h"
|
||||
|
||||
///todo: remove stl dependency
|
||||
|
||||
namespace bullet_utils
|
||||
{
|
||||
void split( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, const std::string& separator)
|
||||
{
|
||||
char** strArray = str_split(vector_str.c_str(),separator.c_str());
|
||||
int numSubStr = str_array_len(strArray);
|
||||
for (int i=0;i<numSubStr;i++)
|
||||
pieces.push_back(std::string(strArray[i]));
|
||||
str_array_free(strArray);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Append an item to a dynamically allocated array of strings. On failure,
|
||||
return NULL, in which case the original array is intact. The item
|
||||
string is dynamically copied. If the array is NULL, allocate a new
|
||||
array. Otherwise, extend the array. Make sure the array is always
|
||||
NULL-terminated. Input string might not be '\0'-terminated. */
|
||||
char **str_array_append(char **array, size_t nitems, const char *item,
|
||||
size_t itemlen)
|
||||
{
|
||||
/* Make a dynamic copy of the item. */
|
||||
char *copy;
|
||||
if (item == NULL)
|
||||
copy = NULL;
|
||||
else {
|
||||
copy = (char*)malloc(itemlen + 1);
|
||||
if (copy == NULL)
|
||||
return NULL;
|
||||
memcpy(copy, item, itemlen);
|
||||
copy[itemlen] = '\0';
|
||||
}
|
||||
|
||||
/* Extend array with one element. Except extend it by two elements,
|
||||
in case it did not yet exist. This might mean it is a teeny bit
|
||||
too big, but we don't care. */
|
||||
array = (char**)realloc(array, (nitems + 2) * sizeof(array[0]));
|
||||
if (array == NULL) {
|
||||
free(copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add copy of item to array, and return it. */
|
||||
array[nitems] = copy;
|
||||
array[nitems+1] = NULL;
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/* Free a dynamic array of dynamic strings. */
|
||||
void str_array_free(char **array)
|
||||
{
|
||||
if (array == NULL)
|
||||
return;
|
||||
for (size_t i = 0; array[i] != NULL; ++i)
|
||||
free(array[i]);
|
||||
free(array);
|
||||
}
|
||||
|
||||
|
||||
/* Split a string into substrings. Return dynamic array of dynamically
|
||||
allocated substrings, or NULL if there was an error. Caller is
|
||||
expected to free the memory, for example with str_array_free. */
|
||||
char **str_split(const char *input, const char *sep)
|
||||
{
|
||||
size_t nitems = 0;
|
||||
char **array = NULL;
|
||||
const char *start = input;
|
||||
const char *next = strstr(start, sep);
|
||||
size_t seplen = strlen(sep);
|
||||
const char *item;
|
||||
size_t itemlen;
|
||||
|
||||
for (;;) {
|
||||
next = strstr(start, sep);
|
||||
if (next == NULL) {
|
||||
/* Add the remaining string (or empty string, if input ends with
|
||||
separator. */
|
||||
char **newstr = str_array_append(array, nitems, start, strlen(start));
|
||||
if (newstr == NULL) {
|
||||
str_array_free(array);
|
||||
return NULL;
|
||||
}
|
||||
array = newstr;
|
||||
++nitems;
|
||||
break;
|
||||
} else if (next == input) {
|
||||
/* Input starts with separator. */
|
||||
item = "";
|
||||
itemlen = 0;
|
||||
} else {
|
||||
item = start;
|
||||
itemlen = next - item;
|
||||
}
|
||||
char **newstr = str_array_append(array, nitems, item, itemlen);
|
||||
if (newstr == NULL) {
|
||||
str_array_free(array);
|
||||
return NULL;
|
||||
}
|
||||
array = newstr;
|
||||
++nitems;
|
||||
start = next + seplen;
|
||||
}
|
||||
|
||||
if (nitems == 0) {
|
||||
/* Input does not contain separator at all. */
|
||||
assert(array == NULL);
|
||||
array = str_array_append(array, nitems, input, strlen(input));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/* Return length of a NULL-delimited array of strings. */
|
||||
size_t str_array_len(char **array)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; array[len] != NULL; ++len)
|
||||
continue;
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST_STRING
|
||||
|
||||
#define MAX_OUTPUT 20
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct {
|
||||
const char *input;
|
||||
const char *sep;
|
||||
char *output[MAX_OUTPUT];
|
||||
} tab[] = {
|
||||
/* Input is empty string. Output should be a list with an empty
|
||||
string. */
|
||||
{
|
||||
"",
|
||||
"and",
|
||||
{
|
||||
"",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
/* Input is exactly the separator. Output should be two empty
|
||||
strings. */
|
||||
{
|
||||
"and",
|
||||
"and",
|
||||
{
|
||||
"",
|
||||
"",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
/* Input is non-empty, but does not have separator. Output should
|
||||
be the same string. */
|
||||
{
|
||||
"foo",
|
||||
"and",
|
||||
{
|
||||
"foo",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
/* Input is non-empty, and does have separator. */
|
||||
{
|
||||
"foo bar 1 and foo bar 2",
|
||||
" and ",
|
||||
{
|
||||
"foo bar 1",
|
||||
"foo bar 2",
|
||||
NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
const int tab_len = sizeof(tab) / sizeof(tab[0]);
|
||||
bool errors;
|
||||
|
||||
errors = false;
|
||||
|
||||
for (int i = 0; i < tab_len; ++i) {
|
||||
printf("test %d\n", i);
|
||||
|
||||
char **output = str_split(tab[i].input, tab[i].sep);
|
||||
if (output == NULL) {
|
||||
fprintf(stderr, "output is NULL\n");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
size_t num_output = str_array_len(output);
|
||||
printf("num_output %lu\n", (unsigned long) num_output);
|
||||
|
||||
size_t num_correct = str_array_len(tab[i].output);
|
||||
if (num_output != num_correct) {
|
||||
fprintf(stderr, "wrong number of outputs (%lu, not %lu)\n",
|
||||
(unsigned long) num_output, (unsigned long) num_correct);
|
||||
errors = true;
|
||||
} else {
|
||||
for (size_t j = 0; j < num_output; ++j) {
|
||||
if (strcmp(tab[i].output[j], output[j]) != 0) {
|
||||
fprintf(stderr, "output[%lu] is '%s' not '%s'\n",
|
||||
(unsigned long) j, output[j], tab[i].output[j]);
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str_array_free(output);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (errors)
|
||||
return EXIT_FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif//
|
||||
|
||||
|
49
Extras/Serialize/BulletXmlWorldImporter/string_split.h
Normal file
49
Extras/Serialize/BulletXmlWorldImporter/string_split.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
///The string split C code is by Lars Wirzenius
|
||||
///See http://stackoverflow.com/questions/2531605/how-to-split-a-string-with-a-delimiter-larger-than-one-single-char
|
||||
|
||||
|
||||
#ifndef STRING_SPLIT_H
|
||||
#define STRING_SPLIT_H
|
||||
|
||||
#include <cstring>
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace bullet_utils
|
||||
{
|
||||
void split( btAlignedObjectArray<std::string>&pieces, const std::string& vector_str, const std::string& separator);
|
||||
};
|
||||
|
||||
///The string split C code is by Lars Wirzenius
|
||||
///See http://stackoverflow.com/questions/2531605/how-to-split-a-string-with-a-delimiter-larger-than-one-single-char
|
||||
|
||||
|
||||
/* Split a string into substrings. Return dynamic array of dynamically
|
||||
allocated substrings, or NULL if there was an error. Caller is
|
||||
expected to free the memory, for example with str_array_free. */
|
||||
char** str_split(const char* input, const char* sep);
|
||||
|
||||
/* Free a dynamic array of dynamic strings. */
|
||||
void str_array_free(char** array);
|
||||
|
||||
/* Return length of a NULL-delimited array of strings. */
|
||||
size_t str_array_len(char** array);
|
||||
|
||||
#endif //STRING_SPLIT_H
|
||||
|
111
Extras/Serialize/BulletXmlWorldImporter/tinystr.cpp
Normal file
111
Extras/Serialize/BulletXmlWorldImporter/tinystr.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#include "tinystr.h"
|
||||
|
||||
// Error value for find primitive
|
||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
|
||||
|
||||
|
||||
// Null rep.
|
||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
|
||||
|
||||
|
||||
void TiXmlString::reserve (size_type cap)
|
||||
{
|
||||
if (cap > capacity())
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(length(), cap);
|
||||
memcpy(tmp.start(), data(), length());
|
||||
swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
||||
{
|
||||
size_type cap = capacity();
|
||||
if (len > cap || cap > 3*(len + 8))
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(len);
|
||||
memcpy(tmp.start(), str, len);
|
||||
swap(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(start(), str, len);
|
||||
set_size(len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
||||
{
|
||||
size_type newsize = length() + len;
|
||||
if (newsize > capacity())
|
||||
{
|
||||
reserve (newsize + capacity());
|
||||
}
|
||||
memmove(finish(), str, len);
|
||||
set_size(newsize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.reserve(a.length() + b.length());
|
||||
tmp += a;
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
||||
tmp.reserve(a.length() + b_len);
|
||||
tmp += a;
|
||||
tmp.append(b, b_len);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
||||
tmp.reserve(a_len + b.length());
|
||||
tmp.append(a, a_len);
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
#endif // TIXML_USE_STL
|
305
Extras/Serialize/BulletXmlWorldImporter/tinystr.h
Normal file
305
Extras/Serialize/BulletXmlWorldImporter/tinystr.h
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#ifndef TIXML_STRING_INCLUDED
|
||||
#define TIXML_STRING_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The support for explicit isn't that universal, and it isn't really
|
||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
||||
used. Be nice to old compilers and macro it here:
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#else
|
||||
#define TIXML_EXPLICIT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
TiXmlString is an emulation of a subset of the std::string template.
|
||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||||
Only the member functions relevant to the TinyXML project have been implemented.
|
||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||||
*/
|
||||
class TiXmlString
|
||||
{
|
||||
public :
|
||||
// The size type used
|
||||
typedef size_t size_type;
|
||||
|
||||
// Error value for find primitive
|
||||
static const size_type npos; // = -1;
|
||||
|
||||
|
||||
// TiXmlString empty constructor
|
||||
TiXmlString () : rep_(&nullrep_)
|
||||
{
|
||||
}
|
||||
|
||||
// TiXmlString copy constructor
|
||||
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
||||
{
|
||||
init(copy.length());
|
||||
memcpy(start(), copy.data(), length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
||||
{
|
||||
init( static_cast<size_type>( strlen(copy) ));
|
||||
memcpy(start(), copy, length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
||||
{
|
||||
init(len);
|
||||
memcpy(start(), str, len);
|
||||
}
|
||||
|
||||
// TiXmlString destructor
|
||||
~TiXmlString ()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
}
|
||||
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const char * suffix)
|
||||
{
|
||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (char single)
|
||||
{
|
||||
return append(&single, 1);
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const TiXmlString & suffix)
|
||||
{
|
||||
return append(suffix.data(), suffix.length());
|
||||
}
|
||||
|
||||
|
||||
// Convert a TiXmlString into a null-terminated char *
|
||||
const char * c_str () const { return rep_->str; }
|
||||
|
||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
||||
const char * data () const { return rep_->str; }
|
||||
|
||||
// Return the length of a TiXmlString
|
||||
size_type length () const { return rep_->size; }
|
||||
|
||||
// Alias for length()
|
||||
size_type size () const { return rep_->size; }
|
||||
|
||||
// Checks if a TiXmlString is empty
|
||||
bool empty () const { return rep_->size == 0; }
|
||||
|
||||
// Return capacity of string
|
||||
size_type capacity () const { return rep_->capacity; }
|
||||
|
||||
|
||||
// single char extraction
|
||||
const char& at (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// [] operator
|
||||
char& operator [] (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// find a char in a string. Return TiXmlString::npos if not found
|
||||
size_type find (char lookup) const
|
||||
{
|
||||
return find(lookup, 0);
|
||||
}
|
||||
|
||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||||
size_type find (char tofind, size_type offset) const
|
||||
{
|
||||
if (offset >= length()) return npos;
|
||||
|
||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
//Lee:
|
||||
//The original was just too strange, though correct:
|
||||
// TiXmlString().swap(*this);
|
||||
//Instead use the quit & re-init:
|
||||
quit();
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
||||
*/
|
||||
void reserve (size_type cap);
|
||||
|
||||
TiXmlString& assign (const char* str, size_type len);
|
||||
|
||||
TiXmlString& append (const char* str, size_type len);
|
||||
|
||||
void swap (TiXmlString& other)
|
||||
{
|
||||
Rep* r = rep_;
|
||||
rep_ = other.rep_;
|
||||
other.rep_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init(size_type sz) { init(sz, sz); }
|
||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||||
char* start() const { return rep_->str; }
|
||||
char* finish() const { return rep_->str + rep_->size; }
|
||||
|
||||
struct Rep
|
||||
{
|
||||
size_type size, capacity;
|
||||
char str[1];
|
||||
};
|
||||
|
||||
void init(size_type sz, size_type cap)
|
||||
{
|
||||
if (cap)
|
||||
{
|
||||
// Lee: the original form:
|
||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||||
// doesn't work in some cases of new being overloaded. Switching
|
||||
// to the normal allocation, although use an 'int' for systems
|
||||
// that are overly picky about structure alignment.
|
||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||||
|
||||
rep_->str[ rep_->size = sz ] = '\0';
|
||||
rep_->capacity = cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
rep_ = &nullrep_;
|
||||
}
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (rep_ != &nullrep_)
|
||||
{
|
||||
// The rep_ is really an array of ints. (see the allocator, above).
|
||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||||
}
|
||||
}
|
||||
|
||||
Rep * rep_;
|
||||
static Rep nullrep_;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return ( a.length() == b.length() ) // optimization on some platforms
|
||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||||
}
|
||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||||
|
||||
|
||||
/*
|
||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||||
Only the operators that we need for TinyXML have been developped.
|
||||
*/
|
||||
class TiXmlOutStream : public TiXmlString
|
||||
{
|
||||
public :
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const char * in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif // TIXML_STRING_INCLUDED
|
||||
#endif // TIXML_USE_STL
|
1886
Extras/Serialize/BulletXmlWorldImporter/tinyxml.cpp
Normal file
1886
Extras/Serialize/BulletXmlWorldImporter/tinyxml.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1805
Extras/Serialize/BulletXmlWorldImporter/tinyxml.h
Normal file
1805
Extras/Serialize/BulletXmlWorldImporter/tinyxml.h
Normal file
File diff suppressed because it is too large
Load Diff
52
Extras/Serialize/BulletXmlWorldImporter/tinyxmlerror.cpp
Normal file
52
Extras/Serialize/BulletXmlWorldImporter/tinyxmlerror.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
// The goal of the seperate error file is to make the first
|
||||
// step towards localization. tinyxml (currently) only supports
|
||||
// english error messages, but the could now be translated.
|
||||
//
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
"Error reading Attributes.",
|
||||
"Error: empty tag.",
|
||||
"Error reading end tag.",
|
||||
"Error parsing Unknown.",
|
||||
"Error parsing Comment.",
|
||||
"Error parsing Declaration.",
|
||||
"Error document empty.",
|
||||
"Error null (0) or unexpected EOF found in input stream.",
|
||||
"Error parsing CDATA.",
|
||||
"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
|
||||
};
|
1638
Extras/Serialize/BulletXmlWorldImporter/tinyxmlparser.cpp
Normal file
1638
Extras/Serialize/BulletXmlWorldImporter/tinyxmlparser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
20
Extras/Serialize/CMakeLists.txt
Normal file
20
Extras/Serialize/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
IF (BUILD_BLEND_DEMO OR INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
SUBDIRS(BlenderSerialize )
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
|
||||
# makesdna and HeaderGenerator are for advanced use only
|
||||
# makesdna can re-generate the binary DNA representing the Bullet serialization structures
|
||||
# Be very careful modifying any of this, otherwise the .bullet format becomes incompatible
|
||||
|
||||
SUBDIRS ( BulletFileLoader BulletXmlWorldImporter BulletWorldImporter HeaderGenerator makesdna)
|
||||
|
||||
ELSE(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
|
||||
SUBDIRS ( BulletFileLoader BulletXmlWorldImporter BulletWorldImporter )
|
||||
|
||||
ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
|
32
Extras/Serialize/HeaderGenerator/CMakeLists.txt
Normal file
32
Extras/Serialize/HeaderGenerator/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
###############################################################################
|
||||
PROJECT(GEN)
|
||||
FILE(GLOB cpp_SRC "*.cpp")
|
||||
FILE(GLOB h_SRC "*.h")
|
||||
|
||||
|
||||
SET(includes
|
||||
.
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BlenderSerialize
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
||||
LINK_LIBRARIES(
|
||||
BulletFileLoader BlenderSerialize LinearMath
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(${includes})
|
||||
|
||||
SET(Main_LIBS LinearMath)
|
||||
|
||||
ADD_EXECUTABLE(HeaderGenerator ${cpp_SRC} ${h_SRC})
|
||||
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET HeaderGenerator
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/HeaderGenerator/createDnaString.bat ${CMAKE_CURRENT_BINARY_DIR}/createDnaString.bat
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/HeaderGenerator/bulletGenerate.py ${CMAKE_CURRENT_BINARY_DIR}/bulletGenerate.py
|
||||
)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
464
Extras/Serialize/HeaderGenerator/apiGen.cpp
Normal file
464
Extras/Serialize/HeaderGenerator/apiGen.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
/* Copyright (C) 2006 Charlie C
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <sstream>
|
||||
#include "bDNA.h"
|
||||
#include "bBlenderFile.h"
|
||||
#include "btBulletFile.h"
|
||||
#include "bCommon.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
bool isBulletFile = false;
|
||||
|
||||
using namespace bParse;
|
||||
typedef std::string bString;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
typedef std::map<bString, bString> bStringMap;
|
||||
typedef std::vector<class bVariable> bVariableList;
|
||||
typedef std::vector<bString> bStringList;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static FILE *dump = 0;
|
||||
static bDNA *mDNA =0;
|
||||
static bStringMap mStructs;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class bVariable
|
||||
{
|
||||
public:
|
||||
bVariable();
|
||||
~bVariable();
|
||||
|
||||
|
||||
bString dataType;
|
||||
bString variableName;
|
||||
|
||||
|
||||
bString functionName;
|
||||
bString classCtor;
|
||||
|
||||
bString memberVariable;
|
||||
bString memberDataType;
|
||||
bString functionArgs;
|
||||
|
||||
|
||||
void initialize(bString dataType, bString variable, bStringMap refDataTable);
|
||||
|
||||
bool isPtr;
|
||||
bool isFunctionPtr;
|
||||
bool isPtrToPtr;
|
||||
bool isArray;
|
||||
bool isCharArray;
|
||||
bool isListBase;
|
||||
bool isPadding;
|
||||
bool isCommentedOut;
|
||||
bool isGeneratedType;
|
||||
bool isbString;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool dataTypeStandard(bString dataType)
|
||||
{
|
||||
if (dataType == "char")
|
||||
return true;
|
||||
if (dataType == "short")
|
||||
return true;
|
||||
if (dataType == "int")
|
||||
return true;
|
||||
if (dataType == "long")
|
||||
return true;
|
||||
if (dataType == "float")
|
||||
return true;
|
||||
if (dataType == "double")
|
||||
return true;
|
||||
if (dataType == "void")
|
||||
return true;
|
||||
if (dataType == "btScalar")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void writeTemplate(short *structData)
|
||||
{
|
||||
bString type = mDNA->getType(structData[0]);
|
||||
bString className=type;
|
||||
bString prefix = isBulletFile? "bullet_" : "blender_";
|
||||
|
||||
int thisLen = structData[1];
|
||||
structData+=2;
|
||||
|
||||
bString fileName = prefix+type;
|
||||
|
||||
bVariableList dataTypes;
|
||||
bStringMap includeFiles;
|
||||
|
||||
|
||||
for (int dataVal =0; dataVal<thisLen; dataVal++, structData+=2)
|
||||
{
|
||||
bString dataType = mDNA->getType(structData[0]);
|
||||
bString dataName = mDNA->getName(structData[1]);
|
||||
{
|
||||
bString newDataType = "";
|
||||
bString newDataName = "";
|
||||
|
||||
bStringMap::iterator addB = mStructs.find(dataType);
|
||||
if (addB != mStructs.end())
|
||||
{
|
||||
newDataType = addB->second;
|
||||
newDataName = dataName;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (dataTypeStandard(dataType))
|
||||
{
|
||||
newDataType = dataType;
|
||||
newDataName = dataName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unresolved
|
||||
// set it to an empty struct
|
||||
// if it's not a ptr generate an error
|
||||
newDataType = "bInvalidHandle";
|
||||
newDataName = dataName;
|
||||
|
||||
if (dataName[0] != '*')
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!newDataType.empty() && !newDataName.empty())
|
||||
{
|
||||
bVariable var = bVariable();
|
||||
var.initialize(newDataType, newDataName, mStructs);
|
||||
dataTypes.push_back(var);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bStringMap::iterator include = mStructs.find(dataType);
|
||||
if (include != mStructs.end())
|
||||
{
|
||||
if (dataName[0] != '*')
|
||||
{
|
||||
if (includeFiles.find(dataType)== includeFiles.end())
|
||||
{
|
||||
includeFiles[dataType]=prefix+dataType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(dump, "###############################################################\n");
|
||||
fprintf(dump, "%s = bStructClass()\n", fileName.c_str());
|
||||
fprintf(dump, "%s.name = '%s'\n", fileName.c_str(), className.c_str());
|
||||
fprintf(dump, "%s.filename = '%s'\n", fileName.c_str(), fileName.c_str());
|
||||
|
||||
bVariableList::iterator vars = dataTypes.begin();
|
||||
while (vars!= dataTypes.end())
|
||||
{
|
||||
fprintf(dump, "%s.dataTypes.append('%s %s')\n", fileName.c_str(), vars->dataType.c_str(), vars->variableName.c_str());
|
||||
vars++;
|
||||
}
|
||||
|
||||
bStringMap::iterator inc = includeFiles.begin();
|
||||
while (inc != includeFiles.end())
|
||||
{
|
||||
fprintf(dump, "%s.includes.append('%s.h')\n", fileName.c_str(), inc->second.c_str());
|
||||
inc++;
|
||||
}
|
||||
fprintf(dump, "DataTypeList.append(%s)\n", fileName.c_str());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
char data[]={
|
||||
"\n"
|
||||
"class bStructClass:\n"
|
||||
" def __init__(self):\n"
|
||||
" self.name = \"\";\n"
|
||||
" self.filename = \"\";\n"
|
||||
" self.includes = []\n"
|
||||
" self.dataTypes = []\n"
|
||||
"\n\n"
|
||||
"DataTypeList = []\n"
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
using namespace bParse;
|
||||
dump = fopen("dump.py", "w");
|
||||
|
||||
if (!dump) return 0;
|
||||
fprintf(dump, "%s\n", data);
|
||||
|
||||
|
||||
char* filename = "../../../Demos/SerializeDemo/testFile.bullet";
|
||||
|
||||
if (argc==2)
|
||||
filename = argv[1];
|
||||
|
||||
bString fileStr(filename);
|
||||
bString extension(".bullet");
|
||||
|
||||
int index2 = fileStr.find(extension);
|
||||
if (index2>=0)
|
||||
isBulletFile=true;
|
||||
|
||||
|
||||
FILE* fp = fopen (filename,"rb");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
printf("error: file not found %s\n",filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char* memBuf = 0;
|
||||
int len = 0;
|
||||
|
||||
long currentpos = ftell(fp); /* save current cursor position */
|
||||
long newpos;
|
||||
int bytesRead;
|
||||
|
||||
fseek(fp, 0, SEEK_END); /* seek to end */
|
||||
newpos = ftell(fp); /* find position of end -- this is the length */
|
||||
fseek(fp, currentpos, SEEK_SET); /* restore previous cursor position */
|
||||
|
||||
len = newpos;
|
||||
|
||||
memBuf = (char*)malloc(len);
|
||||
bytesRead = fread(memBuf,len,1,fp);
|
||||
|
||||
bool swap = false;
|
||||
|
||||
|
||||
if (isBulletFile)
|
||||
{
|
||||
btBulletFile f(memBuf,len);
|
||||
swap = (f.getFlags() & FD_ENDIAN_SWAP)!=0;
|
||||
} else
|
||||
{
|
||||
bBlenderFile f(memBuf,len);
|
||||
swap = (f.getFlags() & FD_ENDIAN_SWAP)!=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char *blenderData = memBuf;
|
||||
int sdnaPos=0;
|
||||
int mDataStart = 12;
|
||||
|
||||
char *tempBuffer = blenderData;
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
// looking for the data's starting position
|
||||
// and the start of SDNA decls
|
||||
|
||||
if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
|
||||
mDataStart = i;
|
||||
if (!sdnaPos && strncmp(tempBuffer, "SDNA", 4)==0)
|
||||
sdnaPos = i;
|
||||
|
||||
if (mDataStart && sdnaPos) break;
|
||||
tempBuffer++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FILE* fpdna = fopen("dnaString.txt","w");
|
||||
char buf[1024];
|
||||
|
||||
for (int i=0;i<len-sdnaPos;i++)
|
||||
{
|
||||
int dnaval = (memBuf+sdnaPos)[i];
|
||||
|
||||
if ((i%32)==0)
|
||||
{
|
||||
sprintf(buf,"%d,\n",dnaval);
|
||||
|
||||
} else
|
||||
{
|
||||
sprintf(buf,"%d,",dnaval);
|
||||
}
|
||||
|
||||
|
||||
fwrite(buf,strlen(buf),1,fpdna);
|
||||
}
|
||||
|
||||
fclose(fpdna);
|
||||
|
||||
|
||||
|
||||
mDNA = new bDNA();
|
||||
//mDNA->initMemory();
|
||||
|
||||
mDNA->init(memBuf+sdnaPos, len-sdnaPos, swap);
|
||||
|
||||
|
||||
for (int i=0; i<mDNA->getNumStructs(); i++)
|
||||
{
|
||||
short *structData = mDNA->getStruct(i);
|
||||
bString type = mDNA->getType(structData[0]);
|
||||
|
||||
bString className = type;
|
||||
mStructs[type]=className;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<mDNA->getNumStructs(); i++)
|
||||
{
|
||||
short *structData = mDNA->getStruct(i);
|
||||
writeTemplate(structData);
|
||||
}
|
||||
|
||||
delete mDNA;
|
||||
fclose(dump);
|
||||
return 0;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int _getArraySize(char* str)
|
||||
{
|
||||
int a, mul=1;
|
||||
char stri[100], *cp=0;
|
||||
int len = (int)strlen(str);
|
||||
|
||||
memcpy(stri, str, len+1);
|
||||
for (a=0; a<len; a++)
|
||||
{
|
||||
if (str[a]== '[')
|
||||
cp= &(stri[a+1]);
|
||||
else if ( str[a]==']' && cp)
|
||||
{
|
||||
stri[a]= 0;
|
||||
mul*= atoi(cp);
|
||||
}
|
||||
}
|
||||
return mul;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bVariable::bVariable()
|
||||
: dataType("invalid"),
|
||||
variableName("invalid"),
|
||||
functionName(""),
|
||||
classCtor(""),
|
||||
memberVariable(""),
|
||||
memberDataType(""),
|
||||
functionArgs(""),
|
||||
isPtr(false),
|
||||
isFunctionPtr(false),
|
||||
isPtrToPtr(false),
|
||||
isArray(false),
|
||||
isCharArray(false),
|
||||
isListBase(false),
|
||||
isPadding(false),
|
||||
isCommentedOut(false),
|
||||
isGeneratedType(false),
|
||||
isbString(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bVariable::~bVariable()
|
||||
{
|
||||
dataType.clear();
|
||||
variableName.clear();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void bVariable::initialize(bString type, bString variable, bStringMap refDataTable)
|
||||
{
|
||||
dataType = type;
|
||||
variableName = variable;
|
||||
|
||||
if (variableName[0] == '*')
|
||||
{
|
||||
isPtr = true;
|
||||
if (variableName[1] == '*')
|
||||
isPtrToPtr = true;
|
||||
}
|
||||
if (variableName[0] == '(')
|
||||
if (variableName[1] == '*')
|
||||
isFunctionPtr = true;
|
||||
|
||||
if (variableName[variableName.size()-1] == ']')
|
||||
{
|
||||
isArray = true;
|
||||
if (type == "char")
|
||||
isCharArray = true;
|
||||
}
|
||||
|
||||
if (type == "ListBase")
|
||||
isListBase = true;
|
||||
|
||||
if (variableName[0] == 'p')
|
||||
{
|
||||
bString sub = variableName.substr(0,3);
|
||||
if (sub == "pad")
|
||||
isPadding = true;
|
||||
}
|
||||
if (dataType[0] == '/' && dataType[1] == '/')
|
||||
isCommentedOut = true;
|
||||
|
||||
|
||||
if (refDataTable.find(dataType) != refDataTable.end())
|
||||
isGeneratedType = true;
|
||||
|
||||
if (!isBulletFile)
|
||||
{
|
||||
// replace valid float arrays
|
||||
if (dataType == "float" && isArray)
|
||||
{
|
||||
int size = _getArraySize((char*)variableName.c_str());
|
||||
if (size==3)
|
||||
{
|
||||
dataType = "vec3f";
|
||||
variableName = variableName.substr(0, variableName.find_first_of("["));
|
||||
}
|
||||
if (size==4)
|
||||
{
|
||||
dataType = "vec4f";
|
||||
variableName = variableName.substr(0, variableName.find_first_of("["));
|
||||
}
|
||||
}
|
||||
}
|
||||
memberDataType = dataType;
|
||||
functionArgs = variableName;
|
||||
}
|
||||
|
||||
// eof
|
111
Extras/Serialize/HeaderGenerator/blenderGenerate.py
Normal file
111
Extras/Serialize/HeaderGenerator/blenderGenerate.py
Normal file
@ -0,0 +1,111 @@
|
||||
import dump
|
||||
|
||||
|
||||
header = """/* Copyright (C) 2006 Charlie C
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// Auto generated from makesdna dna.c
|
||||
"""
|
||||
|
||||
dtList = dump.DataTypeList
|
||||
|
||||
out = "../BlenderSerialize/autogenerated/"
|
||||
spaces = 4
|
||||
|
||||
def addSpaces(file, space):
|
||||
for i in range(0, space):
|
||||
file.write(" ")
|
||||
|
||||
def write(file, spaces, string):
|
||||
addSpaces(file, spaces)
|
||||
file.write(string)
|
||||
|
||||
###################################################################################
|
||||
blender = open(out+"blender.h", 'w')
|
||||
blender.write(header)
|
||||
blender.write("#ifndef __BLENDER_H__\n")
|
||||
blender.write("#define __BLENDER_H__\n")
|
||||
for dt in dtList:
|
||||
blender.write("#include \"%s.h\"\n"%dt.filename)
|
||||
|
||||
blender.write("#endif//__BLENDER_H__")
|
||||
blender.close()
|
||||
|
||||
###################################################################################
|
||||
blenderC = open(out+"blender_Common.h", 'w')
|
||||
blenderC.write(header)
|
||||
blenderC.write("#ifndef __BLENDERCOMMON_H__\n")
|
||||
blenderC.write("#define __BLENDERCOMMON_H__\n")
|
||||
|
||||
strUnRes = """
|
||||
// put an empty struct in the case
|
||||
typedef struct bInvalidHandle {
|
||||
int unused;
|
||||
}bInvalidHandle;
|
||||
|
||||
"""
|
||||
blenderC.write(strUnRes)
|
||||
|
||||
blenderC.write("namespace Blender {\n")
|
||||
for dt in dtList:
|
||||
write(blenderC, 4, "class %s;\n"%dt.name)
|
||||
|
||||
blenderC.write("}\n")
|
||||
blenderC.write("#endif//__BLENDERCOMMON_H__")
|
||||
blenderC.close()
|
||||
|
||||
|
||||
for dt in dtList:
|
||||
fp = open(out+dt.filename+".h", 'w')
|
||||
|
||||
fp.write(header)
|
||||
strUpper = dt.filename.upper()
|
||||
|
||||
fp.write("#ifndef __%s__H__\n"%strUpper)
|
||||
fp.write("#define __%s__H__\n"%strUpper)
|
||||
fp.write("\n\n")
|
||||
|
||||
|
||||
fp.write("// -------------------------------------------------- //\n")
|
||||
fp.write("#include \"blender_Common.h\"\n")
|
||||
|
||||
for i in dt.includes:
|
||||
fp.write("#include \"%s\"\n"%i)
|
||||
|
||||
fp.write("\nnamespace Blender {\n")
|
||||
fp.write("\n\n")
|
||||
|
||||
addSpaces(fp,4)
|
||||
fp.write("// ---------------------------------------------- //\n")
|
||||
|
||||
|
||||
write(fp, 4, "class %s\n"%dt.name)
|
||||
|
||||
write(fp, 4, "{\n")
|
||||
write(fp, 4, "public:\n")
|
||||
for i in dt.dataTypes:
|
||||
write(fp, 8, i+";\n")
|
||||
|
||||
|
||||
write(fp, 4, "};\n")
|
||||
fp.write("}\n")
|
||||
fp.write("\n\n")
|
||||
fp.write("#endif//__%s__H__\n"%strUpper)
|
||||
fp.close()
|
||||
|
||||
|
83
Extras/Serialize/HeaderGenerator/bulletGenerate.py
Normal file
83
Extras/Serialize/HeaderGenerator/bulletGenerate.py
Normal file
@ -0,0 +1,83 @@
|
||||
import dump
|
||||
|
||||
|
||||
header = """/* Copyright (C) 2011 Erwin Coumans & Charlie C
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py
|
||||
"""
|
||||
|
||||
dtList = dump.DataTypeList
|
||||
|
||||
out = "autogenerated/"
|
||||
spaces = 4
|
||||
|
||||
def addSpaces(file, space):
|
||||
for i in range(0, space):
|
||||
file.write(" ")
|
||||
|
||||
def write(file, spaces, string):
|
||||
addSpaces(file, spaces)
|
||||
file.write(string)
|
||||
|
||||
###################################################################################
|
||||
blender = open(out+"bullet.h", 'w')
|
||||
blender.write(header)
|
||||
blender.write("#ifndef __BULLET_H__\n")
|
||||
blender.write("#define __BULLET_H__\n")
|
||||
#for dt in dtList:
|
||||
# blender.write("struct %s;\n"%dt.filename)
|
||||
|
||||
|
||||
###################################################################################
|
||||
|
||||
blender.write("namespace Bullet {\n")
|
||||
|
||||
strUnRes = """
|
||||
// put an empty struct in the case
|
||||
typedef struct bInvalidHandle {
|
||||
int unused;
|
||||
}bInvalidHandle;
|
||||
|
||||
"""
|
||||
blender.write(strUnRes)
|
||||
|
||||
for dt in dtList:
|
||||
write(blender, 4, "class %s;\n"%dt.name)
|
||||
|
||||
|
||||
for dt in dtList:
|
||||
|
||||
strUpper = dt.filename.upper()
|
||||
|
||||
blender.write("// -------------------------------------------------- //\n")
|
||||
|
||||
write(blender, 4, "class %s\n"%dt.name)
|
||||
|
||||
write(blender, 4, "{\n")
|
||||
write(blender, 4, "public:\n")
|
||||
for i in dt.dataTypes:
|
||||
write(blender, 8, i+";\n")
|
||||
|
||||
write(blender, 4, "};\n")
|
||||
|
||||
blender.write("\n\n")
|
||||
|
||||
blender.write("}\n")
|
||||
blender.write("#endif//__BULLET_H__")
|
||||
blender.close()
|
7
Extras/Serialize/HeaderGenerator/createDnaString.bat
Normal file
7
Extras/Serialize/HeaderGenerator/createDnaString.bat
Normal file
@ -0,0 +1,7 @@
|
||||
delete dnaString.txt
|
||||
|
||||
mkdir autogenerated
|
||||
|
||||
Debug\HeaderGenerator.exe
|
||||
|
||||
python bulletGenerate.py
|
345
Extras/Serialize/ReadBulletSample/BulletDataExtractor.cpp
Normal file
345
Extras/Serialize/ReadBulletSample/BulletDataExtractor.cpp
Normal file
@ -0,0 +1,345 @@
|
||||
|
||||
#include "BulletDataExtractor.h"
|
||||
#include "../BulletFileLoader/btBulletFile.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
///work-in-progress
|
||||
///This ReadBulletSample is kept as simple as possible without dependencies to the Bullet SDK.
|
||||
///It can be used to load .bullet data for other physics SDKs
|
||||
///For a more complete example how to load and convert Bullet data using the Bullet SDK check out
|
||||
///the Bullet/Demos/SerializeDemo and Bullet/Serialize/BulletWorldImporter
|
||||
|
||||
using namespace Bullet;
|
||||
|
||||
enum LocalBroadphaseNativeTypes
|
||||
{
|
||||
// polyhedral convex shapes
|
||||
BOX_SHAPE_PROXYTYPE,
|
||||
TRIANGLE_SHAPE_PROXYTYPE,
|
||||
TETRAHEDRAL_SHAPE_PROXYTYPE,
|
||||
CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
|
||||
CONVEX_HULL_SHAPE_PROXYTYPE,
|
||||
CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
|
||||
CUSTOM_POLYHEDRAL_SHAPE_TYPE,
|
||||
//implicit convex shapes
|
||||
IMPLICIT_CONVEX_SHAPES_START_HERE,
|
||||
SPHERE_SHAPE_PROXYTYPE,
|
||||
MULTI_SPHERE_SHAPE_PROXYTYPE,
|
||||
CAPSULE_SHAPE_PROXYTYPE,
|
||||
CONE_SHAPE_PROXYTYPE,
|
||||
CONVEX_SHAPE_PROXYTYPE,
|
||||
CYLINDER_SHAPE_PROXYTYPE,
|
||||
UNIFORM_SCALING_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
|
||||
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
|
||||
BOX_2D_SHAPE_PROXYTYPE,
|
||||
CONVEX_2D_SHAPE_PROXYTYPE,
|
||||
CUSTOM_CONVEX_SHAPE_TYPE,
|
||||
//concave shapes
|
||||
CONCAVE_SHAPES_START_HERE,
|
||||
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
||||
TRIANGLE_MESH_SHAPE_PROXYTYPE,
|
||||
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
|
||||
///used for demo integration FAST/Swift collision library and Bullet
|
||||
FAST_CONCAVE_MESH_PROXYTYPE,
|
||||
//terrain
|
||||
TERRAIN_SHAPE_PROXYTYPE,
|
||||
///Used for GIMPACT Trimesh integration
|
||||
GIMPACT_SHAPE_PROXYTYPE,
|
||||
///Multimaterial mesh
|
||||
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
|
||||
|
||||
EMPTY_SHAPE_PROXYTYPE,
|
||||
STATIC_PLANE_PROXYTYPE,
|
||||
CUSTOM_CONCAVE_SHAPE_TYPE,
|
||||
CONCAVE_SHAPES_END_HERE,
|
||||
|
||||
COMPOUND_SHAPE_PROXYTYPE,
|
||||
|
||||
SOFTBODY_SHAPE_PROXYTYPE,
|
||||
HFFLUID_SHAPE_PROXYTYPE,
|
||||
HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
|
||||
INVALID_SHAPE_PROXYTYPE,
|
||||
|
||||
MAX_BROADPHASE_COLLISION_TYPES
|
||||
|
||||
};
|
||||
|
||||
btBulletDataExtractor::btBulletDataExtractor()
|
||||
{
|
||||
}
|
||||
|
||||
btBulletDataExtractor::~btBulletDataExtractor()
|
||||
{
|
||||
}
|
||||
|
||||
void btBulletDataExtractor::convertAllObjects(bParse::btBulletFile* bulletFile2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
|
||||
{
|
||||
btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
|
||||
if (shapeData->m_name)
|
||||
printf("converting shape %s\n", shapeData->m_name);
|
||||
void* shape = convertCollisionShape(shapeData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* btBulletDataExtractor::convertCollisionShape( btCollisionShapeData* shapeData )
|
||||
{
|
||||
void* shape = 0;
|
||||
|
||||
switch (shapeData->m_shapeType)
|
||||
{
|
||||
case STATIC_PLANE_PROXYTYPE:
|
||||
{
|
||||
btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
|
||||
void* shape = createPlaneShape(planeData->m_planeNormal,planeData->m_planeConstant, planeData->m_localScaling);
|
||||
break;
|
||||
}
|
||||
|
||||
case CYLINDER_SHAPE_PROXYTYPE:
|
||||
case CAPSULE_SHAPE_PROXYTYPE:
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
case SPHERE_SHAPE_PROXYTYPE:
|
||||
case MULTI_SPHERE_SHAPE_PROXYTYPE:
|
||||
case CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
|
||||
|
||||
switch (shapeData->m_shapeType)
|
||||
{
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
{
|
||||
shape = createBoxShape(bsd->m_implicitShapeDimensions, bsd->m_localScaling,bsd->m_collisionMargin);
|
||||
break;
|
||||
}
|
||||
case SPHERE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
shape = createSphereShape(bsd->m_implicitShapeDimensions.m_floats[0],bsd->m_localScaling, bsd->m_collisionMargin);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case CAPSULE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
|
||||
switch (capData->m_upAxis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
shape = createCapsuleShapeX(implicitShapeDimensions.getY(),2*implicitShapeDimensions.getX());
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
shape = createCapsuleShapeY(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getY());
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
shape = createCapsuleShapeZ(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getZ());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("error: wrong up axis for btCapsuleShape\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case CYLINDER_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData;
|
||||
btVector3 halfExtents = implicitShapeDimensions+margin;
|
||||
switch (cylData->m_upAxis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX());
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY());
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("unknown Cylinder up axis\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case MULTI_SPHERE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
|
||||
int numSpheres = mss->m_localPositionArraySize;
|
||||
int i;
|
||||
for ( i=0;i<numSpheres;i++)
|
||||
{
|
||||
tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
|
||||
radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
|
||||
}
|
||||
shape = new btMultiSphereShape(&tmpPos[0],&radii[0],numSpheres);
|
||||
break;
|
||||
}
|
||||
case CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
|
||||
int numPoints = convexData->m_numUnscaledPoints;
|
||||
|
||||
btAlignedObjectArray<btVector3> tmpPoints;
|
||||
tmpPoints.resize(numPoints);
|
||||
int i;
|
||||
for ( i=0;i<numPoints;i++)
|
||||
{
|
||||
if (convexData->m_unscaledPointsFloatPtr)
|
||||
tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
|
||||
if (convexData->m_unscaledPointsDoublePtr)
|
||||
tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
|
||||
}
|
||||
shape = createConvexHullShape();
|
||||
|
||||
return shape;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
|
||||
btTriangleIndexVertexArray* meshInterface = createMeshInterface(trimesh->m_meshInterface);
|
||||
if (!meshInterface->getNumSubParts())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
|
||||
meshInterface->setScaling(scaling);
|
||||
|
||||
|
||||
btOptimizedBvh* bvh = 0;
|
||||
|
||||
btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh);
|
||||
trimeshShape->setMargin(trimesh->m_collisionMargin);
|
||||
shape = trimeshShape;
|
||||
|
||||
if (trimesh->m_triangleInfoMap)
|
||||
{
|
||||
btTriangleInfoMap* map = createTriangleInfoMap();
|
||||
map->deSerialize(*trimesh->m_triangleInfoMap);
|
||||
trimeshShape->setTriangleInfoMap(map);
|
||||
|
||||
#ifdef USE_INTERNAL_EDGE_UTILITY
|
||||
gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
|
||||
#endif //USE_INTERNAL_EDGE_UTILITY
|
||||
|
||||
}
|
||||
|
||||
//printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
|
||||
break;
|
||||
}
|
||||
case COMPOUND_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
|
||||
btCompoundShape* compoundShape = createCompoundShape();
|
||||
|
||||
|
||||
btAlignedObjectArray<btCollisionShape*> childShapes;
|
||||
for (int i=0;i<compoundData->m_numChildShapes;i++)
|
||||
{
|
||||
btCollisionShape* childShape = convertCollisionShape(compoundData->m_childShapePtr[i].m_childShape);
|
||||
if (childShape)
|
||||
{
|
||||
btTransform localTransform;
|
||||
localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
|
||||
compoundShape->addChildShape(localTransform,childShape);
|
||||
} else
|
||||
{
|
||||
printf("error: couldn't create childShape for compoundShape\n");
|
||||
}
|
||||
|
||||
}
|
||||
shape = compoundShape;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GIMPACT_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData;
|
||||
if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
|
||||
{
|
||||
btTriangleIndexVertexArray* meshInterface = createMeshInterface(gimpactData->m_meshInterface);
|
||||
btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
|
||||
btVector3 localScaling;
|
||||
localScaling.deSerializeFloat(gimpactData->m_localScaling);
|
||||
gimpactShape->setLocalScaling(localScaling);
|
||||
gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
|
||||
gimpactShape->updateBound();
|
||||
shape = gimpactShape;
|
||||
} else
|
||||
{
|
||||
printf("unsupported gimpact sub type\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOFTBODY_SHAPE_PROXYTYPE:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
printf("unsupported shape type (%d)\n",shapeData->m_shapeType);
|
||||
}
|
||||
}
|
||||
|
||||
return shape;
|
||||
|
||||
}
|
||||
|
||||
void* btBulletDataExtractor::createBoxShape( const Bullet::btVector3FloatData& halfDimensions, const Bullet::btVector3FloatData& localScaling, float collisionMargin)
|
||||
{
|
||||
printf("createBoxShape with halfDimensions %f,%f,%f\n",halfDimensions.m_floats[0], halfDimensions.m_floats[1],halfDimensions.m_floats[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* btBulletDataExtractor::createSphereShape( float radius, const Bullet::btVector3FloatData& localScaling, float collisionMargin)
|
||||
{
|
||||
printf("createSphereShape with radius %f\n",radius);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void* btBulletDataExtractor::createPlaneShape( const btVector3FloatData& planeNormal, float planeConstant, const Bullet::btVector3FloatData& localScaling)
|
||||
{
|
||||
printf("createPlaneShape with normal %f,%f,%f and planeConstant\n",planeNormal.m_floats[0], planeNormal.m_floats[1],planeNormal.m_floats[2],planeConstant);
|
||||
return 0;
|
||||
}
|
||||
|
32
Extras/Serialize/ReadBulletSample/BulletDataExtractor.h
Normal file
32
Extras/Serialize/ReadBulletSample/BulletDataExtractor.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef BULLET_DATA_EXTRACTOR_H
|
||||
#define BULLET_DATA_EXTRACTOR_H
|
||||
|
||||
|
||||
#include "../BulletFileLoader/autogenerated/bullet.h"
|
||||
|
||||
namespace bParse
|
||||
{
|
||||
class btBulletFile;
|
||||
};
|
||||
|
||||
class btBulletDataExtractor
|
||||
{
|
||||
public:
|
||||
|
||||
btBulletDataExtractor();
|
||||
|
||||
virtual ~btBulletDataExtractor();
|
||||
|
||||
virtual void convertAllObjects(bParse::btBulletFile* bulletFile);
|
||||
|
||||
virtual void* convertCollisionShape( Bullet::btCollisionShapeData* shapeData );
|
||||
|
||||
virtual void* createPlaneShape( const Bullet::btVector3FloatData& planeNormal, float planeConstant, const Bullet::btVector3FloatData& localScaling);
|
||||
|
||||
virtual void* createBoxShape( const Bullet::btVector3FloatData& halfDimensions, const Bullet::btVector3FloatData& localScaling, float collisionMargin);
|
||||
|
||||
virtual void* createSphereShape( float radius, const Bullet::btVector3FloatData& localScaling, float collisionMargin);
|
||||
|
||||
};
|
||||
|
||||
#endif //BULLET_DATA_EXTRACTOR_H
|
33
Extras/Serialize/ReadBulletSample/CMakeLists.txt
Normal file
33
Extras/Serialize/ReadBulletSample/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
LINK_LIBRARIES(
|
||||
BulletFileLoader
|
||||
)
|
||||
IF (WIN32)
|
||||
SET(ADDITIONAL_SRC
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/build/bullet.rc
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
SET(READBULLET_SRC
|
||||
main.cpp
|
||||
BulletDataExtractor.cpp
|
||||
BulletDataExtractor.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btAlignedAllocator.cpp
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(AppReadBulletSample
|
||||
${READBULLET_SRC}
|
||||
${ADDITIONAL_SRC}
|
||||
)
|
||||
|
||||
|
||||
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||
SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES DEBUG_POSTFIX "_Debug")
|
||||
SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
|
||||
SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
|
||||
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
63
Extras/Serialize/ReadBulletSample/main.cpp
Normal file
63
Extras/Serialize/ReadBulletSample/main.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2011 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../BulletFileLoader/btBulletFile.h"
|
||||
#include "BulletDataExtractor.h"
|
||||
|
||||
///This ReadBulletSample is kept as simple as possible without dependencies to the Bullet SDK.
|
||||
///It can be used to load .bullet data for other physics SDKs
|
||||
///For a more complete example how to load and convert Bullet data using the Bullet SDK check out
|
||||
///the Bullet/Demos/SerializeDemo and Bullet/Serialize/BulletWorldImporter
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* fileName="testFile.bullet";
|
||||
bool verboseDumpAllTypes = false;
|
||||
|
||||
bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName);
|
||||
|
||||
bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
|
||||
|
||||
if (ok)
|
||||
bulletFile2->parse(verboseDumpAllTypes);
|
||||
else
|
||||
{
|
||||
printf("Error loading file %s.\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
|
||||
if (!ok)
|
||||
{
|
||||
printf("Error parsing file %s.\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (verboseDumpAllTypes)
|
||||
{
|
||||
bulletFile2->dumpChunks(bulletFile2->getFileDNA());
|
||||
}
|
||||
|
||||
|
||||
btBulletDataExtractor extractor;
|
||||
|
||||
extractor.convertAllObjects(bulletFile2);
|
||||
|
||||
delete bulletFile2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
37
Extras/Serialize/makesdna/CMakeLists.txt
Normal file
37
Extras/Serialize/makesdna/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
cmake_minimum_required(VERSION 2.4)
|
||||
|
||||
IF(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
ENDIF(COMMAND cmake_policy)
|
||||
|
||||
INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/src )
|
||||
|
||||
#FILE(GLOB INC_FILES ../*.h)
|
||||
|
||||
SET (INC_FILES
|
||||
DNA_rigidbody.h
|
||||
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btVector3.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btMatrix3x3.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btTransform.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionShapes/btCollisionShape.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionDispatch/btCollisionObject.h
|
||||
)
|
||||
|
||||
# Build makesdna executable
|
||||
SET(SRC makesdna.cpp)
|
||||
ADD_EXECUTABLE(makesdna ${SRC} ${INC_FILES})
|
||||
|
||||
# Output BulletDNA.c
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp
|
||||
COMMAND ${CMAKE_CFG_INTDIR}/makesdna ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/CommonSerialize/
|
||||
DEPENDS makesdna
|
||||
)
|
||||
|
||||
# Build bf_dna library
|
||||
SET(SRC ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp)
|
||||
ADD_LIBRARY(BulletDNA ${SRC} ${INC_FILES})
|
||||
|
||||
MESSAGE(STATUS "Configuring makesdna")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user