Просмотр исходного кода

Merge pull request #2446 from assimp/issue_2054

closes https://github.com/assimp/assimp/issues/2054: make empty bone …
Kim Kulling 6 лет назад
Родитель
Сommit
34084423ca

+ 1 - 1
code/ASELoader.cpp

@@ -1299,7 +1299,7 @@ void ASEImporter::BuildMaterialIndices()
         }
     }
 
-    // Dekete our temporary array
+    // Delete our temporary array
     delete[] pcIntMaterials;
 }
 

+ 0 - 1
code/ASEParser.cpp

@@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the ASE parser class
  */
 
-
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 

+ 5 - 5
code/ASEParser.h

@@ -188,10 +188,11 @@ struct Animation {
     } mRotationType, mScalingType, mPositionType;
 
     Animation() AI_NO_EXCEPT
-        :   mRotationType   (TRACK)
-        ,   mScalingType    (TRACK)
-        ,   mPositionType   (TRACK)
-    {}
+    :   mRotationType   (TRACK)
+    ,   mScalingType    (TRACK)
+    ,   mPositionType   (TRACK) {
+        // empty
+    }
 
     //! List of track rotation keyframes
     std::vector< aiQuatKey > akeyRotations;
@@ -243,7 +244,6 @@ struct BaseNode {
         mTargetPosition.x = qnan;
     }
 
-
     //! Name of the mesh
     std::string mName;
 

+ 13 - 11
code/FBXConverter.cpp

@@ -76,7 +76,7 @@ namespace Assimp {
 
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
 
-        FBXConverter::FBXConverter(aiScene* out, const Document& doc)
+        FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones)
         : defaultMaterialIndex()
         , lights()
         , cameras()
@@ -89,7 +89,8 @@ namespace Assimp {
         , mNodeNames()
         , anim_fps()
         , out(out)
-        , doc(doc) {
+        , doc(doc)
+        , mRemoveEmptyBones( removeEmptyBones ) {
             // animations need to be converted first since this will
             // populate the node_anim_chain_bits map, which is needed
             // to determine which nodes need to be generated.
@@ -387,6 +388,7 @@ namespace Assimp {
                 break;
             default:
                 ai_assert(false);
+                break;
             }
         }
 
@@ -977,7 +979,9 @@ namespace Assimp {
             unsigned int epcount = 0;
             for (unsigned i = 0; i < indices.size(); i++)
             {
-                if (indices[i] < 0) epcount++;
+                if (indices[i] < 0) {
+                    epcount++;
+                }
             }
             unsigned int pcount = static_cast<unsigned int>( indices.size() );
             unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
@@ -1407,7 +1411,7 @@ namespace Assimp {
 
                     const WeightIndexArray& indices = cluster->GetIndices();
 
-                    if (indices.empty()) {
+                    if (indices.empty() && mRemoveEmptyBones ) {
                         continue;
                     }
 
@@ -1439,13 +1443,11 @@ namespace Assimp {
 
                                 if (index_out_indices.back() == no_index_sentinel) {
                                     index_out_indices.back() = out_indices.size();
-
                                 }
 
                                 if (no_mat_check) {
                                     out_indices.push_back(out_idx[i]);
-                                }
-                                else {
+                                } else {
                                     // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
                                     const std::vector<unsigned int>::iterator it = std::lower_bound(
                                         outputVertStartIndices->begin(),
@@ -1461,11 +1463,11 @@ namespace Assimp {
                             }
                         }
                     }
-
+                    
                     // if we found at least one, generate the output bones
                     // XXX this could be heavily simplified by collecting the bone
                     // data in a single step.
-                    if (ok) {
+                    if (ok && mRemoveEmptyBones) {
                         ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
                             count_out_indices, node_global_transform);
                     }
@@ -3525,9 +3527,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
         }
 
         // ------------------------------------------------------------------------------------------------
-        void ConvertToAssimpScene(aiScene* out, const Document& doc)
+        void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones)
         {
-            FBXConverter converter(out, doc);
+            FBXConverter converter(out, doc, removeEmptyBones);
         }
 
     } // !FBX

+ 6 - 3
code/FBXConverter.h

@@ -79,9 +79,10 @@ class Document;
 /** 
  *  Convert a FBX #Document to #aiScene
  *  @param out Empty scene to be populated
- *  @param doc Parsed FBX document 
+ *  @param doc Parsed FBX document
+ *  @param removeEmptyBones Will remove bones, which do not have any references to vertices.
  */
-void ConvertToAssimpScene(aiScene* out, const Document& doc);
+void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones );
 
 /** Dummy class to encapsulate the conversion process */
 class FBXConverter {
@@ -112,7 +113,7 @@ public:
     };
 
 public:
-    FBXConverter(aiScene* out, const Document& doc);
+    FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones );
     ~FBXConverter();
 
 private:
@@ -453,6 +454,8 @@ private:
 
     aiScene* const out;
     const FBX::Document& doc;
+
+    bool mRemoveEmptyBones;
 };
 
 }

