private static void ExportSkeletonAnimationClips(Animator animator, bool autoPlay, BabylonSkeleton skeleton, Transform[] bones, BabylonMesh babylonMesh)
        {
            AnimationClip clip = null;
            AnimatorController ac = animator.runtimeAnimatorController as AnimatorController;
            if (ac == null)
            {
                return;
            }
            var layer = ac.layers[0];
            if (layer == null)
            {
                return;
            }
            AnimatorStateMachine sm = layer.stateMachine;
            if (sm.states.Length > 0)
            {
                // Only the first state is supported so far.
                var state = sm.states[0].state;
                clip = state.motion as AnimationClip;
            }

            if (clip == null)
            {
                return;
            }

            ExportSkeletonAnimationClipData(animator, autoPlay, skeleton, bones, babylonMesh, clip);
        }
        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var skinIndex = skins.IndexOf(skin);

            var bones = new List<BabylonBone>();
            var gameBones = new List<IIGameNode>();
            var boneIds = new List<int>();
            var bindPoseInfos = new List<BonePoseInfo>();
            for(int i = 0; i < skin.TotalSkinBoneCount; ++i)
            {
                bones.Add(null);
                gameBones.Add(null);
                boneIds.Add(-1);
                bindPoseInfos.Add(null);
            }
            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = skin.GetIGameBone(index, false);

                var sortedIndex = skinSortedBones[skin].IndexOf(gameBone.NodeID);

                gameBones[sortedIndex] = (gameBone);
                boneIds[sortedIndex] =(gameBone.NodeID);
                bones[sortedIndex]=(new BabylonBone { index = sortedIndex, name = gameBone.Name });

                var boneInitMatrix = gameBone.GetObjectTM(0);
                bindPoseInfos[sortedIndex] = (new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
            }

            // fix hierarchy an generate animation keys
            var exportNonOptimizedAnimations = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportnonoptimizedanimations");

            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = gameBones[index];
                var parent = gameBone.NodeParent;
                var babBone = bones[index];
                if (parent != null)
                {
                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
                }

                if (babBone.parentBoneIndex == -1)
                {
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform;
                }
                else
                {
                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                }

                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();

                var babylonAnimation = new BabylonAnimation
                {
                    name = gameBone.Name + "Animation",
                    property = "_matrix",
                    dataType = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.Global.FrameRate
                };

                var start = Loader.Core.AnimRange.Start;
                var end = Loader.Core.AnimRange.End;

                float[] previous = null;
                var keys = new List<BabylonAnimationKey>();
                for (var key = start; key <= end; key += Ticks)
                {
                    var objectTM = gameBone.GetObjectTM(key);
                    var parentNode = gameBone.NodeParent;
                    IGMatrix mat;
                    if (parentNode == null || babBone.parentBoneIndex == -1)
                    {
                        mat = objectTM;
                    }
                    else
                    {
                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
                    }

                    var current = mat.ToArray();
                    if (key == start || key == end || exportNonOptimizedAnimations || !(previous.IsEqualTo(current)))
                    {
                        keys.Add(new BabylonAnimationKey
                        {
                            frame = key / Ticks,
                            values = current
                        });
                    }

                    previous = current;
                }

                babylonAnimation.keys = keys.ToArray();
                babBone.animation = babylonAnimation;
            }

            babylonSkeleton.needInitialSkinMatrix = true;
            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }
        private BabylonSkeleton ConvertUnitySkeletonToBabylon(Transform[] bones, Matrix4x4[] bindPoses, Transform transform, GameObject gameObject, float progress)
        {
            ExporterWindow.ReportProgress(progress, "Exporting skeleton: " + gameObject.name);
            BabylonSkeleton babylonSkeleton = new BabylonSkeleton();
            babylonSkeleton.name = gameObject.name;
            babylonSkeleton.id = Math.Abs(GetID(transform.gameObject).GetHashCode());
            babylonSkeleton.needInitialSkinMatrix = false;

            // Prefilled to keep order and track parents.
            int index = 0;
            var transformToBoneMap = new Dictionary<Transform, BabylonBone>();
            foreach (Transform unityBone in bones)
            {
                var babylonBone = new BabylonBone();
                babylonBone.name = unityBone.name;
                babylonBone.index = index;

                transformToBoneMap.Add(unityBone, babylonBone);
                index++;
            }

            // Attaches Matrix and parent.
            index = 0;
            foreach (Transform unityBone in bones)
            {
                var babylonBone = transformToBoneMap[unityBone];
                Matrix4x4 localTransform;

                // Unity BindPose is already inverse so take the inverse again :-)
                if (transformToBoneMap.ContainsKey(unityBone.parent))
                {
                    var babylonParentBone = transformToBoneMap[unityBone.parent];
                    babylonBone.parentBoneIndex = babylonParentBone.index;
                    localTransform = bindPoses[babylonBone.parentBoneIndex] * bindPoses[index].inverse;
                }
                else
                {
                    babylonBone.parentBoneIndex = -1;
                    localTransform = bindPoses[index].inverse;
                }

                transformToBoneMap[unityBone].matrix = new[] {
                    localTransform[0, 0], localTransform[1, 0], localTransform[2, 0], localTransform[3, 0],
                    localTransform[0, 1], localTransform[1, 1], localTransform[2, 1], localTransform[3, 1],
                    localTransform[0, 2], localTransform[1, 2], localTransform[2, 2], localTransform[3, 2],
                    localTransform[0, 3], localTransform[1, 3], localTransform[2, 3], localTransform[3, 3]
                };
                index++;
            }

            // Reorder and attach the skeleton.
            babylonSkeleton.bones = transformToBoneMap.Values.OrderBy(b => b.index).ToArray();
            babylonScene.SkeletonsList.Add(babylonSkeleton);
            return babylonSkeleton;
        }
Example #4
0
        private static void ExportSkeletonAnimation(SkinnedMeshRenderer skinnedMesh, BabylonMesh babylonMesh, BabylonSkeleton skeleton)
        {
            var animator = skinnedMesh.rootBone.gameObject.GetComponent<Animator>();
            if (animator != null)
            {
                ExportSkeletonAnimationClips(animator, true, skeleton, skinnedMesh.bones, babylonMesh);
            }
            else
            {
                var parent = skinnedMesh.rootBone.parent;
                while (parent != null)
                {
                    animator = parent.gameObject.GetComponent<Animator>();
                    if (animator != null)
                    {
                        ExportSkeletonAnimationClips(animator, true, skeleton, skinnedMesh.bones, babylonMesh);
                        break;
                    }

                    parent = parent.parent;
                }
            }
        }
        private static void ExportSkeletonAnimationClipData(Animator animator, bool autoPlay, BabylonSkeleton skeleton, Transform[] bones, BabylonMesh babylonMesh, AnimationClip clip)
        {
            var frameTime = 1.0f / clip.frameRate;
            int animationFrameCount = (int)(clip.length * clip.frameRate);

            if (autoPlay)
            {
                babylonMesh.autoAnimate = true;
                babylonMesh.autoAnimateFrom = 0;
                babylonMesh.autoAnimateTo = animationFrameCount;
                babylonMesh.autoAnimateLoop = true;
            }

            foreach (var bone in skeleton.bones)
            {
                var keys = new List<BabylonAnimationKey>();
                var transform = bones.Single(b => b.name == bone.name);

                AnimationMode.BeginSampling();
                for (var i = 0; i < animationFrameCount; i++)
                {
                    clip.SampleAnimation(animator.gameObject, i * frameTime);

                    var local = (transform.parent.localToWorldMatrix.inverse * transform.localToWorldMatrix);
                    float[] matrix = new[] {
                        local[0, 0], local[1, 0], local[2, 0], local[3, 0],
                        local[0, 1], local[1, 1], local[2, 1], local[3, 1],
                        local[0, 2], local[1, 2], local[2, 2], local[3, 2],
                        local[0, 3], local[1, 3], local[2, 3], local[3, 3]
                    };

                    var key = new BabylonAnimationKey
                    {
                        frame = i,
                        values = matrix,
                    };
                    keys.Add(key);
                }
                AnimationMode.EndSampling();

                var babylonAnimation = new BabylonAnimation
                {
                    name = bone.name + "Animation",
                    property = "_matrix",
                    dataType = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = (int)clip.frameRate,
                    keys = keys.ToArray()
                };

                bone.animation = babylonAnimation;
            }
        }
        private void ExportSkin(IISkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton {id = skins.IndexOf(skin)};
            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var bones = new List<BabylonBone>();

            for (var index = 0; index < skin.NumBones; index++)
            {
                var bone = new BabylonBone {name = skin.GetBoneName(index), index = index};

                var maxBone = skin.GetBone(index);
                var parentNode = maxBone.ParentNode;

                if (parentNode != null)
                {
                    for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
                    {
                        if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
                        {
                            bone.parentBoneIndex = recurseIndex;
                            break;
                        }
                    }
                }
                var hasParent = bone.parentBoneIndex != -1;
                bone.matrix = GetBoneMatrix(skin, maxBone, 0, hasParent);

                // Animation
                var babylonAnimation = new BabylonAnimation
                {
                    name = bone.name + "Animation", 
                    property = "_matrix", 
                    dataType = BabylonAnimation.DataType.Matrix, 
                    loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.Global.FrameRate
                };

                var start = Loader.Core.AnimRange.Start;
                var end = Loader.Core.AnimRange.End;

                float[] previous = null;
                var keys = new List<BabylonAnimationKey>();
                for (var key = start; key <= end; key += Ticks)
                {
                    var current = GetBoneMatrix(skin, maxBone, key, hasParent);

                    if (key == start || key == end || !(previous.IsEqualTo(current)))
                    {
                        keys.Add(new BabylonAnimationKey
                        {
                            frame = key / Ticks,
                            values = current
                        });
                    }

                    previous = current;
                }

                babylonAnimation.keys = keys.ToArray();
                bone.animation = babylonAnimation;

                bones.Add(bone);
            }

            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }