protected override FbxScene CreateScene(FbxManager manager)
        {
            // Create a scene with a single node that has an animation clip
            // attached to it
            FbxScene scene = FbxScene.Create(manager, "myScene");

            FbxNode animNode = FbxNode.Create(scene, "animNode");

            // setup anim stack
            FbxAnimStack fbxAnimStack = CreateAnimStack(scene);

            // add an animation layer
            FbxAnimLayer fbxAnimLayer = FbxAnimLayer.Create(scene, "animBaseLayer");

            fbxAnimStack.AddMember(fbxAnimLayer);

            // set up the translation
            CreateAnimCurves(
                animNode, fbxAnimLayer, PropertyComponentList, (index) => { return(index * 2.0); }, (index) => { return(index * 3.0f - 1); }
                );

            // TODO: avoid needing to this by creating typemaps for
            //       FbxObject::GetSrcObjectCount and FbxCast.
            //       Not trivial to do as both fbxobject.i and fbxemitter.i
            //       have to be moved up before the ignore all statement
            //       to allow use of templates.
            scene.SetCurrentAnimationStack(fbxAnimStack);
            scene.GetRootNode().AddChild(animNode);
            return(scene);
        }
Exemple #2
0
        protected override FbxAnimStack GenerateFbx()
        {
            HavokAnimationData anim = Souls.dsAnimation;

            IDictionary <int, FrameData> frameDatas = ExtractAnimationData(anim);

            var animStack = FbxAnimStack.Create(Scene, anim.Name + "_AnimStack");

            animStack.SetLocalTimeSpan(new FbxTimeSpan(FbxTime.FromFrame(0), FbxTime.FromFrame(anim.FrameCount)));

            FbxAnimLayer animLayer = FbxAnimLayer.Create(animStack, "Layer0");

            animStack.AddMember(animLayer);

            IDictionary <int, AnimExportHelper> boneHelpers = new Dictionary <int, AnimExportHelper>();

            foreach (DsBoneData boneData in Souls.skeleton.boneDatas)
            {
                boneData.exportData.FbxNode.LclTranslation.GetCurveNode(animLayer, true);
                boneData.exportData.FbxNode.LclRotation.GetCurveNode(animLayer, true);
                boneData.exportData.FbxNode.LclScaling.GetCurveNode(animLayer, true);

                boneHelpers.Add(boneData.exportData.SoulsData.HkxBoneIndex, new AnimExportHelper(
                                    animLayer,
                                    boneData.exportData.FbxNode.LclTranslation,
                                    boneData.exportData.FbxNode.LclRotation,
                                    boneData.exportData.FbxNode.LclScaling
                                    )
                                );
            }

            foreach (var frameData in frameDatas)
            {
                FbxTime time = FbxTime.FromFrame(frameData.Key);

                foreach (var boneData in frameData.Value.boneDatas)
                {
                    int hkxBoneIndex = boneData.hkxBoneIndex;

                    var newBlendableTransform = boneData.transform;

                    AnimExportHelper animExportHelper = boneHelpers[hkxBoneIndex];

                    var euler = new Quaternion(newBlendableTransform.Rotation.X, newBlendableTransform.Rotation.Y, newBlendableTransform.Rotation.Z, newBlendableTransform.Rotation.W).QuaternionToEuler();

                    animExportHelper.translation.AddPoint(time, newBlendableTransform.Translation);
                    animExportHelper.rotation.AddPoint(time, euler);
                    animExportHelper.scale.AddPoint(time, newBlendableTransform.Scale);
                }
            }

            foreach (AnimExportHelper helper in boneHelpers.Values)
            {
                helper.translation.Finish();
                helper.rotation.Finish();
                helper.scale.Finish();
            }

            return(null);
        }
        public static void GenericTests<T>(T fbxCollection, FbxManager manager) where T : FbxCollection
        {
            // TODO: FbxScene has a member count of 3 instead of one (even after clearing), is this normal?
            int initialMemberCount = fbxCollection.GetMemberCount ();

            // test AddMember
            FbxObject obj = FbxObject.Create (manager, "");
            bool result = fbxCollection.AddMember (obj);
            Assert.IsTrue (result);
            Assert.AreEqual(initialMemberCount+1, fbxCollection.GetMemberCount());

            // test Clear
            fbxCollection.Clear ();
            Assert.AreEqual (initialMemberCount, fbxCollection.GetMemberCount());

            // test GetAnimLayerMember()
            fbxCollection.AddMember(FbxAnimLayer.Create(manager, "animLayer"));
            var animLayer = fbxCollection.GetAnimLayerMember ();
            Assert.IsInstanceOf<FbxAnimLayer> (animLayer);

            var animLayer2 = fbxCollection.GetAnimLayerMember (0);

            Assert.AreEqual (animLayer, animLayer2);

            // check invalid
            Assert.IsNull(fbxCollection.GetAnimLayerMember (1));
            Assert.IsNull(fbxCollection.GetAnimLayerMember (-1));
        }
            /// <summary>
            /// Exports all animation
            /// </summary>
            private void ExportAnimationClip(AnimationClip unityAnimClip, GameObject unityRoot, FbxScene fbxScene)
            {
                if (unityAnimClip == null)
                {
                    return;
                }

                // setup anim stack
                FbxAnimStack fbxAnimStack = FbxAnimStack.Create(fbxScene, unityAnimClip.name);

                fbxAnimStack.Description.Set("Animation Take: " + unityAnimClip.name);

                // add one mandatory animation layer
                FbxAnimLayer fbxAnimLayer = FbxAnimLayer.Create(fbxScene, "Animation Base Layer");

                fbxAnimStack.AddMember(fbxAnimLayer);

                // Set up the FPS so our frame-relative math later works out
                // Custom frame rate isn't really supported in FBX SDK (there's
                // a bug), so try hard to find the nearest time mode.
                FbxTime.EMode timeMode  = FbxTime.EMode.eCustom;
                double        precision = 1e-6;

                while (timeMode == FbxTime.EMode.eCustom && precision < 1000)
                {
                    timeMode   = FbxTime.ConvertFrameRateToTimeMode(unityAnimClip.frameRate, precision);
                    precision *= 10;
                }
                if (timeMode == FbxTime.EMode.eCustom)
                {
                    timeMode = FbxTime.EMode.eFrames30;
                }
                FbxTime.SetGlobalTimeMode(timeMode);

                // set time correctly
                var fbxStartTime = FbxTime.FromSecondDouble(0);
                var fbxStopTime  = FbxTime.FromSecondDouble(unityAnimClip.length);

                fbxAnimStack.SetLocalTimeSpan(new FbxTimeSpan(fbxStartTime, fbxStopTime));

                foreach (EditorCurveBinding unityCurveBinding in AnimationUtility.GetCurveBindings(unityAnimClip))
                {
                    Object unityObj = AnimationUtility.GetAnimatedObject(unityRoot, unityCurveBinding);
                    if (!unityObj)
                    {
                        continue;
                    }

                    AnimationCurve unityAnimCurve = AnimationUtility.GetEditorCurve(unityAnimClip, unityCurveBinding);
                    if (unityAnimCurve == null)
                    {
                        continue;
                    }

                    ExportAnimCurve(unityObj, unityAnimCurve, unityCurveBinding.propertyName, fbxAnimLayer);
                }
            }
Exemple #5
0
        protected override FbxScene CreateScene(FbxManager manager)
        {
            // Create a scene with a single node that has an animation clip
            // attached to it
            FbxScene scene = FbxScene.Create(manager, "myScene");

            FbxNode sourceNode      = FbxNode.Create(scene, "source");
            FbxNode constrainedNode = FbxNode.Create(scene, "constrained");

            scene.GetRootNode().AddChild(sourceNode);
            scene.GetRootNode().AddChild(constrainedNode);

            FbxConstraint posConstraint = CreatePositionConstraint(scene, sourceNode, constrainedNode);

            Assert.That(posConstraint, Is.Not.Null);

            bool result = posConstraint.ConnectDstObject(scene);

            Assert.That(result, Is.True);

            // animate weight + active
            // setup anim stack
            FbxAnimStack fbxAnimStack = CreateAnimStack(scene);

            // add an animation layer
            FbxAnimLayer fbxAnimLayer = FbxAnimLayer.Create(scene, "animBaseLayer");

            fbxAnimStack.AddMember(fbxAnimLayer);

            // set up the translation
            CreateAnimCurves(
                posConstraint, fbxAnimLayer, PropertyComponentList, (index) => { return(index * 2.0); }, (index) => { return(index * 3 - 2); }
                );

            // TODO: avoid needing to do this by creating typemaps for
            //       FbxObject::GetSrcObjectCount and FbxCast.
            //       Not trivial to do as both fbxobject.i and fbxemitter.i
            //       have to be moved up before the ignore all statement
            //       to allow use of templates.
            scene.SetCurrentAnimationStack(fbxAnimStack);
            return(scene);
        }
