123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /** @file Implementation of the SplitLargeMeshes postprocessing step
- */
- #include "SplitLargeMeshes.h"
- #include "../include/aiPostProcess.h"
- #include "../include/aiMesh.h"
- #include "../include/aiScene.h"
- using namespace Assimp;
- // Constructor to be privately used by Importer
- SplitLargeMeshesProcess::SplitLargeMeshesProcess()
- {
- }
- // Destructor, private as well
- SplitLargeMeshesProcess::~SplitLargeMeshesProcess()
- {
- // nothing to do here
- }
- // ------------------------------------------------------------------------------------------------
- // Returns whether the processing step is present in the given flag field.
- bool SplitLargeMeshesProcess::IsActive( unsigned int pFlags) const
- {
- return (pFlags & aiProcess_SplitLargeMeshes) != 0;
- }
- // ------------------------------------------------------------------------------------------------
- // Executes the post processing step on the given imported data.
- void SplitLargeMeshesProcess::Execute( aiScene* pScene)
- {
- 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 splitted. rebuild the mesh list
- delete[] pScene->mMeshes;
- pScene->mNumMeshes = 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);
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- // Update a node after some meshes have been split
- void SplitLargeMeshesProcess::UpdateNode(aiNode* pcNode,
- const std::vector<std::pair<aiMesh*, unsigned int> >& avList)
- {
- // for every index in out list build a new entry
- // TODO: Currently O(n^2)
- 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 = 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)
- {
- this->UpdateNode ( pcNode->mChildren[i], avList );
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- // Executes the post processing step on the given imported data.
- void SplitLargeMeshesProcess::SplitMesh(
- unsigned int a,
- aiMesh* pMesh,
- std::vector<std::pair<aiMesh*, unsigned int> >& avList)
- {
- // TODO: Mesh splitting is currently not supported for meshes
- // containing bones
- if (pMesh->mNumVertices > AI_SLM_MAX_VERTICES && 0 == pMesh->mNumBones)
- {
- // we need to split this mesh into sub meshes
- // determine the size of a submesh
- const unsigned int iSubMeshes = (pMesh->mNumVertices / AI_SLM_MAX_VERTICES) + 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;
- 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];
- }
- }
- // (we will also need to copy the array of indices)
- for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
- {
- pcMesh->mFaces[p].mNumIndices = 3;
- // allocate a new array
- unsigned int* pi = pMesh->mFaces[p + iBase].mIndices;
- pcMesh->mFaces[p].mIndices = new unsigned int[3];
- // and copy the contents of the old array, offset by current base
- for (unsigned int v = 0; v < 3;++v)
- {
- unsigned int iIndex = pMesh->mFaces[p+iBase].mIndices[v];
- unsigned int iIndexOut = p*3 + v;
- pcMesh->mFaces[p].mIndices[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;
- }
|