From 193b02cdac6cf38ad87d57c20e8e19da33157e0f Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 9 Dec 2019 10:42:50 +0000 Subject: [PATCH] Odd negative scale: OptimizeGraph OptimizeGraph postprocessing now reverses face order when node scale is mirroring. Fixes flip to backfacing in models that mirrored some nodes. (Odd count of negative scale components, negative determinant) --- code/PostProcessing/ConvertToLHProcess.h | 5 ++-- code/PostProcessing/OptimizeGraph.cpp | 32 ++++++++++++++++-------- code/PostProcessing/OptimizeGraph.h | 6 ++--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/code/PostProcessing/ConvertToLHProcess.h b/code/PostProcessing/ConvertToLHProcess.h index f32b91fc3..0c4a3a091 100644 --- a/code/PostProcessing/ConvertToLHProcess.h +++ b/code/PostProcessing/ConvertToLHProcess.h @@ -137,8 +137,9 @@ public: // ------------------------------------------------------------------- void Execute( aiScene* pScene); -protected: - void ProcessMesh( aiMesh* pMesh); +public: + /** Some other types of post-processing require winding order flips */ + static void ProcessMesh( aiMesh* pMesh); }; // --------------------------------------------------------------------------- diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index 709f465e2..43bd7a3ee 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OptimizeGraph.h" #include "ProcessHelper.h" +#include "ConvertToLHProcess.h" #include #include #include @@ -135,7 +136,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n nodes.push_back(nd); // Now check for possible optimizations in our list of child nodes. join as many as possible - aiNode *join_master = NULL; + aiNode *join_master = nullptr; aiMatrix4x4 inv; const LockedSetType::const_iterator end = locked.end(); @@ -172,7 +173,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++); unsigned int out_meshes = 0; - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { + for (std::list::const_iterator it = join.cbegin(); it != join.cend(); ++it) { out_meshes += (*it)->mNumMeshes; } @@ -183,17 +184,26 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n *tmp++ = join_master->mMeshes[n]; } - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { - for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) { + for (const aiNode *join_node : join) { + for (unsigned int n = 0; n < join_node->mNumMeshes; ++n) { - *tmp = (*it)->mMeshes[n]; + *tmp = join_node->mMeshes[n]; aiMesh *mesh = mScene->mMeshes[*tmp++]; + // Assume the transformation is affine // manually move the mesh into the right coordinate system - const aiMatrix3x3 IT = aiMatrix3x3((*it)->mTransformation).Inverse().Transpose(); + + // Check for odd negative scale (mirror) + if (join_node->mTransformation.Determinant() < 0) { + // Reverse the mesh face winding order + FlipWindingOrderProcess::ProcessMesh(mesh); + } + + // Update positions, normals and tangents + const aiMatrix3x3 IT = aiMatrix3x3(join_node->mTransformation).Inverse().Transpose(); for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - mesh->mVertices[a] *= (*it)->mTransformation; + mesh->mVertices[a] *= join_node->mTransformation; if (mesh->HasNormals()) mesh->mNormals[a] *= IT; @@ -204,7 +214,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n } } } - delete *it; // bye, node + delete join_node; // bye, node } delete[] join_master->mMeshes; join_master->mMeshes = meshes; @@ -304,7 +314,7 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) { ai_assert(nodes.size() == 1); if (dummy_root->mNumChildren == 0) { - pScene->mRootNode = NULL; + pScene->mRootNode = nullptr; throw DeadlyImportError("After optimizing the scene graph, no data remains"); } @@ -318,11 +328,11 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) { // Remove the dummy root node again. pScene->mRootNode = dummy_root->mChildren[0]; - dummy_root->mChildren[0] = NULL; + dummy_root->mChildren[0] = nullptr; delete dummy_root; } - pScene->mRootNode->mParent = NULL; + pScene->mRootNode->mParent = nullptr; if (!DefaultLogger::isNullLogger()) { if (nodes_in != nodes_out) { ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); diff --git a/code/PostProcessing/OptimizeGraph.h b/code/PostProcessing/OptimizeGraph.h index 82cc5db3f..d2a6de9a2 100644 --- a/code/PostProcessing/OptimizeGraph.h +++ b/code/PostProcessing/OptimizeGraph.h @@ -75,13 +75,13 @@ public: ~OptimizeGraphProcess(); // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; + bool IsActive( unsigned int pFlags) const override; // ------------------------------------------------------------------- - void Execute( aiScene* pScene); + void Execute( aiScene* pScene) override; // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); + void SetupProperties(const Importer* pImp) override; // ------------------------------------------------------------------- /** @brief Add a list of node names to be locked and not modified.