Files
SingularityViewer/indra/libndhacd/nd_hacdConvexDecomposition.cpp
2013-01-13 03:23:56 +01:00

394 lines
10 KiB
C++

/**
* copyright 2011 sl.nicky.ml@googlemail.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <memory>
#include "nd_hacdConvexDecomposition.h"
#include "nd_hacdDefines.h"
#include "nd_hacdStructs.h"
#include "nd_hacdUtils.h"
#include "ndConvexDecomposition.h"
#include "nd_EnterExitTracer.h"
#include "nd_StructTracer.h"
LLCDStageData nd_hacdConvexDecomposition::mStages[1];
LLCDParam nd_hacdConvexDecomposition::mParams[4];
LLCDParam::LLCDEnumItem nd_hacdConvexDecomposition::mMethods[1];
LLCDParam::LLCDEnumItem nd_hacdConvexDecomposition::mQuality[1];
LLCDParam::LLCDEnumItem nd_hacdConvexDecomposition::mSimplify[1];
LLConvexDecomposition* nd_hacdConvexDecomposition::getInstance()
{
static nd_hacdConvexDecomposition sImpl;
return &sImpl;
}
nd_hacdConvexDecomposition::nd_hacdConvexDecomposition()
{
mNextId = 0;
mCurrentDecoder = 0;
mSingleHullMeshFromMesh = new HACDDecoder();
mTracer = 0;
}
nd_hacdConvexDecomposition::~nd_hacdConvexDecomposition()
{
if( mTracer )
mTracer->release();
}
LLCDResult nd_hacdConvexDecomposition::initSystem()
{
memset( &mStages[0], 0, sizeof( mStages ) );
memset( &mParams[0], 0, sizeof( mParams ) );
memset( &mMethods[0], 0, sizeof( mMethods ) );
memset( &mQuality[0], 0, sizeof( mQuality ) );
memset( &mSimplify[0], 0, sizeof( mSimplify ) );
mStages[0].mName = "Decompose";
mStages[0].mDescription = NULL;
mMethods[0].mName = "Default";
mMethods[0].mValue = 0;
mQuality[0].mName = "Default";
mQuality[0].mValue = 0;
mSimplify[0].mName = "None";
mSimplify[0].mValue = 0;
mParams[0].mName = "nd_AlwaysNeedTriangles";
mParams[0].mDescription = 0;
mParams[0].mType = LLCDParam::LLCD_BOOLEAN;
mParams[0].mDefault.mBool = true;
mParams[1].mName = "Method";
mParams[1].mType = LLCDParam::LLCD_ENUM;
mParams[1].mDetails.mEnumValues.mNumEnums = sizeof(mMethods)/sizeof(LLCDParam::LLCDEnumItem);
mParams[1].mDetails.mEnumValues.mEnumsArray = mMethods;
mParams[1].mDefault.mIntOrEnumValue = 0;
mParams[2].mName = "Decompose Quality";
mParams[2].mType = LLCDParam::LLCD_ENUM;
mParams[2].mDetails.mEnumValues.mNumEnums = sizeof(mQuality)/sizeof(LLCDParam::LLCDEnumItem);
mParams[2].mDetails.mEnumValues.mEnumsArray = mQuality;
mParams[2].mDefault.mIntOrEnumValue = 0;
mParams[3].mName = "Simplify Method";
mParams[3].mType = LLCDParam::LLCD_ENUM;
mParams[3].mDetails.mEnumValues.mNumEnums = sizeof(mSimplify)/sizeof(LLCDParam::LLCDEnumItem);
mParams[3].mDetails.mEnumValues.mEnumsArray = mSimplify;
mParams[3].mDefault.mIntOrEnumValue = 0;
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::initThread()
{
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::quitThread()
{
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::quitSystem()
{
return LLCD_OK;
}
void nd_hacdConvexDecomposition::genDecomposition( int& decomp )
{
HACDDecoder *pGen = new HACDDecoder();
decomp = mNextId;
++mNextId;
mDecoders[ decomp ] = pGen;
}
void nd_hacdConvexDecomposition::deleteDecomposition( int decomp )
{
delete mDecoders[ decomp ];
mDecoders.erase( decomp );
}
void nd_hacdConvexDecomposition::bindDecomposition( int decomp )
{
TRACE_FUNC( mTracer );
mCurrentDecoder = decomp;
}
LLCDResult nd_hacdConvexDecomposition::setParam( const char* name, float val )
{
TRACE_FUNC( mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::setParam( const char* name, bool val )
{
TRACE_FUNC( mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::setParam( const char* name, int val )
{
TRACE_FUNC( mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::setMeshData( const LLCDMeshData* data, bool vertex_based )
{
TRACE_FUNC( mTracer );
ndStructTracer::trace( data, vertex_based, mTracer );
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
return ::setMeshData( data, vertex_based, pC );
}
LLCDResult nd_hacdConvexDecomposition::registerCallback( int stage, llcdCallbackFunc callback )
{
TRACE_FUNC( mTracer );
if( mDecoders.end() == mDecoders.find( mCurrentDecoder ) )
return LLCD_STAGE_NOT_READY;
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
pC->mCallback = callback;
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::buildSingleHull()
{
TRACE_FUNC( mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::executeStage( int stage )
{
TRACE_FUNC( mTracer );
if ( stage < 0 || stage >= NUM_STAGES )
return LLCD_INVALID_STAGE;
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
tHACD *pHACD = init( 1, MIN_NUMBER_OF_CLUSTERS, MAX_VERTICES_PER_HULL, CONNECT_DISTS[0], pC );
DecompData oRes = decompose( pHACD );
ndStructTracer::trace( oRes, mTracer );
delete pHACD;
pC->mStages[ stage ] = oRes;
return LLCD_OK;
}
int nd_hacdConvexDecomposition::getNumHullsFromStage( int stage )
{
TRACE_FUNC( mTracer );
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
if ( !pC )
return 0;
if ( stage < 0 || static_cast<size_t>(stage) >= pC->mStages.size() )
return 0;
return pC->mStages[stage].mHulls.size();
}
DecompData toSingleHull( HACDDecoder *aDecoder, LLCDResult &aRes, ndConvexDecompositionTracer *aTracer )
{
TRACE_FUNC( aTracer );
aRes = LLCD_REQUEST_OUT_OF_RANGE;
for ( int i = 0; i < TO_SINGLE_HULL_TRIES; ++i )
{
tHACD *pHACD = init( CONCAVITY_FOR_SINGLE_HULL[i], 1, MAX_VERTICES_PER_HULL, CONNECT_DISTS[i], aDecoder );
DecompData oRes = decompose( pHACD );
delete pHACD;
ndStructTracer::trace( oRes, aTracer );
if ( oRes.mHulls.size() == 1 )
{
aRes = LLCD_OK;
return oRes;
}
}
return DecompData();
}
LLCDResult nd_hacdConvexDecomposition::getSingleHull( LLCDHull* hullOut )
{
TRACE_FUNC( mTracer );
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
memset( hullOut, 0, sizeof( LLCDHull ) );
LLCDResult res;
// Will already trace oRes
DecompData oRes = ::toSingleHull( pC, res, mTracer );
if ( LLCD_OK != res || oRes.mHulls.size() != 1 )
return res;
pC->mSingleHull = oRes.mHulls[0];
pC->mSingleHull.toLLHull( hullOut );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::getHullFromStage( int stage, int hull, LLCDHull* hullOut )
{
TRACE_FUNC( mTracer );
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
memset( hullOut, 0, sizeof( LLCDHull ) );
if ( stage < 0 || static_cast<size_t>(stage) >= pC->mStages.size() )
return LLCD_INVALID_STAGE;
DecompData &oData = pC->mStages[ stage ];
if ( hull < 0 ||static_cast<size_t>(hull) >= oData.mHulls.size() )
return LLCD_REQUEST_OUT_OF_RANGE;
oData.mHulls[ hull ].toLLHull( hullOut );
ndStructTracer::trace( hullOut, mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut )
{
TRACE_FUNC( mTracer );
HACDDecoder *pC = mDecoders[ mCurrentDecoder ];
memset( meshDataOut, 0, sizeof( LLCDHull ) );
if ( stage < 0 || static_cast<size_t>(stage) >= pC->mStages.size() )
return LLCD_INVALID_STAGE;
DecompData &oData = pC->mStages[ stage ];
if ( hull < 0 || static_cast<size_t>(hull) >= oData.mHulls.size() )
return LLCD_REQUEST_OUT_OF_RANGE;
oData.mHulls[ hull ].toLLMesh( meshDataOut );
ndStructTracer::trace( meshDataOut, true, mTracer );
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut )
{
TRACE_FUNC( mTracer );
memset( meshOut, 0, sizeof( LLCDMeshData ) );
mMeshToHullVertices.clear();
mMeshToHullTriangles.clear();
if( !hullIn || !hullIn->mVertexBase || !meshOut )
return LLCD_NULL_PTR;
if( hullIn->mVertexStrideBytes < 3*sizeof(float) || hullIn->mNumVertices < 3 )
return LLCD_INVALID_HULL_DATA;
LLCDResult oRet = convertHullToMesh( hullIn, mMeshToHullVertices, mMeshToHullTriangles );
if( LLCD_OK != oRet )
return oRet;
meshOut->mVertexStrideBytes = sizeof( float )*3;
meshOut->mNumVertices = mMeshToHullVertices.size()/3;
meshOut->mVertexBase = &mMeshToHullVertices[0];
meshOut->mIndexType = LLCDMeshData::INT_32;
meshOut->mIndexStrideBytes = sizeof( hacdUINT32 ) * 3;
meshOut->mNumTriangles = mMeshToHullTriangles.size()/3;
meshOut->mIndexBase = &mMeshToHullTriangles[0];
return LLCD_OK;
}
LLCDResult nd_hacdConvexDecomposition::generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut )
{
TRACE_FUNC( mTracer );
memset( meshOut, 0, sizeof( LLCDMeshData ) );
mSingleHullMeshFromMesh->clear();
LLCDResult res = ::setMeshData( meshIn, meshIn->mNumVertices > 3, mSingleHullMeshFromMesh );
if ( LLCD_OK != res )
return res;
// Will already trace oRes
DecompData oRes = ::toSingleHull( mSingleHullMeshFromMesh, res, mTracer );
if ( LLCD_OK != res || oRes.mHulls.size() != 1 )
return res;
mSingleHullMeshFromMesh->mSingleHull = oRes.mHulls[0];
mSingleHullMeshFromMesh->mSingleHull.toLLMesh( meshOut );
return LLCD_OK;
}
void nd_hacdConvexDecomposition::loadMeshData( const char* fileIn, LLCDMeshData** meshDataOut )
{
TRACE_FUNC( mTracer );
static LLCDMeshData meshData;
memset( &meshData, 0, sizeof( LLCDMeshData ) );
*meshDataOut = &meshData;
}
int nd_hacdConvexDecomposition::getParameters( const LLCDParam** paramsOut )
{
TRACE_FUNC( mTracer );
*paramsOut = mParams;
return sizeof(mParams)/sizeof(LLCDParam);
}
int nd_hacdConvexDecomposition::getStages( const LLCDStageData** stagesOut )
{
TRACE_FUNC( mTracer );
*stagesOut = mStages;
return sizeof(mStages)/sizeof(LLCDStageData);
}
void nd_hacdConvexDecomposition::setTracer( ndConvexDecompositionTracer * aTracer)
{
if( mTracer )
mTracer->release();
mTracer = aTracer;
if( mTracer )
mTracer->addref();
}
bool nd_hacdConvexDecomposition::isFunctional()
{
return true;
}