diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:09:44 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:10:02 +0100 |
commit | 77d294db076dac19e8b549b445ffede9f7260c84 (patch) | |
tree | 828ee7a6862ec5c0bd24f97cb540625a2c647376 /src/3rdparty/assimp/code/SplitLargeMeshes.cpp | |
parent | 59f8fec8a41606b3185fe3a4e276978e3e1ed5ef (diff) | |
parent | 939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (diff) |
Merge branch 'dev' into wip/animationwip/animation
Change-Id: I6e770609c90a7745d08fa4e2f424e865678c5d6f
Diffstat (limited to 'src/3rdparty/assimp/code/SplitLargeMeshes.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/SplitLargeMeshes.cpp | 1120 |
1 files changed, 559 insertions, 561 deletions
diff --git a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp index 4be8fe104..5e21ec6b8 100644 --- a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp +++ b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp @@ -2,11 +2,11 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2016, assimp team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the +Redistribution and use of this software 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 @@ -23,16 +23,16 @@ following conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +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 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +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 +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. ---------------------------------------------------------------------- @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the SplitLargeMeshes postprocessing step */ -#include "AssimpPCH.h" + // internal headers of the post-processing framework #include "SplitLargeMeshes.h" @@ -54,50 +54,50 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() { - LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES; + LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES; } // ------------------------------------------------------------------------------------------------ SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() { - // nothing to do here + // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. 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. void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) { - if (0xffffffff == this->LIMIT)return; - - DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin"); - std::vector<std::pair<aiMesh*, unsigned int> > avList; - - 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 - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) - pScene->mMeshes[i] = avList[i].first; - - // now we need to update all nodes - this->UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); - } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); - return; + if (0xffffffff == this->LIMIT)return; + + DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin"); + std::vector<std::pair<aiMesh*, unsigned int> > avList; + + 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 + delete[] pScene->mMeshes; + pScene->mNumMeshes = (unsigned int)avList.size(); + pScene->mMeshes = new aiMesh*[avList.size()]; + + for (unsigned int i = 0; i < avList.size();++i) + pScene->mMeshes[i] = avList[i].first; + + // now we need to update all nodes + this->UpdateNode(pScene->mRootNode,avList); + DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); + } + else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); + return; } // ------------------------------------------------------------------------------------------------ @@ -105,573 +105,571 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) { // 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); } // ------------------------------------------------------------------------------------------------ // Update a node after some meshes have been split 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 - std::vector<unsigned int> aiEntries; - aiEntries.reserve(pcNode->mNumMeshes + 1); - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - for (unsigned int a = 0; a < avList.size();++a) - { - if (avList[a].second == pcNode->mMeshes[i]) - { - aiEntries.push_back(a); - } - } - } - - // now build the new list - delete pcNode->mMeshes; - pcNode->mNumMeshes = (unsigned int)aiEntries.size(); - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - - for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) - pcNode->mMeshes[b] = aiEntries[b]; - - // recusively update all other nodes - for (unsigned int i = 0; i < pcNode->mNumChildren;++i) - { - UpdateNode ( pcNode->mChildren[i], avList ); - } - return; + // for every index in out list build a new entry + std::vector<unsigned int> aiEntries; + aiEntries.reserve(pcNode->mNumMeshes + 1); + for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) + { + for (unsigned int a = 0; a < avList.size();++a) + { + if (avList[a].second == pcNode->mMeshes[i]) + { + aiEntries.push_back(a); + } + } + } + + // now build the new list + delete[] pcNode->mMeshes; + pcNode->mNumMeshes = (unsigned int)aiEntries.size(); + pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; + + for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) + pcNode->mMeshes[b] = aiEntries[b]; + + // recusively update all other nodes + for (unsigned int i = 0; i < pcNode->mNumChildren;++i) + { + UpdateNode ( pcNode->mChildren[i], avList ); + } + return; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. void SplitLargeMeshesProcess_Triangle::SplitMesh( - unsigned int a, - aiMesh* pMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList) + unsigned int a, + aiMesh* pMesh, + std::vector<std::pair<aiMesh*, unsigned int> >& avList) { - if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) - { - DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ..."); - - // we need to split this mesh into sub meshes - // determine the size of a submesh - const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1; - - const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes; - const unsigned int iOutVertexNum = iOutFaceNum * 3; - - // now generate all submeshes - for (unsigned int i = 0; i < iSubMeshes;++i) - { - aiMesh* pcMesh = new aiMesh; - pcMesh->mNumFaces = iOutFaceNum; - pcMesh->mMaterialIndex = pMesh->mMaterialIndex; - - // the name carries the adjacency information between the meshes - pcMesh->mName = pMesh->mName; - - if (i == iSubMeshes-1) - { - pcMesh->mNumFaces = iOutFaceNum + ( - pMesh->mNumFaces - iOutFaceNum * iSubMeshes); - } - // copy the list of faces - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - const unsigned int iBase = iOutFaceNum * i; - - // get the total number of indices - unsigned int iCnt = 0; - for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) - { - iCnt += pMesh->mFaces[p].mNumIndices; - } - pcMesh->mNumVertices = iCnt; - - // allocate storage - if (pMesh->mVertices != NULL) - pcMesh->mVertices = new aiVector3D[iCnt]; - - if (pMesh->HasNormals()) - pcMesh->mNormals = new aiVector3D[iCnt]; - - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents = new aiVector3D[iCnt]; - pcMesh->mBitangents = new aiVector3D[iCnt]; - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; - if (pMesh->HasTextureCoords( c)) - { - pcMesh->mTextureCoords[c] = new aiVector3D[iCnt]; - } - } - - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - { - pcMesh->mColors[c] = new aiColor4D[iCnt]; - } - } - - if (pMesh->HasBones()) - { - // assume the number of bones won't change in most cases - pcMesh->mBones = new aiBone*[pMesh->mNumBones]; - - // iterate through all bones of the mesh and find those which - // need to be copied to the split mesh - std::vector<aiVertexWeight> avTempWeights; - for (unsigned int p = 0; p < pcMesh->mNumBones;++p) - { - aiBone* const bone = pcMesh->mBones[p]; - avTempWeights.clear(); - avTempWeights.reserve(bone->mNumWeights / iSubMeshes); - - for (unsigned int q = 0; q < bone->mNumWeights;++q) - { - aiVertexWeight& weight = bone->mWeights[q]; - if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) - { - avTempWeights.push_back(weight); - weight = avTempWeights.back(); - weight.mVertexId -= iBase; - } - } - - if (!avTempWeights.empty()) - { - // we'll need this bone. Copy it ... - aiBone* pc = new aiBone(); - pcMesh->mBones[pcMesh->mNumBones++] = pc; - pc->mName = aiString(bone->mName); - pc->mNumWeights = (unsigned int)avTempWeights.size(); - pc->mOffsetMatrix = bone->mOffsetMatrix; - - // no need to reallocate the array for the last submesh. - // Here we can reuse the (large) source array, although - // we'll waste some memory - if (iSubMeshes-1 == i) - { - pc->mWeights = bone->mWeights; - bone->mWeights = NULL; - } - else pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - - // copy the weights - ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights); - } - } - } - - // (we will also need to copy the array of indices) - unsigned int iCurrent = 0; - for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) - { - pcMesh->mFaces[p].mNumIndices = 3; - // allocate a new array - const unsigned int iTemp = p + iBase; - const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices; - - // setup face type and number of indices - pcMesh->mFaces[p].mNumIndices = iNumIndices; - unsigned int* pi = pMesh->mFaces[iTemp].mIndices; - unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices]; - - // need to update the output primitive types - switch (iNumIndices) - { - case 1: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - - // and copy the contents of the old array, offset by current base - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pi[v]; - unsigned int iIndexOut = iCurrent++; - piOut[v] = iIndexOut; - - // copy positions - if (pMesh->mVertices != NULL) - pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex]; - - // copy normals - if (pMesh->HasNormals()) - pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex]; - - // copy tangents/bitangents - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex]; - pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex]; - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - if (pMesh->HasTextureCoords( c)) - pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex]; - } - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex]; - } - } - } - - // add the newly created mesh to the list - avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); - } - - // now delete the old mesh data - delete pMesh; - } - else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); - return; + if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) + { + DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ..."); + + // we need to split this mesh into sub meshes + // determine the size of a submesh + const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1; + + const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes; + const unsigned int iOutVertexNum = iOutFaceNum * 3; + + // now generate all submeshes + for (unsigned int i = 0; i < iSubMeshes;++i) + { + aiMesh* pcMesh = new aiMesh; + pcMesh->mNumFaces = iOutFaceNum; + pcMesh->mMaterialIndex = pMesh->mMaterialIndex; + + // the name carries the adjacency information between the meshes + pcMesh->mName = pMesh->mName; + + if (i == iSubMeshes-1) + { + pcMesh->mNumFaces = iOutFaceNum + ( + pMesh->mNumFaces - iOutFaceNum * iSubMeshes); + } + // copy the list of faces + pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; + + const unsigned int iBase = iOutFaceNum * i; + + // get the total number of indices + unsigned int iCnt = 0; + for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) + { + iCnt += pMesh->mFaces[p].mNumIndices; + } + pcMesh->mNumVertices = iCnt; + + // allocate storage + if (pMesh->mVertices != NULL) + pcMesh->mVertices = new aiVector3D[iCnt]; + + if (pMesh->HasNormals()) + pcMesh->mNormals = new aiVector3D[iCnt]; + + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents = new aiVector3D[iCnt]; + pcMesh->mBitangents = new aiVector3D[iCnt]; + } + + // texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; + if (pMesh->HasTextureCoords( c)) + { + pcMesh->mTextureCoords[c] = new aiVector3D[iCnt]; + } + } + + // vertex colors + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) + { + if (pMesh->HasVertexColors( c)) + { + pcMesh->mColors[c] = new aiColor4D[iCnt]; + } + } + + if (pMesh->HasBones()) + { + // assume the number of bones won't change in most cases + pcMesh->mBones = new aiBone*[pMesh->mNumBones]; + + // iterate through all bones of the mesh and find those which + // need to be copied to the split mesh + std::vector<aiVertexWeight> avTempWeights; + for (unsigned int p = 0; p < pcMesh->mNumBones;++p) + { + aiBone* const bone = pcMesh->mBones[p]; + avTempWeights.clear(); + avTempWeights.reserve(bone->mNumWeights / iSubMeshes); + + for (unsigned int q = 0; q < bone->mNumWeights;++q) + { + aiVertexWeight& weight = bone->mWeights[q]; + if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) + { + avTempWeights.push_back(weight); + weight = avTempWeights.back(); + weight.mVertexId -= iBase; + } + } + + if (!avTempWeights.empty()) + { + // we'll need this bone. Copy it ... + aiBone* pc = new aiBone(); + pcMesh->mBones[pcMesh->mNumBones++] = pc; + pc->mName = aiString(bone->mName); + pc->mNumWeights = (unsigned int)avTempWeights.size(); + pc->mOffsetMatrix = bone->mOffsetMatrix; + + // no need to reallocate the array for the last submesh. + // Here we can reuse the (large) source array, although + // we'll waste some memory + if (iSubMeshes-1 == i) + { + pc->mWeights = bone->mWeights; + bone->mWeights = NULL; + } + else pc->mWeights = new aiVertexWeight[pc->mNumWeights]; + + // copy the weights + ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights); + } + } + } + + // (we will also need to copy the array of indices) + unsigned int iCurrent = 0; + for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) + { + pcMesh->mFaces[p].mNumIndices = 3; + // allocate a new array + const unsigned int iTemp = p + iBase; + const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices; + + // setup face type and number of indices + pcMesh->mFaces[p].mNumIndices = iNumIndices; + unsigned int* pi = pMesh->mFaces[iTemp].mIndices; + unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices]; + + // need to update the output primitive types + switch (iNumIndices) + { + case 1: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + } + + // and copy the contents of the old array, offset by current base + for (unsigned int v = 0; v < iNumIndices;++v) + { + unsigned int iIndex = pi[v]; + unsigned int iIndexOut = iCurrent++; + piOut[v] = iIndexOut; + + // copy positions + if (pMesh->mVertices != NULL) + pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex]; + + // copy normals + if (pMesh->HasNormals()) + pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex]; + + // copy tangents/bitangents + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex]; + pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex]; + } + + // texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (pMesh->HasTextureCoords( c)) + pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex]; + } + // vertex colors + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) + { + if (pMesh->HasVertexColors( c)) + pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex]; + } + } + } + + // add the newly created mesh to the list + avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); + } + + // now delete the old mesh data + delete pMesh; + } + else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); + return; } // ------------------------------------------------------------------------------------------------ SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() { - LIMIT = AI_SLM_DEFAULT_MAX_VERTICES; + LIMIT = AI_SLM_DEFAULT_MAX_VERTICES; } // ------------------------------------------------------------------------------------------------ SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() { - // nothing to do here + // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. 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. void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) { - std::vector<std::pair<aiMesh*, unsigned int> > avList; - - if (0xffffffff == this->LIMIT)return; - - DefaultLogger::get()->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) - { - // it seems something has been split. rebuild the mesh list - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) - pScene->mMeshes[i] = avList[i].first; - - // now we need to update all nodes - SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split"); - } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do"); - return; + std::vector<std::pair<aiMesh*, unsigned int> > avList; + + if (0xffffffff == this->LIMIT)return; + + DefaultLogger::get()->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) + { + // it seems something has been split. rebuild the mesh list + delete[] pScene->mMeshes; + pScene->mNumMeshes = (unsigned int)avList.size(); + pScene->mMeshes = new aiMesh*[avList.size()]; + + for (unsigned int i = 0; i < avList.size();++i) + pScene->mMeshes[i] = avList[i].first; + + // now we need to update all nodes + SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); + DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split"); + } + else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do"); + return; } // ------------------------------------------------------------------------------------------------ // Setup properties 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); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. void SplitLargeMeshesProcess_Vertex::SplitMesh( - unsigned int a, - aiMesh* pMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList) + unsigned int a, + aiMesh* pMesh, + std::vector<std::pair<aiMesh*, unsigned int> >& avList) { - if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) - { - typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable; - - // build a per-vertex weight list if necessary - VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh); - - // we need to split this mesh into sub meshes - // determine the estimated size of a submesh - // (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 iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes; - - // create a std::vector<unsigned int> to indicate which vertices - // have already been copied - std::vector<unsigned int> avWasCopied; - avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF); - - // try to find a good estimate for the number of output faces - // per mesh. Add 12.5% as buffer - unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes; - iEstimatedSize += iEstimatedSize >> 3; - - // now generate all submeshes - unsigned int iBase = 0; - while (true) - { - const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT; - - aiMesh* pcMesh = new aiMesh; - pcMesh->mNumVertices = 0; - pcMesh->mMaterialIndex = pMesh->mMaterialIndex; - - // the name carries the adjacency information between the meshes - pcMesh->mName = pMesh->mName; - - typedef std::vector<aiVertexWeight> BoneWeightList; - if (pMesh->HasBones()) - { - pcMesh->mBones = new aiBone*[pMesh->mNumBones]; - ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones); - } - - // clear the temporary helper array - if (iBase) - { - // we can't use memset here we unsigned int needn' be 32 bits - for (std::vector<unsigned int>::iterator - iter = avWasCopied.begin(),end = avWasCopied.end(); - iter != end;++iter) - { - (*iter) = 0xffffffff; - } - } - - // output vectors - std::vector<aiFace> vFaces; - - // reserve enough storage for most cases - if (pMesh->HasPositions()) - { - pcMesh->mVertices = new aiVector3D[iOutVertexNum]; - } - if (pMesh->HasNormals()) - { - pcMesh->mNormals = new aiVector3D[iOutVertexNum]; - } - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents = new aiVector3D[iOutVertexNum]; - pcMesh->mBitangents = new aiVector3D[iOutVertexNum]; - } - for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) - { - pcMesh->mColors[c] = new aiColor4D[iOutVertexNum]; - } - for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) - { - pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; - pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum]; - } - vFaces.reserve(iEstimatedSize); - - // (we will also need to copy the array of indices) - while (iBase < pMesh->mNumFaces) - { - // allocate a new array - const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices; - - // doesn't catch degenerates but is quite fast - unsigned int iNeed = 0; - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; - - // check whether we do already have this vertex - if (0xFFFFFFFF == avWasCopied[iIndex]) - { - iNeed++; - } - } - if (pcMesh->mNumVertices + iNeed > iOutVertexNum) - { - // don't use this face - break; - } - - vFaces.push_back(aiFace()); - aiFace& rFace = vFaces.back(); - - // setup face type and number of indices - rFace.mNumIndices = iNumIndices; - rFace.mIndices = new unsigned int[iNumIndices]; - - // need to update the output primitive types - switch (rFace.mNumIndices) - { - case 1: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - - // and copy the contents of the old array, offset by current base - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; - - // check whether we do already have this vertex - if (0xFFFFFFFF != avWasCopied[iIndex]) - { - rFace.mIndices[v] = avWasCopied[iIndex]; - continue; - } - - // copy positions - pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]); - - // copy normals - if (pMesh->HasNormals()) - { - pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]); - } - - // copy tangents/bitangents - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]); - pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]); - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - if (pMesh->HasTextureCoords( c)) - { - pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex]; - } - } - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - { - pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex]; - } - } - // check whether we have bone weights assigned to this vertex - rFace.mIndices[v] = pcMesh->mNumVertices; - if (avPerVertexWeights) - { - VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ]; - if( !table.empty() ) - { - for (VertexWeightTable::const_iterator - iter = table.begin(); - iter != table.end();++iter) - { - // allocate the bone weight array if necessary - BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first]; - if (!pcWeightList) - { - pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList()); - } - pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second)); - } - } - } - - avWasCopied[iIndex] = pcMesh->mNumVertices; - pcMesh->mNumVertices++; - } - iBase++; - if(pcMesh->mNumVertices == iOutVertexNum) - { - // break here. The face is only added if it was complete - break; - } - } - - // check which bones we'll need to create for this submesh - if (pMesh->HasBones()) - { - aiBone** ppCurrent = pcMesh->mBones; - for (unsigned int k = 0; k < pMesh->mNumBones;++k) - { - // check whether the bone is existing - BoneWeightList* pcWeightList; - if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) - { - aiBone* pcOldBone = pMesh->mBones[k]; - aiBone* pcOut; - *ppCurrent++ = pcOut = new aiBone(); - pcOut->mName = aiString(pcOldBone->mName); - pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix; - pcOut->mNumWeights = (unsigned int)pcWeightList->size(); - pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights]; - - // copy the vertex weights - ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0), - pcOut->mNumWeights * sizeof(aiVertexWeight)); - - // delete the temporary bone weight list - delete pcWeightList; - pcMesh->mNumBones++; - } - } - } - - // copy the face list to the mesh - pcMesh->mFaces = new aiFace[vFaces.size()]; - pcMesh->mNumFaces = (unsigned int)vFaces.size(); - - for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) - pcMesh->mFaces[p] = vFaces[p]; - - // add the newly created mesh to the list - avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); - - if (iBase == pMesh->mNumFaces) - { - // have all faces ... finish the outer loop, too - break; - } - } - - // delete the per-vertex weight list again - delete[] avPerVertexWeights; - - // now delete the old mesh data - delete pMesh; - return; - } - avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); - return; + if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) + { + typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable; + + // build a per-vertex weight list if necessary + VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh); + + // we need to split this mesh into sub meshes + // determine the estimated size of a submesh + // (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 iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes; + + // create a std::vector<unsigned int> to indicate which vertices + // have already been copied + std::vector<unsigned int> avWasCopied; + avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF); + + // try to find a good estimate for the number of output faces + // per mesh. Add 12.5% as buffer + unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes; + iEstimatedSize += iEstimatedSize >> 3; + + // now generate all submeshes + unsigned int iBase = 0; + while (true) + { + const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT; + + aiMesh* pcMesh = new aiMesh; + pcMesh->mNumVertices = 0; + pcMesh->mMaterialIndex = pMesh->mMaterialIndex; + + // the name carries the adjacency information between the meshes + pcMesh->mName = pMesh->mName; + + typedef std::vector<aiVertexWeight> BoneWeightList; + if (pMesh->HasBones()) + { + pcMesh->mBones = new aiBone*[pMesh->mNumBones]; + ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones); + } + + // clear the temporary helper array + if (iBase) + { + // we can't use memset here we unsigned int needn' be 32 bits + for (auto &elem : avWasCopied) + { + elem = 0xffffffff; + } + } + + // output vectors + std::vector<aiFace> vFaces; + + // reserve enough storage for most cases + if (pMesh->HasPositions()) + { + pcMesh->mVertices = new aiVector3D[iOutVertexNum]; + } + if (pMesh->HasNormals()) + { + pcMesh->mNormals = new aiVector3D[iOutVertexNum]; + } + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents = new aiVector3D[iOutVertexNum]; + pcMesh->mBitangents = new aiVector3D[iOutVertexNum]; + } + for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) + { + pcMesh->mColors[c] = new aiColor4D[iOutVertexNum]; + } + for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) + { + pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; + pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum]; + } + vFaces.reserve(iEstimatedSize); + + // (we will also need to copy the array of indices) + while (iBase < pMesh->mNumFaces) + { + // allocate a new array + const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices; + + // doesn't catch degenerates but is quite fast + unsigned int iNeed = 0; + for (unsigned int v = 0; v < iNumIndices;++v) + { + unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; + + // check whether we do already have this vertex + if (0xFFFFFFFF == avWasCopied[iIndex]) + { + iNeed++; + } + } + if (pcMesh->mNumVertices + iNeed > iOutVertexNum) + { + // don't use this face + break; + } + + vFaces.push_back(aiFace()); + aiFace& rFace = vFaces.back(); + + // setup face type and number of indices + rFace.mNumIndices = iNumIndices; + rFace.mIndices = new unsigned int[iNumIndices]; + + // need to update the output primitive types + switch (rFace.mNumIndices) + { + case 1: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + } + + // and copy the contents of the old array, offset by current base + for (unsigned int v = 0; v < iNumIndices;++v) + { + unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; + + // check whether we do already have this vertex + if (0xFFFFFFFF != avWasCopied[iIndex]) + { + rFace.mIndices[v] = avWasCopied[iIndex]; + continue; + } + + // copy positions + pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]); + + // copy normals + if (pMesh->HasNormals()) + { + pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]); + } + + // copy tangents/bitangents + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]); + pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]); + } + + // texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (pMesh->HasTextureCoords( c)) + { + pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex]; + } + } + // vertex colors + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) + { + if (pMesh->HasVertexColors( c)) + { + pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex]; + } + } + // check whether we have bone weights assigned to this vertex + rFace.mIndices[v] = pcMesh->mNumVertices; + if (avPerVertexWeights) + { + VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ]; + if( !table.empty() ) + { + for (VertexWeightTable::const_iterator + iter = table.begin(); + iter != table.end();++iter) + { + // allocate the bone weight array if necessary + BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first]; + if (!pcWeightList) + { + pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList()); + } + pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second)); + } + } + } + + avWasCopied[iIndex] = pcMesh->mNumVertices; + pcMesh->mNumVertices++; + } + iBase++; + if(pcMesh->mNumVertices == iOutVertexNum) + { + // break here. The face is only added if it was complete + break; + } + } + + // check which bones we'll need to create for this submesh + if (pMesh->HasBones()) + { + aiBone** ppCurrent = pcMesh->mBones; + for (unsigned int k = 0; k < pMesh->mNumBones;++k) + { + // check whether the bone is existing + BoneWeightList* pcWeightList; + if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) + { + aiBone* pcOldBone = pMesh->mBones[k]; + aiBone* pcOut; + *ppCurrent++ = pcOut = new aiBone(); + pcOut->mName = aiString(pcOldBone->mName); + pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix; + pcOut->mNumWeights = (unsigned int)pcWeightList->size(); + pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights]; + + // copy the vertex weights + ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0), + pcOut->mNumWeights * sizeof(aiVertexWeight)); + + // delete the temporary bone weight list + delete pcWeightList; + pcMesh->mNumBones++; + } + } + } + + // copy the face list to the mesh + pcMesh->mFaces = new aiFace[vFaces.size()]; + pcMesh->mNumFaces = (unsigned int)vFaces.size(); + + for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) + pcMesh->mFaces[p] = vFaces[p]; + + // add the newly created mesh to the list + avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); + + if (iBase == pMesh->mNumFaces) + { + // have all faces ... finish the outer loop, too + break; + } + } + + // delete the per-vertex weight list again + delete[] avPerVertexWeights; + + // now delete the old mesh data + delete pMesh; + return; + } + avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); + return; } |