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

184 lines
4.9 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 "nd_hacdUtils.h"
tHACD* init( int nConcavity, int nClusters, int nMaxVerticesPerHull, double dMaxConnectDist, HACDDecoder *aData )
{
tHACD *pDec = HACD::CreateHACD(0);
pDec->SetPoints( &aData->mVertices[0] );
pDec->SetNPoints( aData->mVertices.size() );
if ( aData->mTriangles.size() )
{
pDec->SetTriangles( &aData->mTriangles[0] );
pDec->SetNTriangles( aData->mTriangles.size() );
}
pDec->SetCompacityWeight( 0.1f );
pDec->SetVolumeWeight( 0 );
pDec->SetNClusters( nClusters );
pDec->SetAddExtraDistPoints( true );
pDec->SetAddFacesPoints( true );
pDec->SetNVerticesPerCH( nMaxVerticesPerHull );
pDec->SetConcavity( nConcavity );
pDec->SetConnectDist( dMaxConnectDist );
pDec->SetCallBack( aData );
return pDec;
}
DecompData decompose( tHACD *aHACD )
{
aHACD->Compute();
DecompData oRet;
int nClusters = aHACD->GetNClusters();
for ( int i = 0; i < nClusters; ++i )
{
int nVertices = aHACD->GetNPointsCH( i );
int nTriangles = aHACD->GetNTrianglesCH( i );
DecompHull oHull;
oHull.mVertices.resize( nVertices );
oHull.mTriangles.resize( nTriangles );
aHACD->GetCH( i, &oHull.mVertices[0], &oHull.mTriangles[0] );
oRet.mHulls.push_back( oHull );
}
return oRet;
}
tVecLong fromI16( void const *& pPtr, int aStride )
{
hacdUINT16 const *pVal = reinterpret_cast< hacdUINT16 const * >( pPtr );
tVecLong oRet( pVal[0], pVal[1], pVal[2] );
pVal += aStride / 2;
pPtr = pVal;
return oRet;
}
tVecLong fromI32( void const *& pPtr, int aStride )
{
hacdUINT32 const *pVal = reinterpret_cast< hacdUINT32 const * >( pPtr );
tVecLong oRet( pVal[0], pVal[1], pVal[2] );
pVal += aStride / 4;
pPtr = pVal;
return oRet;
}
LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based, HACDDecoder *aDec )
{
if ( !data || !data->mVertexBase || ( data->mNumVertices < 3 ) || ( data->mVertexStrideBytes != 12 && data->mVertexStrideBytes != 16 ) )
return LLCD_INVALID_MESH_DATA;
if ( !vertex_based && ( ( data->mNumTriangles < 1 ) || ! data->mIndexBase ) )
return LLCD_INVALID_MESH_DATA;
aDec->clear();
int nCount = data->mNumVertices;
float const* pVertex = data->mVertexBase;
int nStride = data->mVertexStrideBytes / sizeof( float );
for ( int i = 0; i < nCount; ++i )
{
tVecDbl oPt( pVertex[0], pVertex[1], pVertex[2] );
aDec->mVertices.push_back( oPt );
pVertex += nStride;
}
if ( !vertex_based )
{
fFromIXX pFunc = 0;
nCount = data->mNumTriangles;
nStride = data->mIndexStrideBytes;
void const *pData = data->mIndexBase;
if ( data->mIndexType == LLCDMeshData::INT_16 )
pFunc = fromI16;
else
pFunc = fromI32;
for ( int i = 0; i < nCount; ++i )
{
tVecLong oVal( ( *pFunc )( pData, nStride ) );
aDec->mTriangles.push_back( oVal );
}
}
return LLCD_OK;
}
LLCDResult convertHullToMesh( const LLCDHull* aHull, std::vector< float > &aVerticesOut, std::vector< int > &aTrianglesOut )
{
if( !aHull || !aHull->mVertexBase )
return LLCD_NULL_PTR;
if( aHull->mVertexStrideBytes < 3*sizeof(float) || aHull->mNumVertices < 3 )
return LLCD_INVALID_HULL_DATA;
HACD::ICHull oHull;
int nCount = aHull->mNumVertices;
float const *pVertex = aHull->mVertexBase;
int nStride = aHull->mVertexStrideBytes / sizeof( float );
std::vector< tVecDbl > vcPoints;
for ( int i = 0; i < nCount; ++i )
{
vcPoints.push_back( tVecDbl( pVertex[0], pVertex[1], pVertex[2] ) );
pVertex += nStride;
}
oHull.AddPoints( &vcPoints[0], vcPoints.size() );
HACD::ICHullError eErr = oHull.Process( MAX_VERTICES_PER_HULL );
if( HACD::ICHullErrorOK != eErr )
return LLCD_INVALID_HULL_DATA;
HACD::TMMesh &oMesh = oHull.GetMesh();
std::vector< tVecDbl > vPoints;
std::vector< tVecLong > vTriangles;
vPoints.resize( oMesh.GetNVertices() );
vTriangles.resize( oMesh.GetNTriangles() );
oMesh.GetIFS( &vPoints[0], &vTriangles[0] );
for( size_t i = 0; i < vPoints.size(); ++i )
{
aVerticesOut.push_back( static_cast<float>( vPoints[i].X() ) );
aVerticesOut.push_back( static_cast<float>( vPoints[i].Y() ) );
aVerticesOut.push_back( static_cast<float>( vPoints[i].Z() ) );
}
for( size_t i = 0; i < vTriangles.size(); ++i )
{
aTrianglesOut.push_back( vTriangles[i].X() );
aTrianglesOut.push_back( vTriangles[i].Y() );
aTrianglesOut.push_back( vTriangles[i].Z() );
}
return LLCD_OK;
}