瀏覽代碼

Merge branch 'master' into kimkulling_dev

Kim Kulling 5 年之前
父節點
當前提交
b1165cff28
共有 2 個文件被更改,包括 94 次插入181 次删除
  1. 91 162
      code/FBX/FBXConverter.cpp
  2. 3 19
      code/FBX/FBXConverter.h

+ 91 - 162
code/FBX/FBXConverter.cpp

@@ -655,7 +655,8 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);
 
-        if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
+        if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
+            comp == TransformationComp_PreRotation || comp == TransformationComp_PostRotation) {
             continue;
         }
 
@@ -2739,15 +2740,12 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
     // be invoked _later_ (animations come first). If this node has only rotation,
     // scaling and translation _and_ there are no animated other components either,
     // we can use a single node and also a single node animation channel.
-    if (!has_complex && !NeedsComplexTransformationChain(target)) {
-
-        aiNodeAnim *const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
+    if( !has_complex && !NeedsComplexTransformationChain(target)) {
+        aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
                 node_property_map.end(),
-                layer_map,
                 start, stop,
                 max_time,
-                min_time,
-                true // input is TRS order, assimp is SRT
+                min_time
         );
 
         ai_assert(nd);
@@ -3021,133 +3019,121 @@ aiNodeAnim *FBXConverter::GenerateTranslationNodeAnim(const std::string &name,
     return na.release();
 }
 
-aiNodeAnim *FBXConverter::GenerateSimpleNodeAnim(const std::string &name,
-        const Model &target,
+aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
+        const Model& target,
         NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
-        NodeMap::const_iterator iter_end,
-        const LayerMap &layer_map,
+        NodeMap::const_iterator iterEnd,
         int64_t start, int64_t stop,
-        double &max_time,
-        double &min_time,
-        bool reverse_order)
-
+        double& maxTime,
+        double& minTime)
 {
     std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
     na->mNodeName.Set(name);
 
     const PropertyTable &props = target.Props();
 
-    // need to convert from TRS order to SRT?
-    if (reverse_order) {
+    // collect unique times and keyframe lists
+    KeyFrameListList keyframeLists[TransformationComp_MAXIMUM];
+    KeyTimeList keytimes;
 
-        aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
-        aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
-        aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
+    for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
+        if (chain[i] == iterEnd)
+            continue;
 
-        KeyFrameListList scaling;
-        KeyFrameListList translation;
-        KeyFrameListList rotation;
+        keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop);
 
-        if (chain[TransformationComp_Scaling] != iter_end) {
-            scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
+        for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) {
+            const KeyTimeList& times = *std::get<0>(*it);
+            keytimes.insert(keytimes.end(), times.begin(), times.end());
         }
 
-        if (chain[TransformationComp_Translation] != iter_end) {
-            translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
-        }
+        // remove duplicates
+        std::sort(keytimes.begin(), keytimes.end());
 
-        if (chain[TransformationComp_Rotation] != iter_end) {
-            rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
-        }
+        auto last = std::unique(keytimes.begin(), keytimes.end());
+        keytimes.erase(last, keytimes.end());
+    }
 
-        KeyFrameListList joined;
-        joined.insert(joined.end(), scaling.begin(), scaling.end());
-        joined.insert(joined.end(), translation.begin(), translation.end());
-        joined.insert(joined.end(), rotation.begin(), rotation.end());
+    const Model::RotOrder rotOrder = target.RotationOrder();
+    const size_t keyCount = keytimes.size();
 
-        const KeyTimeList &times = GetKeyTimeList(joined);
+    aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
+    aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
+    aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
+    aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
 
-        aiQuatKey *out_quat = new aiQuatKey[times.size()];
-        aiVectorKey *out_scale = new aiVectorKey[times.size()];
-        aiVectorKey *out_translation = new aiVectorKey[times.size()];
+    aiVectorKey* outTranslations = new aiVectorKey[keyCount];
+    aiQuatKey* outRotations = new aiQuatKey[keyCount];
+    aiVectorKey* outScales = new aiVectorKey[keyCount];
 
