123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- Copyright (c) 2006-2020, 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
- 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 assimp team, nor the names of its
- contributors may be used to endorse or promote products
- 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
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- 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
- 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.
- ----------------------------------------------------------------------
- */
- /**
- * @file Implementation of the SplitLargeMeshes postprocessing step
- */
- // internal headers of the post-processing framework
- #include "SplitLargeMeshes.h"
- #include "ProcessHelper.h"
- using namespace Assimp;
- // ------------------------------------------------------------------------------------------------
- SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() {
- LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
- }
- // ------------------------------------------------------------------------------------------------
- SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() {
- // 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;
- }
- // ------------------------------------------------------------------------------------------------
- // Executes the post processing step on the given imported data.
- void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) {
- if (0xffffffff == this->LIMIT || nullptr == pScene ) {
- return;
- }
- ASSIMP_LOG_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);
- ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
- } else {
- ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
- }
- }
- // ------------------------------------------------------------------------------------------------
- // Setup properties
- 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);
- }
- // ------------------------------------------------------------------------------------------------
- // Update a node after some meshes have been split
- void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
- 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 );
- }
- }
- // ------------------------------------------------------------------------------------------------
- // 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) {
- if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) {
- ASSIMP_LOG_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 != nullptr) {
- 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 = nullptr;
- } 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 != nullptr) {
- 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));
- }
- }
- // ------------------------------------------------------------------------------------------------
- SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() {
- LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
- }
- // ------------------------------------------------------------------------------------------------
- SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() {
- // 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;
- }
- // ------------------------------------------------------------------------------------------------
- // Executes the post processing step on the given imported data.
- void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) {
- if (0xffffffff == this->LIMIT || nullptr == pScene ) {
- return;
- }
- ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin");
- 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
- 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);
- ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
- } else {
- ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
- }
- }
- // ------------------------------------------------------------------------------------------------
- // Setup properties
- void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) {
- 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) {
- 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;
- // 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 (nullptr == 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;
- pcWeightList = (BoneWeightList *)pcMesh->mBones[k];
- if (nullptr != pcWeightList) {
- aiBone *pcOldBone = pMesh->mBones[k];
- aiBone* pcOut( nullptr );
- *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));
- }
|