Do not throw exception on empty mesh after removal of degenerates

Remove mesh instead. This keeps one edge case open: nodes without mesh
references. They are kept as it is for now (they may stilol contain
transformations and child references).
pull/1965/head
Daniel Löber 2018-05-16 11:02:07 +02:00
parent 8f587b9750
commit 46ed73c768
2 changed files with 54 additions and 5 deletions

View File

@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
//remove mesh at position 'index' from the scene
static void removeMesh(aiScene* pScene, unsigned const index);
//correct node indices to meshes and remove references to deleted mesh
static void updateSceneGraph(aiNode* pNode, unsigned const index);
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindDegeneratesProcess::FindDegeneratesProcess()
@ -87,11 +92,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
void FindDegeneratesProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
ExecuteOnMesh( pScene->mMeshes[ i ] );
if (ExecuteOnMesh(pScene->mMeshes[i])) {
removeMesh(pScene, i);
--i; //the current i is removed, do not skip the next one
}
}
ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
}
static void removeMesh(aiScene* pScene, unsigned const index) {
//we start at index and copy the pointers one position forward
//save the mesh pointer to delete it later
auto delete_me = pScene->mMeshes[index];
for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) {
pScene->mMeshes[i] = pScene->mMeshes[i+1];
}
pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr;
--(pScene->mNumMeshes);
delete delete_me;
//removing a mesh also requires updating all references to it in the scene graph
updateSceneGraph(pScene->mRootNode, index);
}
static void updateSceneGraph(aiNode* pNode, unsigned const index) {
for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
if (pNode->mMeshes[i] > index) {
--(pNode->mMeshes[i]);
continue;
}
if (pNode->mMeshes[i] == index) {
for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) {
pNode->mMeshes[j] = pNode->mMeshes[j+1];
}
--(pNode->mNumMeshes);
--i;
continue;
}
}
//recurse to all children
for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
updateSceneGraph(pNode->mChildren[i], index);
}
}
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
ai_real s = (a + b + c) / 2;
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
@ -125,7 +169,7 @@ static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
mesh->mPrimitiveTypes = 0;
std::vector<bool> remove_me;
@ -227,19 +271,22 @@ evil_jump_outside:
if (&face_src != &face_dest) {
// clear source
face_src.mNumIndices = 0;
face_src.mIndices = NULL;
face_src.mIndices = nullptr;
}
}
else {
// Otherwise delete it if we don't need this face
delete[] face_src.mIndices;
face_src.mIndices = NULL;
face_src.mIndices = nullptr;
face_src.mNumIndices = 0;
}
}
// Just leave the rest of the array unreferenced, we don't care for now
mesh->mNumFaces = n;
if (!mesh->mNumFaces) {
//The whole mesh consists of degenerated faces
//signal upward, that this mesh should be deleted.
return true;
// WTF!?
// OK ... for completeness and because I'm not yet tired,
// let's write code that will hopefully never be called
@ -253,4 +300,5 @@ evil_jump_outside:
if (deg && !DefaultLogger::isNullLogger()) {
ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
}
return false;
}

View File

@ -74,7 +74,8 @@ public:
// -------------------------------------------------------------------
// Execute step on a given mesh
void ExecuteOnMesh( aiMesh* mesh);
///@returns true if the current mesh should be deleted, false otherwise
bool ExecuteOnMesh( aiMesh* mesh);
// -------------------------------------------------------------------
/// @brief Enable the instant removal of degenerated primitives