-        if (times.size()) {
-            ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation,
-                    scaling,
-                    translation,
-                    rotation,
-                    times,
-                    max_time,
-                    min_time,
-                    target.RotationOrder(),
-                    def_scale,
-                    def_translate,
-                    def_rot);
+    if (keyframeLists[TransformationComp_Translation].size() > 0) {
+        InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime);
+    } else {
+        for (size_t i = 0; i < keyCount; ++i) {
+            outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
+            outTranslations[i].mValue = defTranslate;
         }
+    }
 
-        // XXX remove duplicates / redundant keys which this operation did
-        // likely produce if not all three channels were equally dense.
-
-        na->mNumScalingKeys = static_cast<unsigned int>(times.size());
-        na->mNumRotationKeys = na->mNumScalingKeys;
-        na->mNumPositionKeys = na->mNumScalingKeys;
+    if (keyframeLists[TransformationComp_Rotation].size() > 0) {
+        InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
+    } else {
+        for (size_t i = 0; i < keyCount; ++i) {
+            outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
+            outRotations[i].mValue = defQuat;
+        }
+    }
 
-        na->mScalingKeys = out_scale;
-        na->mRotationKeys = out_quat;
-        na->mPositionKeys = out_translation;
+    if (keyframeLists[TransformationComp_Scaling].size() > 0) {
+        InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime);
     } else {
+        for (size_t i = 0; i < keyCount; ++i) {
+            outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
+            outScales[i].mValue = defScale;
+        }
+    }
 
-        // if a particular transformation is not given, grab it from
-        // the corresponding node to meet the semantics of aiNodeAnim,
-        // which requires all of rotation, scaling and translation
-        // to be set.
-        if (chain[TransformationComp_Scaling] != iter_end) {
-            ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second,
-                    layer_map,
-                    start, stop,
-                    max_time,
-                    min_time);
-        } else {
-            na->mScalingKeys = new aiVectorKey[1];
-            na->mNumScalingKeys = 1;
+    bool ok = false;
+    const float zero_epsilon = 1e-6f;
 
-            na->mScalingKeys[0].mTime = 0.;
-            na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling",
-                    aiVector3D(1.f, 1.f, 1.f));
+    const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
+    if (ok && preRotation.SquareLength() > zero_epsilon) {
+        const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ);
+        for (size_t i = 0; i < keyCount; ++i) {
+            outRotations[i].mValue = preQuat * outRotations[i].mValue;
         }
+    }
 
-        if (chain[TransformationComp_Rotation] != iter_end) {
-            ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second,
-                    layer_map,
-                    start, stop,
-                    max_time,
-                    min_time,
-                    target.RotationOrder());
-        } else {
-            na->mRotationKeys = new aiQuatKey[1];
-            na->mNumRotationKeys = 1;
-
-            na->mRotationKeys[0].mTime = 0.;
-            na->mRotationKeys[0].mValue = EulerToQuaternion(
-                    PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)),
-                    target.RotationOrder());
+    const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
+    if (ok && postRotation.SquareLength() > zero_epsilon) {
+        const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ);
+        for (size_t i = 0; i < keyCount; ++i) {
+            outRotations[i].mValue = outRotations[i].mValue * postQuat;
         }
+    }
 
-        if (chain[TransformationComp_Translation] != iter_end) {
-            ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second,
-                    layer_map,
-                    start, stop,
-                    max_time,
-                    min_time);
-        } else {
-            na->mPositionKeys = new aiVectorKey[1];
-            na->mNumPositionKeys = 1;
+    // convert TRS to SRT
+    for (size_t i = 0; i < keyCount; ++i) {
+        aiQuaternion& r = outRotations[i].mValue;
+        aiVector3D& s = outScales[i].mValue;
+        aiVector3D& t = outTranslations[i].mValue;
 
-            na->mPositionKeys[0].mTime = 0.;
-            na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation",
-                    aiVector3D(0.f, 0.f, 0.f));
-        }
+        aiMatrix4x4 mat, temp;
+        aiMatrix4x4::Translation(t, mat);
+        mat *= aiMatrix4x4(r.GetMatrix());
+        mat *= aiMatrix4x4::Scaling(s, temp);
+
+        mat.Decompose(s, r, t);
     }
