Exemplo n.º 1
0
            /// <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);
                }
            }
        public void TestSetCurrentAnimStack()
        {
            using (FbxScene newScene = FbxScene.Create(Manager, "")) {
                FbxAnimStack animStack = FbxAnimStack.Create(Manager, "");
                newScene.SetCurrentAnimationStack(animStack);
                Assert.AreEqual(animStack, newScene.GetCurrentAnimationStack());

                // test null
                Assert.That(() => { newScene.SetCurrentAnimationStack(null); }, Throws.Exception.TypeOf <System.ArgumentNullException>());

                // test invalid
                animStack.Destroy();
                Assert.That(() => { newScene.SetCurrentAnimationStack(animStack); }, Throws.Exception.TypeOf <System.ArgumentNullException>());
            }
        }
        protected FbxAnimStack CreateAnimStack(FbxScene scene)
        {
            FbxAnimStack fbxAnimStack = FbxAnimStack.Create(scene, "animClip");

            fbxAnimStack.Description.Set("Animation Take");

            FbxTime.EMode timeMode = FbxTime.EMode.eFrames30;
            scene.GetGlobalSettings().SetTimeMode(timeMode);

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

            fbxAnimStack.SetLocalTimeSpan(new FbxTimeSpan(fbxStartTime, fbxStopTime));
            return(fbxAnimStack);
        }
Exemplo n.º 4
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();
        }
Exemplo n.º 6
0
            /// <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);
                }
            }