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)pull/2818/head
parent
463573c771
commit
193b02cdac
|
@ -137,8 +137,9 @@ public:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
void Execute( aiScene* pScene);
|
void Execute( aiScene* pScene);
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
void ProcessMesh( aiMesh* pMesh);
|
/** Some other types of post-processing require winding order flips */
|
||||||
|
static void ProcessMesh( aiMesh* pMesh);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "OptimizeGraph.h"
|
#include "OptimizeGraph.h"
|
||||||
#include "ProcessHelper.h"
|
#include "ProcessHelper.h"
|
||||||
|
#include "ConvertToLHProcess.h"
|
||||||
#include <assimp/Exceptional.h>
|
#include <assimp/Exceptional.h>
|
||||||
#include <assimp/SceneCombiner.h>
|
#include <assimp/SceneCombiner.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -135,7 +136,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
|
||||||
nodes.push_back(nd);
|
nodes.push_back(nd);
|
||||||
|
|
||||||
// Now check for possible optimizations in our list of child nodes. join as many as possible
|
// 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;
|
aiMatrix4x4 inv;
|
||||||
|
|
||||||
const LockedSetType::const_iterator end = locked.end();
|
const LockedSetType::const_iterator end = locked.end();
|
||||||
|
@ -172,7 +173,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
|
||||||
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++);
|
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++);
|
||||||
|
|
||||||
unsigned int out_meshes = 0;
|
unsigned int out_meshes = 0;
|
||||||
for (std::list<aiNode *>::iterator it = join.begin(); it != join.end(); ++it) {
|
for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++it) {
|
||||||
out_meshes += (*it)->mNumMeshes;
|
out_meshes += (*it)->mNumMeshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,17 +184,26 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
|
||||||
*tmp++ = join_master->mMeshes[n];
|
*tmp++ = join_master->mMeshes[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::list<aiNode *>::iterator it = join.begin(); it != join.end(); ++it) {
|
for (const aiNode *join_node : join) {
|
||||||
for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
|
for (unsigned int n = 0; n < join_node->mNumMeshes; ++n) {
|
||||||
|
|
||||||
*tmp = (*it)->mMeshes[n];
|
*tmp = join_node->mMeshes[n];
|
||||||
aiMesh *mesh = mScene->mMeshes[*tmp++];
|
aiMesh *mesh = mScene->mMeshes[*tmp++];
|
||||||
|
|
||||||
|
// Assume the transformation is affine
|
||||||
// manually move the mesh into the right coordinate system
|
// 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) {
|
for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
|
||||||
|
|
||||||
mesh->mVertices[a] *= (*it)->mTransformation;
|
mesh->mVertices[a] *= join_node->mTransformation;
|
||||||
|
|
||||||
if (mesh->HasNormals())
|
if (mesh->HasNormals())
|
||||||
mesh->mNormals[a] *= IT;
|
mesh->mNormals[a] *= IT;
|
||||||
|
@ -204,7 +214,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete *it; // bye, node
|
delete join_node; // bye, node
|
||||||
}
|
}
|
||||||
delete[] join_master->mMeshes;
|
delete[] join_master->mMeshes;
|
||||||
join_master->mMeshes = meshes;
|
join_master->mMeshes = meshes;
|
||||||
|
@ -304,7 +314,7 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) {
|
||||||
ai_assert(nodes.size() == 1);
|
ai_assert(nodes.size() == 1);
|
||||||
|
|
||||||
if (dummy_root->mNumChildren == 0) {
|
if (dummy_root->mNumChildren == 0) {
|
||||||
pScene->mRootNode = NULL;
|
pScene->mRootNode = nullptr;
|
||||||
throw DeadlyImportError("After optimizing the scene graph, no data remains");
|
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.
|
// Remove the dummy root node again.
|
||||||
pScene->mRootNode = dummy_root->mChildren[0];
|
pScene->mRootNode = dummy_root->mChildren[0];
|
||||||
|
|
||||||
dummy_root->mChildren[0] = NULL;
|
dummy_root->mChildren[0] = nullptr;
|
||||||
delete dummy_root;
|
delete dummy_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
pScene->mRootNode->mParent = NULL;
|
pScene->mRootNode->mParent = nullptr;
|
||||||
if (!DefaultLogger::isNullLogger()) {
|
if (!DefaultLogger::isNullLogger()) {
|
||||||
if (nodes_in != nodes_out) {
|
if (nodes_in != nodes_out) {
|
||||||
ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out);
|
ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out);
|
||||||
|
|
|
@ -75,13 +75,13 @@ public:
|
||||||
~OptimizeGraphProcess();
|
~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.
|
/** @brief Add a list of node names to be locked and not modified.
|
||||||
|
|
Loading…
Reference in New Issue