+
+    na->mNumScalingKeys = static_cast<unsigned int>(keyCount);
+    na->mNumRotationKeys = na->mNumScalingKeys;
+    na->mNumPositionKeys = na->mNumScalingKeys;
+
+    na->mScalingKeys = outScales;
+    na->mRotationKeys = outRotations;
+    na->mPositionKeys = outTranslations;
+
     return na.release();
 }
 
@@ -3328,10 +3314,7 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
         // take shortest path by checking the inner product
         // http://www.3dkingdoms.com/weekly/weekly.php?a=36
         if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) {
-            quat.x = -quat.x;
-            quat.y = -quat.y;
-            quat.z = -quat.z;
-            quat.w = -quat.w;
+            quat.Conjugate();
         }
         lastq = quat;
 
@@ -3339,60 +3322,6 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
     }
 }
 
-void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey *out_quat, aiVectorKey *out_scale,
-        aiVectorKey *out_translation,
-        const KeyFrameListList &scaling,
-        const KeyFrameListList &translation,
-        const KeyFrameListList &rotation,
-        const KeyTimeList &times,
-        double &maxTime,
-        double &minTime,
-        Model::RotOrder order,
-        const aiVector3D &def_scale,
-        const aiVector3D &def_translate,
-        const aiVector3D &def_rotation) {
-    if (rotation.size()) {
-        InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order);
-    } else {
-        for (size_t i = 0; i < times.size(); ++i) {
-            out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-            out_quat[i].mValue = EulerToQuaternion(def_rotation, order);
-        }
-    }
-
-    if (scaling.size()) {
-        InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime);
-    } else {
-        for (size_t i = 0; i < times.size(); ++i) {
-            out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-            out_scale[i].mValue = def_scale;
-        }
-    }
-
-    if (translation.size()) {
-        InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime);
-    } else {
-        for (size_t i = 0; i < times.size(); ++i) {
-            out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-            out_translation[i].mValue = def_translate;
-        }
-    }
-
-    const size_t count = times.size();
-    for (size_t i = 0; i < count; ++i) {
-        aiQuaternion &r = out_quat[i].mValue;
-        aiVector3D &s = out_scale[i].mValue;
-        aiVector3D &t = out_translation[i].mValue;
-
-        aiMatrix4x4 mat, temp;
-        aiMatrix4x4::Translation(t, mat);
-        mat *= aiMatrix4x4(r.GetMatrix());
-        mat *= aiMatrix4x4::Scaling(s, temp);
-
-        mat.Decompose(s, r, t);
-    }
-}
-
 aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D &rot, Model::RotOrder order) {
     aiMatrix4x4 m;
     GetRotationMatrix(order, rot, m);

+ 3 - 19
code/FBX/FBXConverter.h

@@ -349,12 +349,10 @@ private:
     aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
         const Model& target,
         NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
-        NodeMap::const_iterator iter_end,
-        const LayerMap& layer_map,
+        NodeMap::const_iterator iterEnd,
         int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time,
-        bool reverse_order = false);
+        double& maxTime,
+        double& minTime);
 
     // key (time), value, mapto (component index)
     typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
@@ -379,20 +377,6 @@ private:
         double& minTime,
         Model::RotOrder order);
 
-    // ------------------------------------------------------------------------------------------------
-    void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
-        aiVectorKey* out_translation,
-        const KeyFrameListList& scaling,
-        const KeyFrameListList& translation,
-        const KeyFrameListList& rotation,
-        const KeyTimeList& times,
-        double& maxTime,
-        double& minTime,
-        Model::RotOrder order,
-        const aiVector3D& def_scale,
-        const aiVector3D& def_translate,
-        const aiVector3D& def_rotation);
-
     // ------------------------------------------------------------------------------------------------
     // euler xyz -> quat
     aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);