Merge pull request #1965 from loebl/bug/exception-on-empty-mesh-after-degenerate-removal
Bug/exception on empty mesh after degenerate removalpull/1971/head
commit
f8c4891acf
|
@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace Assimp;
|
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
|
// Constructor to be privately used by Importer
|
||||||
FindDegeneratesProcess::FindDegeneratesProcess()
|
FindDegeneratesProcess::FindDegeneratesProcess()
|
||||||
|
@ -87,11 +92,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
|
||||||
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){
|
||||||
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");
|
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 ) {
|
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
|
||||||
ai_real s = (a + b + c) / 2;
|
ai_real s = (a + b + c) / 2;
|
||||||
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
|
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
|
// Executes the post processing step on the given imported mesh
|
||||||
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
||||||
mesh->mPrimitiveTypes = 0;
|
mesh->mPrimitiveTypes = 0;
|
||||||
|
|
||||||
std::vector<bool> remove_me;
|
std::vector<bool> remove_me;
|
||||||
|
@ -227,30 +271,28 @@ evil_jump_outside:
|
||||||
if (&face_src != &face_dest) {
|
if (&face_src != &face_dest) {
|
||||||
// clear source
|
// clear source
|
||||||
face_src.mNumIndices = 0;
|
face_src.mNumIndices = 0;
|
||||||
face_src.mIndices = NULL;
|
face_src.mIndices = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Otherwise delete it if we don't need this face
|
// Otherwise delete it if we don't need this face
|
||||||
delete[] face_src.mIndices;
|
delete[] face_src.mIndices;
|
||||||
face_src.mIndices = NULL;
|
face_src.mIndices = nullptr;
|
||||||
face_src.mNumIndices = 0;
|
face_src.mNumIndices = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Just leave the rest of the array unreferenced, we don't care for now
|
// Just leave the rest of the array unreferenced, we don't care for now
|
||||||
mesh->mNumFaces = n;
|
mesh->mNumFaces = n;
|
||||||
if (!mesh->mNumFaces) {
|
if (!mesh->mNumFaces) {
|
||||||
// WTF!?
|
//The whole mesh consists of degenerated faces
|
||||||
// OK ... for completeness and because I'm not yet tired,
|
//signal upward, that this mesh should be deleted.
|
||||||
// let's write code that will hopefully never be called
|
ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
|
||||||
// (famous last words)
|
return true;
|
||||||
|
|
||||||
// OK ... bad idea.
|
|
||||||
throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deg && !DefaultLogger::isNullLogger()) {
|
if (deg && !DefaultLogger::isNullLogger()) {
|
||||||
ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
|
ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Execute step on a given mesh
|
// 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
|
/// @brief Enable the instant removal of degenerated primitives
|
||||||
|
|
Loading…
Reference in New Issue