Exemple #6
0
    public void CreateDocument()
    {
        Scene = FbxScene.Create(SdkManager, "");

        FbxDocumentInfo SceneInfo = FbxDocumentInfo.Create(SdkManager, "SceneInfo");

        SceneInfo.mTitle   = new FbxString("Unreal FBX Exporter");
        SceneInfo.mSubject = new FbxString("Export FBX meshes from Unreal");
        SceneInfo.Original_ApplicationVendor.Set(new FbxString("Epic Games"));
        SceneInfo.Original_ApplicationName.Set(new FbxString("Unreal Engine"));
        SceneInfo.Original_ApplicationVersion.Set(new FbxString("4.18"));
        SceneInfo.LastSaved_ApplicationVendor.Set(new FbxString("Epic Games"));
        SceneInfo.LastSaved_ApplicationName.Set(new FbxString("Unreal Engine"));
        SceneInfo.LastSaved_ApplicationVersion.Set(new FbxString("4.18"));

        FbxAxisSystem.EFrontVector FrontVector = (FbxAxisSystem.EFrontVector)(0 - FbxAxisSystem.EFrontVector.eParityOdd);
        if (bForceFrontXAxis)
        {
            FrontVector = FbxAxisSystem.EFrontVector.eParityEven;
        }

        FbxAxisSystem UnrealZUp = new FbxAxisSystem(FbxAxisSystem.EUpVector.eZAxis, FrontVector, FbxAxisSystem.ECoordSystem.eRightHanded);

        //const FbxAxisSystem UnrealZUp(FbxAxisSystem.EUpVector, FrontVector, FbxAxisSystem::eRightHanded);
        Scene.GetGlobalSettings().SetAxisSystem(FbxAxisSystem.Max);
        Scene.GetGlobalSettings().SetOriginalUpAxis(FbxAxisSystem.Max);
        Scene.GetGlobalSettings().SetSystemUnit(FbxSystemUnit.cm);

        Scene.SetSceneInfo(SceneInfo);

        // setup anim stack
        AnimStack = FbxAnimStack.Create(Scene, "Unreal Take");
        //KFbxSet<KTime>(AnimStack.LocalStart, KTIME_ONE_SECOND);
        AnimStack.Description.Set((new FbxString("Animation Take for Unreal.")));

        // this take contains one base layer. In fact having at least one layer is mandatory.
        AnimLayer = FbxAnimLayer.Create(Scene, "Base Layer");
        AnimStack.AddMember(AnimLayer);
        //if(Mathf)
    }
        // tests that should work for any subclass of FbxProperty
        public static void GenericPropertyTests <T>(T property, FbxObject parent, string propertyName, FbxDataType dataType) where T : FbxProperty
        {
            Assert.IsTrue(property.IsValid());
            Assert.AreEqual(dataType, property.GetPropertyDataType());
            Assert.AreEqual(propertyName, property.GetName());
            Assert.AreEqual(propertyName, property.ToString());
            Assert.AreEqual(propertyName, property.GetHierarchicalName());
            Assert.AreEqual(propertyName, property.GetLabel(true));
            property.SetLabel("label");
            Assert.AreEqual("label", property.GetLabel());
            Assert.AreEqual(parent, property.GetFbxObject());
            Assert.AreEqual(property.GetFbxObject(), parent); // test it both ways just in case equals is busted

            // test the flags using the animatable flag
            property.ModifyFlag(FbxPropertyFlags.EFlags.eAnimatable, true);
            Assert.IsTrue(property.GetFlag(FbxPropertyFlags.EFlags.eAnimatable));
            Assert.AreNotEqual(0, property.GetFlags() | FbxPropertyFlags.EFlags.eAnimatable);
            property.SetFlagInheritType(FbxPropertyFlags.EFlags.eAnimatable, FbxPropertyFlags.EInheritType.eInherit);
            Assert.AreEqual(FbxPropertyFlags.EInheritType.eInherit, property.GetFlagInheritType(FbxPropertyFlags.EFlags.eAnimatable));

            // not clear when this ever returns true: whether we set animatable
            // to true or false it says it has the default value.
            Assert.IsFalse(property.ModifiedFlag(FbxPropertyFlags.EFlags.eAnimatable));

            // Test setting the value with the generic float accessor.
            // The value may not round-trip: a bool property will go to 1.0
            property.Set(5.0f);
            TestGetter(property.GetFloat());
            TestGetter(property.GetBool());
            TestGetter(property.GetDouble());
            TestGetter(property.GetFbxColor());
            TestGetter(property.GetFbxDouble3());
            TestGetter(property.GetString());
            TestGetter(property.GetInt());

            // Test setting the value with color accessor
            property.Set(new FbxColor());

            // test GetCurve(). Just make sure it doesn't crash. We can't
            // generically test actually getting curves, because the details
            // (channel names etc) depend on the type of property and its
            // flags.
            FbxAnimLayer layer = FbxAnimLayer.Create(parent, "layer");

            property.GetCurve(layer);
            property.GetCurve(layer, true);
            property.GetCurve(layer, "asdf");
            property.GetCurve(layer, "asdf", true);
            property.GetCurve(layer, "asdf", "hjkl", true);
            Assert.That(() => { property.GetCurve(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

            // test GetCurveNode() (make sure it doesn't crash)
            FbxAnimCurveNode curveNode = property.GetCurveNode();

            Assert.IsNull(curveNode);  // didn't create one so should be null

            curveNode = property.GetCurveNode(true);
            // TODO: figure out why the curve node doesn't get created
            //Assert.IsNotNull (curveNode);

            property.GetCurveNode(FbxAnimStack.Create(parent, "anim stack"));
            property.GetCurveNode(FbxAnimStack.Create(parent, "anim stack"), true);
            property.GetCurveNode(FbxAnimLayer.Create(parent, "anim layer"));
            property.GetCurveNode(FbxAnimLayer.Create(parent, "anim layer"), true);

            Assert.That(() => { property.GetCurveNode((FbxAnimStack)null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());
            Assert.That(() => { property.GetCurveNode((FbxAnimLayer)null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

            using (FbxManager manager = FbxManager.Create()) {
                // Test ConnectSrcObject functions
                FbxObject obj    = FbxObject.Create(manager, "obj");
                bool      result = property.ConnectSrcObject(obj);
                Assert.IsTrue(result);
                Assert.IsTrue(property.IsConnectedSrcObject(obj));
                Assert.AreEqual(1, property.GetSrcObjectCount());
                Assert.AreEqual(obj, property.GetSrcObject());
                Assert.AreEqual(obj, property.GetSrcObject(0));
                Assert.AreEqual(obj, property.FindSrcObject("obj"));
                Assert.IsNull(property.FindSrcObject("obj", 1));
                Assert.That(() => { property.FindSrcObject(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

                Assert.IsTrue(property.DisconnectSrcObject(obj));
                Assert.IsFalse(property.IsConnectedSrcObject(obj));

                Assert.That(() => { property.ConnectSrcObject(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

                Assert.IsTrue(property.ConnectSrcObject(obj, FbxConnection.EType.eData));

                Assert.IsTrue(property.DisconnectAllSrcObject());

                // Test ConnectDstObject functions
                result = property.ConnectDstObject(obj);
                Assert.IsTrue(result);
                Assert.IsTrue(property.IsConnectedDstObject(obj));
                Assert.AreEqual(1, property.GetDstObjectCount());
                Assert.AreEqual(obj, property.GetDstObject());
                Assert.AreEqual(obj, property.GetDstObject(0));
                Assert.AreEqual(obj, property.FindDstObject("obj"));
                Assert.IsNull(property.FindDstObject("obj", 1));
                Assert.That(() => { property.FindDstObject(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

                Assert.IsTrue(property.DisconnectDstObject(obj));
                Assert.IsFalse(property.IsConnectedDstObject(obj));

                Assert.That(() => { property.ConnectDstObject(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

                Assert.IsTrue(property.ConnectDstObject(obj, FbxConnection.EType.eData));

                Assert.IsTrue(property.DisconnectAllDstObject());
            }

            // verify this in the future: will dispose destroy?
            property.Dispose();
        }
            /// <summary>
            /// Export an AnimationClip as a single take
            /// </summary>
            protected void ExportAnimationClip(AnimationClip unityAnimClip, GameObject unityRoot, FbxScene fbxScene)
            {
                if (Verbose)
                {
                    Debug.Log(string.Format("exporting clip {1} for {0}", unityRoot.name, unityAnimClip.name));
                }

                // setup anim stack
                FbxAnimStack fbxAnimStack = FbxAnimStack.Create(fbxScene, unityAnimClip.name);

                fbxAnimStack.Description.Set("Animation Take: " + unityAnimClip.name);

                // add one mandatory animation layer
                FbxAnimLayer fbxAnimLayer = FbxAnimLayer.Create(fbxScene, "Animation Base Layer");

                fbxAnimStack.AddMember(fbxAnimLayer);

                // Set up the FPS so our frame-relative math later works out
                // Custom frame rate isn't really supported in FBX SDK (there's
                // a bug), so try hard to find the nearest time mode.
                FbxTime.EMode timeMode  = FbxTime.EMode.eCustom;
                double        precision = 1e-6;

                while (timeMode == FbxTime.EMode.eCustom && precision < 1000)
                {
                    timeMode   = FbxTime.ConvertFrameRateToTimeMode(unityAnimClip.frameRate, precision);
                    precision *= 10;
                }
                if (timeMode == FbxTime.EMode.eCustom)
                {
                    timeMode = FbxTime.EMode.eFrames30;
                }
                FbxTime.SetGlobalTimeMode(timeMode);

                // set time correctly
                var fbxStartTime = FbxTime.FromSecondDouble(0);
                var fbxStopTime  = FbxTime.FromSecondDouble(unityAnimClip.length);

                fbxAnimStack.SetLocalTimeSpan(new FbxTimeSpan(fbxStartTime, fbxStopTime));

                /* The major difficulty: Unity uses quaternions for rotation
                 * (which is how it should be) but FBX uses euler angles. So we
                 * need to gather up the list of transform curves per object. */
                var quaternions = new Dictionary <UnityEngine.GameObject, QuaternionCurve> ();

                foreach (EditorCurveBinding unityCurveBinding in AnimationUtility.GetCurveBindings(unityAnimClip))
                {
                    Object unityObj = AnimationUtility.GetAnimatedObject(unityRoot, unityCurveBinding);
                    if (!unityObj)
                    {
                        continue;
                    }

                    AnimationCurve unityAnimCurve = AnimationUtility.GetEditorCurve(unityAnimClip, unityCurveBinding);
                    if (unityAnimCurve == null)
                    {
                        continue;
                    }

                    int index = QuaternionCurve.GetQuaternionIndex(unityCurveBinding.propertyName);
                    if (index == -1)
                    {
                        if (Verbose)
                        {
                            Debug.Log(string.Format("export binding {1} for {0}", unityCurveBinding.propertyName, unityObj.ToString()));
                        }

                        /* Some normal property (e.g. translation), export right away */
                        ExportAnimCurve(unityObj, unityAnimCurve, unityCurveBinding.propertyName,
                                        fbxScene, fbxAnimLayer);
                    }
                    else
                    {
                        /* Rotation property; save it to convert quaternion -> euler later. */

                        var unityGo = GetGameObject(unityObj);
                        if (!unityGo)
                        {
                            continue;
                        }

                        QuaternionCurve quat;
                        if (!quaternions.TryGetValue(unityGo, out quat))
                        {
                            quat = new QuaternionCurve();
                            quaternions.Add(unityGo, quat);
                        }
                        quat.SetCurve(index, unityAnimCurve);
                    }
                }

                /* now export all the quaternion curves */
                foreach (var kvp in quaternions)
                {
                    var unityGo = kvp.Key;
                    var quat    = kvp.Value;

                    FbxNode fbxNode;
                    if (!MapUnityObjectToFbxNode.TryGetValue(unityGo, out fbxNode))
                    {
                        Debug.LogError(string.Format("no fbxnode found for '0'", unityGo.name));
                        continue;
                    }
                    quat.Animate(unityGo.transform, fbxNode, fbxAnimLayer, Verbose);
                }
            }