Merge pull request #2148 from arkeon7/Manage_PCloud_in_Filters

Allow findDegenerate and SplitLargeMesh to pass point clouds models.
pull/2175/head^2
Kim Kulling 2018-10-09 16:14:58 +02:00 committed by GitHub
commit c3e6a01397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 135 additions and 188 deletions

View File

@ -91,8 +91,10 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void FindDegeneratesProcess::Execute( aiScene* pScene) { void FindDegeneratesProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin"); ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
if (ExecuteOnMesh(pScene->mMeshes[i])) { {
//Do not process point cloud, ExecuteOnMesh works only with faces data
if ((pScene->mMeshes[i]->mPrimitiveTypes != aiPrimitiveType::aiPrimitiveType_POINT) && ExecuteOnMesh(pScene->mMeshes[i])) {
removeMesh(pScene, i); removeMesh(pScene, i);
--i; //the current i is removed, do not skip the next one --i; //the current i is removed, do not skip the next one
} }

View File

@ -40,73 +40,67 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/**
/** @file Implementation of the SplitLargeMeshes postprocessing step * @file Implementation of the SplitLargeMeshes postprocessing step
*/ */
// internal headers of the post-processing framework // internal headers of the post-processing framework
#include "SplitLargeMeshes.h" #include "SplitLargeMeshes.h"
#include "ProcessHelper.h" #include "ProcessHelper.h"
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() {
{
LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES; LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const {
{
return (pFlags & aiProcess_SplitLargeMeshes) != 0; return (pFlags & aiProcess_SplitLargeMeshes) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) {
{ if (0xffffffff == this->LIMIT || nullptr == pScene ) {
if (0xffffffff == this->LIMIT)return; return;
}
ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle begin"); ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle begin");
std::vector<std::pair<aiMesh*, unsigned int> > avList; std::vector<std::pair<aiMesh*, unsigned int> > avList;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
this->SplitMesh(a, pScene->mMeshes[a],avList); this->SplitMesh(a, pScene->mMeshes[a],avList);
}
if (avList.size() != pScene->mNumMeshes) if (avList.size() != pScene->mNumMeshes) {
{
// it seems something has been split. rebuild the mesh list // it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes; delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)avList.size(); pScene->mNumMeshes = (unsigned int)avList.size();
pScene->mMeshes = new aiMesh*[avList.size()]; pScene->mMeshes = new aiMesh*[avList.size()];
for (unsigned int i = 0; i < avList.size();++i) for (unsigned int i = 0; i < avList.size();++i) {
pScene->mMeshes[i] = avList[i].first; pScene->mMeshes[i] = avList[i].first;
}
// now we need to update all nodes // now we need to update all nodes
this->UpdateNode(pScene->mRootNode,avList); this->UpdateNode(pScene->mRootNode,avList);
ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
} } else {
else {
ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup properties // Setup properties
void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) {
{
// get the current value of the split property // get the current value of the split property
this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES); this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
} }
@ -114,17 +108,13 @@ void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Update a node after some meshes have been split // Update a node after some meshes have been split
void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
const std::vector<std::pair<aiMesh*, unsigned int> >& avList) const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
{
// for every index in out list build a new entry // for every index in out list build a new entry
std::vector<unsigned int> aiEntries; std::vector<unsigned int> aiEntries;
aiEntries.reserve(pcNode->mNumMeshes + 1); aiEntries.reserve(pcNode->mNumMeshes + 1);
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) {
{ for (unsigned int a = 0; a < avList.size();++a) {
for (unsigned int a = 0; a < avList.size();++a) if (avList[a].second == pcNode->mMeshes[i]) {
{
if (avList[a].second == pcNode->mMeshes[i])
{
aiEntries.push_back(a); aiEntries.push_back(a);
} }
} }
@ -135,15 +125,14 @@ void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
pcNode->mNumMeshes = (unsigned int)aiEntries.size(); pcNode->mNumMeshes = (unsigned int)aiEntries.size();
pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) {
pcNode->mMeshes[b] = aiEntries[b]; pcNode->mMeshes[b] = aiEntries[b];
}
// recusively update all other nodes // recusively update all other nodes
for (unsigned int i = 0; i < pcNode->mNumChildren;++i) for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
{
UpdateNode ( pcNode->mChildren[i], avList ); UpdateNode ( pcNode->mChildren[i], avList );
} }
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -151,10 +140,8 @@ void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
void SplitLargeMeshesProcess_Triangle::SplitMesh( void SplitLargeMeshesProcess_Triangle::SplitMesh(
unsigned int a, unsigned int a,
aiMesh* pMesh, aiMesh* pMesh,
std::vector<std::pair<aiMesh*, unsigned int> >& avList) std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
{ if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) {
if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
{
ASSIMP_LOG_INFO("Mesh exceeds the triangle limit. It will be split ..."); ASSIMP_LOG_INFO("Mesh exceeds the triangle limit. It will be split ...");
// we need to split this mesh into sub meshes // we need to split this mesh into sub meshes
@ -165,8 +152,7 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
const unsigned int iOutVertexNum = iOutFaceNum * 3; const unsigned int iOutVertexNum = iOutFaceNum * 3;
// now generate all submeshes // now generate all submeshes
for (unsigned int i = 0; i < iSubMeshes;++i) for (unsigned int i = 0; i < iSubMeshes;++i) {
{
aiMesh* pcMesh = new aiMesh; aiMesh* pcMesh = new aiMesh;
pcMesh->mNumFaces = iOutFaceNum; pcMesh->mNumFaces = iOutFaceNum;
pcMesh->mMaterialIndex = pMesh->mMaterialIndex; pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
@ -174,8 +160,7 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
// the name carries the adjacency information between the meshes // the name carries the adjacency information between the meshes
pcMesh->mName = pMesh->mName; pcMesh->mName = pMesh->mName;
if (i == iSubMeshes-1) if (i == iSubMeshes-1) {
{
pcMesh->mNumFaces = iOutFaceNum + ( pcMesh->mNumFaces = iOutFaceNum + (
pMesh->mNumFaces - iOutFaceNum * iSubMeshes); pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
} }
@ -186,71 +171,62 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
// get the total number of indices // get the total number of indices
unsigned int iCnt = 0; unsigned int iCnt = 0;
for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) {
{
iCnt += pMesh->mFaces[p].mNumIndices; iCnt += pMesh->mFaces[p].mNumIndices;
} }
pcMesh->mNumVertices = iCnt; pcMesh->mNumVertices = iCnt;
// allocate storage // allocate storage
if (pMesh->mVertices != NULL) if (pMesh->mVertices != nullptr) {
pcMesh->mVertices = new aiVector3D[iCnt]; pcMesh->mVertices = new aiVector3D[iCnt];
}
if (pMesh->HasNormals()) if (pMesh->HasNormals()) {
pcMesh->mNormals = new aiVector3D[iCnt]; pcMesh->mNormals = new aiVector3D[iCnt];
}
if (pMesh->HasTangentsAndBitangents()) if (pMesh->HasTangentsAndBitangents()) {
{
pcMesh->mTangents = new aiVector3D[iCnt]; pcMesh->mTangents = new aiVector3D[iCnt];
pcMesh->mBitangents = new aiVector3D[iCnt]; pcMesh->mBitangents = new aiVector3D[iCnt];
} }
// texture coordinates // texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
{
pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
if (pMesh->HasTextureCoords( c)) if (pMesh->HasTextureCoords( c)) {
{
pcMesh->mTextureCoords[c] = new aiVector3D[iCnt]; pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
} }
} }
// vertex colors // vertex colors
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
{ if (pMesh->HasVertexColors( c)) {
if (pMesh->HasVertexColors( c))
{
pcMesh->mColors[c] = new aiColor4D[iCnt]; pcMesh->mColors[c] = new aiColor4D[iCnt];
} }
} }
if (pMesh->HasBones()) if (pMesh->HasBones()) {
{
// assume the number of bones won't change in most cases // assume the number of bones won't change in most cases
pcMesh->mBones = new aiBone*[pMesh->mNumBones]; pcMesh->mBones = new aiBone*[pMesh->mNumBones];
// iterate through all bones of the mesh and find those which // iterate through all bones of the mesh and find those which
// need to be copied to the split mesh // need to be copied to the split mesh
std::vector<aiVertexWeight> avTempWeights; std::vector<aiVertexWeight> avTempWeights;
for (unsigned int p = 0; p < pcMesh->mNumBones;++p) for (unsigned int p = 0; p < pcMesh->mNumBones;++p) {
{
aiBone* const bone = pcMesh->mBones[p]; aiBone* const bone = pcMesh->mBones[p];
avTempWeights.clear(); avTempWeights.clear();
avTempWeights.reserve(bone->mNumWeights / iSubMeshes); avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
for (unsigned int q = 0; q < bone->mNumWeights;++q) for (unsigned int q = 0; q < bone->mNumWeights;++q) {
{
aiVertexWeight& weight = bone->mWeights[q]; aiVertexWeight& weight = bone->mWeights[q];
if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) {
{
avTempWeights.push_back(weight); avTempWeights.push_back(weight);
weight = avTempWeights.back(); weight = avTempWeights.back();
weight.mVertexId -= iBase; weight.mVertexId -= iBase;
} }
} }
if (!avTempWeights.empty()) if (!avTempWeights.empty()) {
{
// we'll need this bone. Copy it ... // we'll need this bone. Copy it ...
aiBone* pc = new aiBone(); aiBone* pc = new aiBone();
pcMesh->mBones[pcMesh->mNumBones++] = pc; pcMesh->mBones[pcMesh->mNumBones++] = pc;
@ -261,12 +237,12 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
// no need to reallocate the array for the last submesh. // no need to reallocate the array for the last submesh.
// Here we can reuse the (large) source array, although // Here we can reuse the (large) source array, although
// we'll waste some memory // we'll waste some memory
if (iSubMeshes-1 == i) if (iSubMeshes-1 == i) {
{
pc->mWeights = bone->mWeights; pc->mWeights = bone->mWeights;
bone->mWeights = NULL; bone->mWeights = nullptr;
} else {
pc->mWeights = new aiVertexWeight[pc->mNumWeights];
} }
else pc->mWeights = new aiVertexWeight[pc->mNumWeights];
// copy the weights // copy the weights
::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights); ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
@ -276,8 +252,7 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
// (we will also need to copy the array of indices) // (we will also need to copy the array of indices)
unsigned int iCurrent = 0; unsigned int iCurrent = 0;
for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
{
pcMesh->mFaces[p].mNumIndices = 3; pcMesh->mFaces[p].mNumIndices = 3;
// allocate a new array // allocate a new array
const unsigned int iTemp = p + iBase; const unsigned int iTemp = p + iBase;
@ -289,8 +264,7 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices]; unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
// need to update the output primitive types // need to update the output primitive types
switch (iNumIndices) switch (iNumIndices) {
{
case 1: case 1:
pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break; break;
@ -305,41 +279,41 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
} }
// and copy the contents of the old array, offset by current base // and copy the contents of the old array, offset by current base
for (unsigned int v = 0; v < iNumIndices;++v) for (unsigned int v = 0; v < iNumIndices;++v) {
{
unsigned int iIndex = pi[v]; unsigned int iIndex = pi[v];
unsigned int iIndexOut = iCurrent++; unsigned int iIndexOut = iCurrent++;
piOut[v] = iIndexOut; piOut[v] = iIndexOut;
// copy positions // copy positions
if (pMesh->mVertices != NULL) if (pMesh->mVertices != nullptr) {
pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex]; pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
}
// copy normals // copy normals
if (pMesh->HasNormals()) if (pMesh->HasNormals()) {
pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex]; pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
}
// copy tangents/bitangents // copy tangents/bitangents
if (pMesh->HasTangentsAndBitangents()) if (pMesh->HasTangentsAndBitangents()) {
{
pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex]; pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex]; pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
} }
// texture coordinates // texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
{ if (pMesh->HasTextureCoords( c ) ) {
if (pMesh->HasTextureCoords( c))
pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex]; pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
} }
}
// vertex colors // vertex colors
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
{ if (pMesh->HasVertexColors( c)) {
if (pMesh->HasVertexColors( c))
pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex]; pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
} }
} }
} }
}
// add the newly created mesh to the list // add the newly created mesh to the list
avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
@ -347,51 +321,59 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
// now delete the old mesh data // now delete the old mesh data
delete pMesh; delete pMesh;
} else {
avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
} }
else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() {
{
LIMIT = AI_SLM_DEFAULT_MAX_VERTICES; LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const {
{
return (pFlags & aiProcess_SplitLargeMeshes) != 0; return (pFlags & aiProcess_SplitLargeMeshes) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) {
{ if (0xffffffff == this->LIMIT || nullptr == pScene ) {
std::vector<std::pair<aiMesh*, unsigned int> > avList; return;
}
if (0xffffffff == this->LIMIT)return;
ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin"); ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin");
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
this->SplitMesh(a, pScene->mMeshes[a],avList);
if (avList.size() != pScene->mNumMeshes) std::vector<std::pair<aiMesh*, unsigned int> > avList;
{
//Check for point cloud first,
//Do not process point cloud, splitMesh works only with faces data
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if ( pScene->mMeshes[a]->mPrimitiveTypes == aiPrimitiveType_POINT ) {
return;
}
}
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
this->SplitMesh(a, pScene->mMeshes[a], avList);
}
if (avList.size() != pScene->mNumMeshes) {
// it seems something has been split. rebuild the mesh list // it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes; delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)avList.size(); pScene->mNumMeshes = (unsigned int)avList.size();
pScene->mMeshes = new aiMesh*[avList.size()]; pScene->mMeshes = new aiMesh*[avList.size()];
for (unsigned int i = 0; i < avList.size();++i) for (unsigned int i = 0; i < avList.size();++i) {
pScene->mMeshes[i] = avList[i].first; pScene->mMeshes[i] = avList[i].first;
}
// now we need to update all nodes // now we need to update all nodes
SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
@ -403,8 +385,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup properties // Setup properties
void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) {
{
this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES); this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
} }
@ -413,10 +394,8 @@ void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp)
void SplitLargeMeshesProcess_Vertex::SplitMesh( void SplitLargeMeshesProcess_Vertex::SplitMesh(
unsigned int a, unsigned int a,
aiMesh* pMesh, aiMesh* pMesh,
std::vector<std::pair<aiMesh*, unsigned int> >& avList) std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
{ if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) {
if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT)
{
typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable; typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
// build a per-vertex weight list if necessary // build a per-vertex weight list if necessary
@ -426,7 +405,6 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
// determine the estimated size of a submesh // determine the estimated size of a submesh
// (this could be too large. Max waste is a single digit percentage) // (this could be too large. Max waste is a single digit percentage)
const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1; const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
//const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes;
// create a std::vector<unsigned int> to indicate which vertices // create a std::vector<unsigned int> to indicate which vertices
// have already been copied // have already been copied
@ -439,11 +417,9 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
iEstimatedSize += iEstimatedSize >> 3; iEstimatedSize += iEstimatedSize >> 3;
// now generate all submeshes // now generate all submeshes
unsigned int iBase = 0; unsigned int iBase( 0 );
while (true) while (true) {
{
const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT; const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
aiMesh* pcMesh = new aiMesh; aiMesh* pcMesh = new aiMesh;
pcMesh->mNumVertices = 0; pcMesh->mNumVertices = 0;
pcMesh->mMaterialIndex = pMesh->mMaterialIndex; pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
@ -452,18 +428,15 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
pcMesh->mName = pMesh->mName; pcMesh->mName = pMesh->mName;
typedef std::vector<aiVertexWeight> BoneWeightList; typedef std::vector<aiVertexWeight> BoneWeightList;
if (pMesh->HasBones()) if (pMesh->HasBones()) {
{
pcMesh->mBones = new aiBone*[pMesh->mNumBones]; pcMesh->mBones = new aiBone*[pMesh->mNumBones];
::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones); ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
} }
// clear the temporary helper array // clear the temporary helper array
if (iBase) if (iBase) {
{
// we can't use memset here we unsigned int needn' be 32 bits // we can't use memset here we unsigned int needn' be 32 bits
for (auto &elem : avWasCopied) for (auto &elem : avWasCopied) {
{
elem = 0xffffffff; elem = 0xffffffff;
} }
} }
@ -472,50 +445,41 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
std::vector<aiFace> vFaces; std::vector<aiFace> vFaces;
// reserve enough storage for most cases // reserve enough storage for most cases
if (pMesh->HasPositions()) if (pMesh->HasPositions()) {
{
pcMesh->mVertices = new aiVector3D[iOutVertexNum]; pcMesh->mVertices = new aiVector3D[iOutVertexNum];
} }
if (pMesh->HasNormals()) if (pMesh->HasNormals()) {
{
pcMesh->mNormals = new aiVector3D[iOutVertexNum]; pcMesh->mNormals = new aiVector3D[iOutVertexNum];
} }
if (pMesh->HasTangentsAndBitangents()) if (pMesh->HasTangentsAndBitangents()) {
{
pcMesh->mTangents = new aiVector3D[iOutVertexNum]; pcMesh->mTangents = new aiVector3D[iOutVertexNum];
pcMesh->mBitangents = new aiVector3D[iOutVertexNum]; pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
} }
for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) {
{
pcMesh->mColors[c] = new aiColor4D[iOutVertexNum]; pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
} }
for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) {
{
pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum]; pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
} }
vFaces.reserve(iEstimatedSize); vFaces.reserve(iEstimatedSize);
// (we will also need to copy the array of indices) // (we will also need to copy the array of indices)
while (iBase < pMesh->mNumFaces) while (iBase < pMesh->mNumFaces) {
{
// allocate a new array // allocate a new array
const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices; const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
// doesn't catch degenerates but is quite fast // doesn't catch degenerates but is quite fast
unsigned int iNeed = 0; unsigned int iNeed = 0;
for (unsigned int v = 0; v < iNumIndices;++v) for (unsigned int v = 0; v < iNumIndices;++v) {
{
unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
// check whether we do already have this vertex // check whether we do already have this vertex
if (0xFFFFFFFF == avWasCopied[iIndex]) if (0xFFFFFFFF == avWasCopied[iIndex]) {
{
iNeed++; iNeed++;
} }
} }
if (pcMesh->mNumVertices + iNeed > iOutVertexNum) if (pcMesh->mNumVertices + iNeed > iOutVertexNum) {
{
// don't use this face // don't use this face
break; break;
} }
@ -528,8 +492,7 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
rFace.mIndices = new unsigned int[iNumIndices]; rFace.mIndices = new unsigned int[iNumIndices];
// need to update the output primitive types // need to update the output primitive types
switch (rFace.mNumIndices) switch (rFace.mNumIndices) {
{
case 1: case 1:
pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break; break;
@ -544,13 +507,11 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
} }
// and copy the contents of the old array, offset by current base // and copy the contents of the old array, offset by current base
for (unsigned int v = 0; v < iNumIndices;++v) for (unsigned int v = 0; v < iNumIndices;++v) {
{
unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
// check whether we do already have this vertex // check whether we do already have this vertex
if (0xFFFFFFFF != avWasCopied[iIndex]) if (0xFFFFFFFF != avWasCopied[iIndex]) {
{
rFace.mIndices[v] = avWasCopied[iIndex]; rFace.mIndices[v] = avWasCopied[iIndex];
continue; continue;
} }
@ -559,49 +520,38 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]); pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
// copy normals // copy normals
if (pMesh->HasNormals()) if (pMesh->HasNormals()) {
{
pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]); pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
} }
// copy tangents/bitangents // copy tangents/bitangents
if (pMesh->HasTangentsAndBitangents()) if (pMesh->HasTangentsAndBitangents()) {
{
pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]); pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]); pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
} }
// texture coordinates // texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
{ if (pMesh->HasTextureCoords( c)) {
if (pMesh->HasTextureCoords( c))
{
pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex]; pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
} }
} }
// vertex colors // vertex colors
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
{ if (pMesh->HasVertexColors( c)) {
if (pMesh->HasVertexColors( c))
{
pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex]; pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
} }
} }
// check whether we have bone weights assigned to this vertex // check whether we have bone weights assigned to this vertex
rFace.mIndices[v] = pcMesh->mNumVertices; rFace.mIndices[v] = pcMesh->mNumVertices;
if (avPerVertexWeights) if (avPerVertexWeights) {
{
VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ]; VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
if( !table.empty() ) if( !table.empty() ) {
{ for (VertexWeightTable::const_iterator iter = table.begin();
for (VertexWeightTable::const_iterator iter != table.end();++iter) {
iter = table.begin();
iter != table.end();++iter)
{
// allocate the bone weight array if necessary // allocate the bone weight array if necessary
BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first]; BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
if (!pcWeightList) if (nullptr == pcWeightList) {
{
pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList()); pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
} }
pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second)); pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
@ -612,26 +562,22 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
avWasCopied[iIndex] = pcMesh->mNumVertices; avWasCopied[iIndex] = pcMesh->mNumVertices;
pcMesh->mNumVertices++; pcMesh->mNumVertices++;
} }
iBase++; ++iBase;
if(pcMesh->mNumVertices == iOutVertexNum) if(pcMesh->mNumVertices == iOutVertexNum) {
{
// break here. The face is only added if it was complete // break here. The face is only added if it was complete
break; break;
} }
} }
// check which bones we'll need to create for this submesh // check which bones we'll need to create for this submesh
if (pMesh->HasBones()) if (pMesh->HasBones()) {
{
aiBone** ppCurrent = pcMesh->mBones; aiBone** ppCurrent = pcMesh->mBones;
for (unsigned int k = 0; k < pMesh->mNumBones;++k) for (unsigned int k = 0; k < pMesh->mNumBones;++k) {
{
// check whether the bone is existing // check whether the bone is existing
BoneWeightList* pcWeightList; BoneWeightList* pcWeightList;
if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) {
{
aiBone* pcOldBone = pMesh->mBones[k]; aiBone* pcOldBone = pMesh->mBones[k];
aiBone* pcOut; aiBone* pcOut( nullptr );
*ppCurrent++ = pcOut = new aiBone(); *ppCurrent++ = pcOut = new aiBone();
pcOut->mName = aiString(pcOldBone->mName); pcOut->mName = aiString(pcOldBone->mName);
pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix; pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
@ -653,14 +599,14 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
pcMesh->mFaces = new aiFace[vFaces.size()]; pcMesh->mFaces = new aiFace[vFaces.size()];
pcMesh->mNumFaces = (unsigned int)vFaces.size(); pcMesh->mNumFaces = (unsigned int)vFaces.size();
for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) {
pcMesh->mFaces[p] = vFaces[p]; pcMesh->mFaces[p] = vFaces[p];
}
// add the newly created mesh to the list // add the newly created mesh to the list
avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
if (iBase == pMesh->mNumFaces) if (iBase == pMesh->mNumFaces) {
{
// have all faces ... finish the outer loop, too // have all faces ... finish the outer loop, too
break; break;
} }
@ -674,5 +620,4 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
return; return;
} }
avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
return;
} }