瀏覽代碼

FBX Importer: apply inverse of geometric transform to child nodes.

Tommy 7 年之前
父節點
當前提交
fb213e4bac
共有 2 個文件被更改,包括 66 次插入7 次删除
  1. 61 5
      code/FBXConverter.cpp
  2. 5 2
      code/FBXConverter.h

+ 61 - 5
code/FBXConverter.cpp

@@ -142,6 +142,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
     nodes.reserve( conns.size() );
 
     std::vector<aiNode*> nodes_chain;
+    std::vector<aiNode*> post_nodes_chain;
 
     try {
         for( const Connection* con : conns ) {
@@ -161,6 +162,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
 
             if ( model ) {
                 nodes_chain.clear();
+                post_nodes_chain.clear();
 
                 aiMatrix4x4 new_abs_transform = parent_transform;
 
@@ -168,7 +170,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
                 // assimp (or rather: the complicated transformation chain that
                 // is employed by fbx) means that we may need multiple aiNode's
                 // to represent a fbx node's transformation.
-                GenerateTransformationNodeChain( *model, nodes_chain );
+                GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain );
 
                 ai_assert( nodes_chain.size() );
 
@@ -213,8 +215,25 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
                 // attach geometry
                 ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
 
+                // now link the geometric transform inverse nodes,
+                // before we attach any child nodes
+                for( aiNode* postnode : post_nodes_chain ) {
+                    ai_assert( postnode );
+
+                    if ( last_parent != &parent ) {
+                        last_parent->mNumChildren = 1;
+                        last_parent->mChildren = new aiNode*[ 1 ];
+                        last_parent->mChildren[ 0 ] = postnode;
+                    }
+
+                    postnode->mParent = last_parent;
+                    last_parent = postnode;
+
+                    new_abs_transform *= postnode->mTransformation;
+                }
+
                 // attach sub-nodes
-                ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform );
+                ConvertNodes( model->ID(), *last_parent, new_abs_transform );
 
                 if ( doc.Settings().readLights ) {
                     ConvertLights( *model );
@@ -396,6 +415,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
         return "GeometricRotation";
     case TransformationComp_GeometricTranslation:
         return "GeometricTranslation";
+    case TransformationComp_GeometricScalingInverse:
+        return "GeometricScalingInverse";
+    case TransformationComp_GeometricRotationInverse:
+        return "GeometricRotationInverse";
+    case TransformationComp_GeometricTranslationInverse:
+        return "GeometricTranslationInverse";
     case TransformationComp_MAXIMUM: // this is to silence compiler warnings
     default:
         break;
@@ -437,6 +462,12 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp )
         return "GeometricRotation";
     case TransformationComp_GeometricTranslation:
         return "GeometricTranslation";
+    case TransformationComp_GeometricScalingInverse:
+        return "GeometricScalingInverse";
+    case TransformationComp_GeometricRotationInverse:
+        return "GeometricRotationInverse";
+    case TransformationComp_GeometricTranslationInverse:
+        return "GeometricTranslationInverse";
     case TransformationComp_MAXIMUM: // this is to silence compiler warnings
         break;
     }
@@ -570,7 +601,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
     return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
 }
 
-void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
+void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes )
 {
     const PropertyTable& props = model.Props();
     const Model::RotOrder rot = model.RotationOrder();
@@ -646,16 +677,33 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
     const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>( props, "GeometricScaling", ok );
     if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) {
         aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
+        aiVector3D GeometricScalingInverse = GeometricScaling;
+        bool canscale = true;
+        for (size_t i = 0; i < 3; ++i) {
+            if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
+                GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
+            } else {
+                FBXImporter::LogError( "cannot invert geometric scaling matrix with a 0.0 scale component" );
+                canscale = false;
+                break;
+            }
+        }
+        if (canscale) {
+            aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] );
+        }
     }
 
     const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>( props, "GeometricRotation", ok );
     if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) {
         GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] );
+        GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] );
+        chain[ TransformationComp_GeometricRotationInverse ].Inverse();
     }
 
     const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>( props, "GeometricTranslation", ok );
     if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) {
         aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] );
+        aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] );
     }
 
     // is_complex needs to be consistent with NeedsComplexTransformationChain()
@@ -690,10 +738,18 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
             }
 
             aiNode* nd = new aiNode();
-            output_nodes.push_back( nd );
-
             nd->mName.Set( NameTransformationChainNode( name, comp ) );
             nd->mTransformation = chain[ i ];
+
+            // geometric inverses go in a post-node chain
+            if ( comp == TransformationComp_GeometricScalingInverse ||
+                 comp == TransformationComp_GeometricRotationInverse ||
+                 comp == TransformationComp_GeometricTranslationInverse
+            ) {
+                post_output_nodes.push_back( nd );
+            } else {
+                output_nodes.push_back( nd );
+            }
         }
 
         ai_assert( output_nodes.size() );

+ 5 - 2
code/FBXConverter.h

@@ -82,7 +82,10 @@ public:
     *  The different parts that make up the final local transformation of a fbx-node
     */
     enum TransformationComp {
-        TransformationComp_Translation = 0,
+        TransformationComp_GeometricScalingInverse = 0,
+        TransformationComp_GeometricRotationInverse,
+        TransformationComp_GeometricTranslationInverse,
+        TransformationComp_Translation,
         TransformationComp_RotationOffset,
         TransformationComp_RotationPivot,
         TransformationComp_PreRotation,
@@ -153,7 +156,7 @@ private:
     /**
     *  note: memory for output_nodes will be managed by the caller
     */
-    void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes);
+    void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
 
     // ------------------------------------------------------------------------------------------------
     void SetupNodeMetadata(const Model& model, aiNode& nd);