예제 #1
0
        public static List <AnimationKey> GetBoneKeyFrames(Bone bone, FBXFile file)
        {
            var result = new List <AnimationKey>();

            var curveNodes = FBX.FBXHelper.GetAnimationCurveNodes(file, bone);

            // get curves for the curve nodes of the bone
            foreach (var curveNode in curveNodes)
            {
                var curves = file.GetAnimationCurves(curveNode);

                foreach (var curve in curves)
                {
                    // the connection defines the axis being affected
                    var axis = file.GetConnectionType(curve.Id, curveNode.Id);

                    if (axis.Contains("X"))
                    {
                        axis = "x";
                    }
                    if (axis.Contains("Y"))
                    {
                        axis = "y";
                    }
                    if (axis.Contains("Z"))
                    {
                        axis = "z";
                    }

                    curveNode.Curves.Add(axis, curve);
                }
            }

            // convert curves to animation keys
            var keys   = curveNodes.SelectMany(c => c.Curves.SelectMany(b => b.Value.KeyTime)).Distinct().OrderBy(a => a).ToArray();
            int frames = keys.Length;

            for (int i = 0; i < keys.Length; i++)
            {
                var animKey = new AnimationKey()
                {
                    Frame     = i,
                    Transform = bone.JointMatrix
                };

                // Translation
                var curveNode = curveNodes.Where(a => a.Name.Contains("T")).FirstOrDefault();

                if (curveNode != null)
                {
                    // check if the curve has a value for that frame first
                    var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : animKey.Translation[0];

                    framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : animKey.Translation[1];

                    framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : animKey.Translation[2];

                    animKey.Translation = new float[] { x, y, z };
                }

                // Rotation
                curveNode = curveNodes.Where(a => a.Name.Contains("R")).FirstOrDefault();

                if (curveNode != null)
                {
                    // check if the curve has a value for that frame first
                    var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : 0F;

                    framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : 0f;

                    framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : 0f;

                    animKey.Rotation = new float[] { x.ToRadians(), y.ToRadians(), z.ToRadians() }.QuaternionFromEuler(EulerOrder.XYZ);
                }

                // Scale
                curveNode = curveNodes.Where(a => a.Name.Contains("S")).FirstOrDefault();

                if (curveNode != null)
                {
                    // check if the curve has a value for that frame first
                    var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : 0f;

                    framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : 0f;

                    framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                    var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : 0f;

                    animKey.Scale = new float[] { x, y, z };
                }

                // add the animation key to the list
                result.Add(animKey);
            }

            return(result);
        }
예제 #2
0
        public Animation(FBXFile file, List <string> bones)
        {
            var rawNodes  = file.GetAnimationCurveNodes();
            var rawCurves = file.GetAnimationCurves();

            // first: expand AnimationCurveNode into curve nodes
            var curveNodes = new List <FBXAnimCurveNode>();

            foreach (var tempNode in rawNodes)
            {
                var fileNode = file.FindChild(tempNode.Id);

                curveNodes.Add(new FBXAnimCurveNode(fileNode, file, bones));
            }

            // second: gen dict, mapped by internalId
            var tmp = new Dictionary <long, FBXAnimCurveNode>();

            for (var i = 0; i < curveNodes.Count; ++i)
            {
                tmp.Add(curveNodes[i].Id, curveNodes[i]);
            }

            // third: insert curves into the dict
            var ac  = new List <FBXAnimCurve>();
            var max = 0f;

            foreach (var curve in rawCurves)
            {
                ac.Add(curve);

                max = curve.Length > max ? curve.Length : max;

                var parentId = file.Connections.Where(a => a.Src == curve.Id).FirstOrDefault().Dst;
                var axis     = file.GetConnectionType(curve.Id, parentId);

                if (axis.Contains("X"))
                {
                    axis = "x";
                }
                if (axis.Contains("Y"))
                {
                    axis = "y";
                }
                if (axis.Contains("Z"))
                {
                    axis = "z";
                }

                tmp[parentId].Curves.Add(axis, curve);
            }

            // forth:
            foreach (var t in tmp)
            {
                var id = t.Value.ContainerBoneId;

                if (!Curves.ContainsKey(id))
                {
                    Curves.Add(id, new Dictionary <string, FBXAnimCurveNode>());
                }

                if (Curves[id].ContainsKey(t.Value.Attr))
                {
                    Curves[id][t.Value.Attr] = t.Value;
                }
                else
                {
                    Curves[id].Add(t.Value.Attr, t.Value);
                }
            }

            Length = max;
            Frames = Length * FPS;
        }
예제 #3
0
        public Animator(FBXFile file)
        {
            var bones = Bone.GetBoneHierarchy(file);

            var boneCurveNodes = new SortedList <string, List <CoreFBX.FBX.Animation.FBXAnimCurveNode> >();

            AnimationKeys = new Dictionary <string, List <AnimationKey> >();
            PoseKeys      = new Dictionary <string, AnimationKey>();

            foreach (var bone in bones)
            {
                AnimationKeys.Add(bone.Id, new List <AnimationKey>());
                var curveNodes = FBX.FBXHelper.GetAnimationCurveNodes(file, bone);

                // get curves for the curve nodes of the bone
                foreach (var curveNode in curveNodes)
                {
                    var curves = file.GetAnimationCurves(curveNode);

                    foreach (var curve in curves)
                    {
                        // the connection defines the axis being affected
                        var axis = file.GetConnectionType(curve.Id, curveNode.Id);

                        if (axis.Contains("X"))
                        {
                            axis = "x";
                        }
                        if (axis.Contains("Y"))
                        {
                            axis = "y";
                        }
                        if (axis.Contains("Z"))
                        {
                            axis = "z";
                        }

                        curveNode.Curves.Add(axis, curve);
                    }
                }

                boneCurveNodes.Add(bone.Id, curveNodes);
            }

            // convert curves to animation keys
            var keys = boneCurveNodes.SelectMany(a => a.Value.SelectMany(c => c.Curves.SelectMany(b => b.Value.KeyTime))).Distinct().OrderBy(a => a).ToArray();

            Frames = keys.Length;

            for (int i = 0; i < keys.Length; i++)
            {
                foreach (var bone in bones)
                {
                    var animKey = new AnimationKey()
                    {
                        Frame     = i,
                        Transform = bone.JointMatrix
                    };

                    // Translation
                    var curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("T")).FirstOrDefault();

                    if (curveNode != null)
                    {
                        // check if the curve has a value for that frame first
                        var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : animKey.Translation[0];

                        framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : animKey.Translation[1];

                        framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : animKey.Translation[2];

                        animKey.Translation = new float[] { x, y, z };
                    }

                    // Rotation
                    curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("R")).FirstOrDefault();

                    if (curveNode != null)
                    {
                        // check if the curve has a value for that frame first
                        var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : 0F;

                        framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : 0f;

                        framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : 0f;

                        animKey.Rotation = new float[] { x.ToRadians(), y.ToRadians(), z.ToRadians() }.QuaternionFromEuler(EulerOrder.XYZ);
                    }

                    // Scale
                    curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("S")).FirstOrDefault();

                    if (curveNode != null)
                    {
                        // check if the curve has a value for that frame first
                        var framePos = curveNode.Curves["x"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var x        = (framePos > -1) ? curveNode.Curves["x"].KeyValueFloat[framePos] : 0f;

                        framePos = curveNode.Curves["y"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var y = (framePos > -1) ? curveNode.Curves["y"].KeyValueFloat[framePos] : 0f;

                        framePos = curveNode.Curves["z"].KeyTime.TakeWhile(a => a < keys[i]).Count() - 1;
                        var z = (framePos > -1) ? curveNode.Curves["z"].KeyValueFloat[framePos] : 0f;

                        animKey.Scale = new float[] { x, y, z };
                    }

                    // add the animation key to the list
                    bone.Keyframes.Add(animKey);
                    //AnimationKeys[bone.Id].Add(animKey);
                }
            }

            //restore bind pose
            foreach (var bone in bones)
            {
                var animKey = new AnimationKey()
                {
                    Frame     = 0,
                    Transform = bone.JointMatrix
                };

                // Translation
                var curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("T")).FirstOrDefault();

                if (curveNode != null)
                {
                    animKey.Translation = curveNode.Value;
                }

                // Rotation
                curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("R")).FirstOrDefault();

                if (curveNode != null)
                {
                    animKey.Rotation = curveNode.Value.ToRadians().QuaternionFromEuler(EulerOrder.XYZ);
                }

                // Scale
                curveNode = boneCurveNodes[bone.Id].Where(a => a.Name.Contains("S")).FirstOrDefault();

                if (curveNode != null)
                {
                    animKey.Scale = curveNode.Value;
                }

                // add the animation key to the list
                PoseKeys.Add(bone.Name, animKey);
            }
        }// Constructor()