+ 20 - 14
code/FBXImportSettings.h

@@ -53,19 +53,21 @@ namespace FBX {
 struct ImportSettings
 {
     ImportSettings()
-        : strictMode(true)
-        , readAllLayers(true)
-        , readAllMaterials(false)
-        , readMaterials(true)
-        , readTextures(true)
-        , readCameras(true)
-        , readLights(true)
-        , readAnimations(true)
-        , readWeights(true)
-        , preservePivots(true)
-        , optimizeEmptyAnimationCurves(true)
-        , useLegacyEmbeddedTextureNaming(false)
-    {}
+    : strictMode(true)
+    , readAllLayers(true)
+    , readAllMaterials(false)
+    , readMaterials(true)
+    , readTextures(true)
+    , readCameras(true)
+    , readLights(true)
+    , readAnimations(true)
+    , readWeights(true)
+    , preservePivots(true)
+    , optimizeEmptyAnimationCurves(true)
+    , useLegacyEmbeddedTextureNaming(false)
+    , removeEmptyBones( true ) {
+        // empty
+    }
 
 
     /** enable strict mode:
@@ -141,8 +143,12 @@ struct ImportSettings
     bool optimizeEmptyAnimationCurves;
 
     /** use legacy naming for embedded textures eg: (*0, *1, *2)
-    **/
+    */
     bool useLegacyEmbeddedTextureNaming;
+
+    /** Empty bones shall be removed
+    */
+    bool removeEmptyBones;
 };
 
 

+ 2 - 1
code/FBXImporter.cpp

@@ -140,6 +140,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
     settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
     settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
     settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
+    settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -184,7 +185,7 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
         Document doc(parser,settings);
 
         // convert the FBX DOM to aiScene
-        ConvertToAssimpScene(pScene,doc);
+        ConvertToAssimpScene(pScene,doc, settings.removeEmptyBones);
 
         std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
     }

+ 13 - 20
code/ValidateDataStructure.cpp

@@ -46,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *    the data structure returned by Assimp.
  */
 
-
-
 // internal headers
 #include "ValidateDataStructure.h"
 #include <assimp/BaseImporter.h>
@@ -110,8 +108,8 @@ void ValidateDSProcess::ReportWarning(const char* msg,...)
 }
 
 // ------------------------------------------------------------------------------------------------
-inline int HasNameMatch(const aiString& in, aiNode* node)
-{
+inline
+int HasNameMatch(const aiString& in, aiNode* node) {
     int result = (node->mName == in ? 1 : 0 );
     for (unsigned int i = 0; i < node->mNumChildren;++i)    {
         result += HasNameMatch(in,node->mChildren[i]);
@@ -121,9 +119,8 @@ inline int HasNameMatch(const aiString& in, aiNode* node)
 
 // ------------------------------------------------------------------------------------------------
 template <typename T>
-inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
-    const char* firstName, const char* secondName)
-{
+inline
+void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* firstName, const char* secondName) {
     // validate all entries
     if (size)
     {
@@ -181,7 +178,8 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 inline
-void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) {
+void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName,
+        const char* secondName) {
     // validate all entries
     DoValidationEx(array,size,firstName,secondName);
 
@@ -201,9 +199,8 @@ void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size,
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void ValidateDSProcess::Execute( aiScene* pScene)
-{
-    this->mScene = pScene;
+void ValidateDSProcess::Execute( aiScene* pScene) {
+    mScene = pScene;
     ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin");
 
     // validate the node graph of the scene
@@ -516,13 +513,11 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
 }
 
 // ------------------------------------------------------------------------------------------------
-void ValidateDSProcess::Validate( const aiMesh* pMesh,
-    const aiBone* pBone,float* afSum)
-{
+void ValidateDSProcess::Validate( const aiMesh* pMesh, const aiBone* pBone,float* afSum) {
     this->Validate(&pBone->mName);
 
     if (!pBone->mNumWeights)    {
-        ReportError("aiBone::mNumWeights is zero");
+        //ReportError("aiBone::mNumWeights is zero");
     }
 
     // check whether all vertices affected by this bone are valid
@@ -563,9 +558,6 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
     else {
     	ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
     }
-
-    // Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
-    // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -746,8 +738,9 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
                     "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
             }
             break;
-        default: ;
-        };
+        default:
+            break;
+        }
     }
 
     if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) {

+ 5 - 1
include/assimp/config.h.in

@@ -657,7 +657,11 @@ enum aiComponent
 */
 #define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
 	"AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
-	
+
+// ---------------------------------------------------------------------------
+#define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \
+    "AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES"
+
 // ---------------------------------------------------------------------------
 /** @brief  Set the vertex animation keyframe to be imported
  *