From 5d6fc7a5574e16d276159cca6952542689c6d765 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Jan 2019 21:05:58 +0100 Subject: [PATCH 1/2] Closes https://github.com/assimp/assimp/issues/2251: introduce AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS to avoid removing textures. --- code/FindInvalidDataProcess.cpp | 36 +++++++++++++++++++-------------- code/FindInvalidDataProcess.h | 20 +++++++++--------- include/assimp/config.h.in | 7 +++++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index b1a296a54..19dd420a1 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "FindInvalidDataProcess.h" #include "ProcessHelper.h" + #include #include #include @@ -60,8 +61,8 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindInvalidDataProcess::FindInvalidDataProcess() - : configEpsilon(0.0) -{ +: configEpsilon(0.0) +, mIgnoreTexCoods( false ){ // nothing to do here } @@ -85,6 +86,7 @@ void FindInvalidDataProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f)); + mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false); } // ------------------------------------------------------------------------------------------------ @@ -171,7 +173,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ template -inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, +inline +const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) { return NULL; @@ -179,7 +182,8 @@ inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/ // ------------------------------------------------------------------------------------------------ template <> -inline const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, +inline +const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) { bool b = false; @@ -251,8 +255,8 @@ bool EpsilonCompare(const aiQuatKey& n, const aiQuatKey& s, ai_real e // ------------------------------------------------------------------------------------------------ template -inline bool AllIdentical(T* in, unsigned int num, ai_real epsilon) -{ +inline +bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { if (num <= 1) { return true; } @@ -361,17 +365,19 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) // process texture coordinates for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) { - if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) { - pMesh->mNumUVComponents[i] = 0; + if (!mIgnoreTexCoods) { + if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) { + pMesh->mNumUVComponents[i] = 0; - // delete all subsequent texture coordinate sets. - for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { - delete[] pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[a] = NULL; - pMesh->mNumUVComponents[a] = 0; + // delete all subsequent texture coordinate sets. + for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + delete[] pMesh->mTextureCoords[a]; + pMesh->mTextureCoords[a] = NULL; + pMesh->mNumUVComponents[a] = 0; + } + + ret = true; } - - ret = true; } } diff --git a/code/FindInvalidDataProcess.h b/code/FindInvalidDataProcess.h index 00dfef145..f5a49f496 100644 --- a/code/FindInvalidDataProcess.h +++ b/code/FindInvalidDataProcess.h @@ -41,7 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines a post processing step to search an importer's output - for data that is obviously invalid */ + * for data that is obviously invalid + */ #ifndef AI_FINDINVALIDDATA_H_INC #define AI_FINDINVALIDDATA_H_INC @@ -50,7 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include struct aiMesh; + class FindInvalidDataProcessTest; + namespace Assimp { // --------------------------------------------------------------------------- @@ -59,15 +62,11 @@ namespace Assimp { * * Originally this was a workaround for some models written by Blender * which have zero normal vectors. */ -class ASSIMP_API FindInvalidDataProcess : public BaseProcess -{ +class ASSIMP_API FindInvalidDataProcess : public BaseProcess { public: - FindInvalidDataProcess(); ~FindInvalidDataProcess(); -public: - // ------------------------------------------------------------------- // bool IsActive( unsigned int pFlags) const; @@ -80,26 +79,25 @@ public: // Run the step void Execute( aiScene* pScene); -public: - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given mesh + /** Executes the post-processing step on the given mesh * @param pMesh The mesh to process. * @return 0 - nothing, 1 - removed sth, 2 - please delete me */ int ProcessMesh( aiMesh* pMesh); // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given animation + /** Executes the post-processing step on the given animation * @param anim The animation to process. */ void ProcessAnimation (aiAnimation* anim); // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given anim channel + /** Executes the post-processing step on the given anim channel * @param anim The animation channel to process.*/ void ProcessAnimationChannel (aiNodeAnim* anim); private: ai_real configEpsilon; + bool mIgnoreTexCoods; }; } // end of namespace Assimp diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index fd828bc6e..a37ff0b8c 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -498,6 +498,13 @@ enum aiComponent #define AI_CONFIG_PP_FID_ANIM_ACCURACY \ "PP_FID_ANIM_ACCURACY" +// --------------------------------------------------------------------------- +/** @brief Input parameter to the #aiProcess_FindInvalidData step: + * Set to true to ignore texture coordinates. This may be useful if you have + * to assign different kind of textures like one for the summer or one for the winter. + */ +#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \ + "PP_FID_IGNORE_TEXTURECOORDS" // TransformUVCoords evaluates UV scalings #define AI_UVTRAFO_SCALING 0x1 From b35331b92ae90b6d7d5932721f203a7bd6bb2933 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 28 Jan 2019 10:50:36 +0100 Subject: [PATCH 2/2] Update FindInvalidDataProcess.cpp -Fix some review findings. --- code/FindInvalidDataProcess.cpp | 80 ++++++++++++++------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index 19dd420a1..c775187e9 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -68,22 +68,19 @@ FindInvalidDataProcess::FindInvalidDataProcess() // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FindInvalidDataProcess::~FindInvalidDataProcess() -{ +FindInvalidDataProcess::~FindInvalidDataProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const -{ +bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindInvalidData); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindInvalidDataProcess::SetupProperties(const Importer* pImp) -{ +void FindInvalidDataProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f)); mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false); @@ -91,8 +88,7 @@ void FindInvalidDataProcess::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Update mesh references in the node graph -void UpdateMeshReferences(aiNode* node, const std::vector& meshMapping) -{ +void UpdateMeshReferences(aiNode* node, const std::vector& meshMapping) { if (node->mNumMeshes) { unsigned int out = 0; for (unsigned int a = 0; a < node->mNumMeshes;++a) { @@ -118,8 +114,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector& meshMap // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindInvalidDataProcess::Execute( aiScene* pScene) -{ +void FindInvalidDataProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin"); bool out = false; @@ -175,17 +170,16 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) template inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, - const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) + const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) { - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ template <> inline const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, - const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) -{ + const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) { bool b = false; unsigned int cnt = 0; for (unsigned int i = 0; i < size;++i) { @@ -207,14 +201,14 @@ const char* ValidateArrayContents(const aiVector3D* arr, unsigned in if (cnt > 1 && !b && !mayBeIdentical) { return "All vectors are identical"; } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ template -inline bool ProcessArray(T*& in, unsigned int num,const char* name, - const std::vector& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) -{ +inline +bool ProcessArray(T*& in, unsigned int num,const char* name, + const std::vector& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) { const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero); if (err) { ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err); @@ -261,17 +255,14 @@ bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { return true; } - if (epsilon > 0.f) { + if (fabs(epsilon) > 0.f) { for (unsigned int i = 0; i < num-1;++i) { - if (!EpsilonCompare(in[i],in[i+1],epsilon)) { return false; } } - } - else { + } else { for (unsigned int i = 0; i < num-1;++i) { - if (in[i] != in[i+1]) { return false; } @@ -282,27 +273,24 @@ bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { // ------------------------------------------------------------------------------------------------ // Search an animation for invalid content -void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) -{ +void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) { // Process all animation channels - for (unsigned int a = 0; a < anim->mNumChannels;++a) { + for ( unsigned int a = 0; a < anim->mNumChannels; ++a ) { ProcessAnimationChannel( anim->mChannels[a]); } } // ------------------------------------------------------------------------------------------------ -void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) -{ - int i = 0; - - // ScenePreprocessor's work ... - ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys)); +void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) { + ai_assert( 0 != anim->mPositionKeys ); + ai_assert( 0 != anim->mRotationKeys ); + ai_assert( 0 != anim->mScalingKeys ); // Check whether all values in a tracks are identical - in this case // we can remove al keys except one. // POSITIONS - if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) - { + int i = 0; + if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) { aiVectorKey v = anim->mPositionKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -313,8 +301,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) } // ROTATIONS - if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) - { + if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) { aiQuatKey v = anim->mRotationKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -325,8 +312,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) } // SCALINGS - if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) - { + if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) { aiVectorKey v = anim->mScalingKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -335,8 +321,9 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) anim->mScalingKeys[0] = v; i = 1; } - if (1 == i) + if ( 1 == i ) { ASSIMP_LOG_WARN("Simplified dummy tracks with just one key"); + } } // ------------------------------------------------------------------------------------------------ @@ -364,8 +351,8 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) } // process texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) { - if (!mIgnoreTexCoods) { + if (!mIgnoreTexCoods) { + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) { if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) { pMesh->mNumUVComponents[i] = 0; @@ -394,13 +381,11 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes) { // We need to update the lookup-table - for (unsigned int m = 0; m < pMesh->mNumFaces;++m) - { - const aiFace& f = pMesh->mFaces[m]; + for (unsigned int m = 0; m < pMesh->mNumFaces;++m) { + const aiFace& f = pMesh->mFaces[ m ]; if (f.mNumIndices < 3) { dirtyMask[f.mIndices[0]] = true; - if (f.mNumIndices == 2) { dirtyMask[f.mIndices[1]] = true; } @@ -409,7 +394,9 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) } // Normals, tangents and bitangents are undefined for // the whole mesh (and should not even be there) - else return ret; + else { + return ret; + } } // Process mesh normals @@ -432,5 +419,4 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) return ret ? 1 : 0; } - #endif // !! ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS