Example #1
0
        public FBXAnimCurveNode(FBXFileNode node, FBXFile file, List <string> bones)
        {
            Id   = node.Id;
            Name = node.NodeName;
            Attr = Name;

            var propsNode = node.Nodes.Where(a => a.Name == "Properties70").FirstOrDefault();

            if (Name.Contains("T") || Name.Contains("R") || Name.Contains("S"))
            {
                foreach (var propNode in propsNode.Nodes)
                {
                    foreach (var prop in propNode.Properties)
                    {
                        if (prop.Data is string && (prop.Data as string).Contains("X"))
                        {
                            AttrX  = true;
                            ValueX = (float)(double)propNode.Properties[4].Data;
                        }
                        else if (prop.Data is string && (prop.Data as string).Contains("Y"))
                        {
                            AttrY  = true;
                            ValueY = (float)(double)propNode.Properties[4].Data;
                        }
                        else if (prop.Data is string && (prop.Data as string).Contains("Z"))
                        {
                            AttrZ  = true;
                            ValueZ = (float)(double)propNode.Properties[4].Data;
                        }
                    }
                }
            }

            ContainerIndices = file.Connections.Where(a => a.Src == node.Id).Select(a => a.Dst).ToArray();
            CurveIdx         = file.Connections.Where(a => a.Dst == node.Id).Select(a => a.Src).ToArray();

            for (int i = ContainerIndices.Length - 1; i >= 0; i--)
            {
                // gets the real id of the bone

                /*var boneId = bones.TakeWhile(a => a.Id != ContainerIndices[i]).Count();
                 *
                 * if(boneId >= 0)
                 * {
                 *  ContainerBoneId = boneId;
                 *  ContainerId = ContainerIndices[i];
                 *
                 *  break;
                 * }*/
            }
        }
Example #2
0
        public static List <Bone> GetBoneHierarchy(FBXTreeNode node, FBXFile fbx)
        {
            var bones      = new List <Bone>();
            var modelNodes = node.Children.Where(a => a.Node.Name == "Model");

            foreach (var child in modelNodes)
            {
                var model = new Model(child.Node, fbx);

                if (model.ModelType == Model.FBXModelType.LimbNode || (model.ModelType == Model.FBXModelType.None && !model.HasGeometry))
                {
                    var children = GetBoneHierarchy(child, fbx);

                    var t = model.LclTranslation;
                    var r = model.LclRotation.ToRadians().QuaternionFromEuler(EulerOrder.XYZ);
                    var s = model.LclScaling;

                    var deformerId = fbx.Connections.Where(a => a.Src == model.Id && fbx.FindChild(a.Dst).Name == "Deformer").FirstOrDefault();
                    var globalInverseMatrix = new float[] { }.IdentityMatrix();

                    if (deformerId != null)
                    {
                        var deformer = new Deformer(fbx.FindChild(deformerId.Dst));
                    }

                    var bone = new Bone()
                    {
                        Id          = model.Id.ToString(),
                        Parent      = (node.Node != null) ? node.Node.Id.ToString() : "",
                        Children    = children.Select(a => a.Id).ToList(),
                        JointMatrix = new float[] { }.MatrixCompose(t, r, s),
                        Name        = model.Name
                    };

                    bone.Keyframes = GetBoneKeyFrames(bone, fbx);

                    bones.Add(bone);

                    bones.AddRange(children);
                }
            }

            return(bones);
        }
Example #3
0
        public static List <FBXAnimCurveNode> GetAnimationCurveNodes(FBXFile file, Bone bone)
        {
            var result = new List <FBXAnimCurveNode>();

            var root = file.RootNode.FindChild(long.Parse(bone.Id));

            var nodes = root.Children;

            foreach (var node in nodes)
            {
                if (node.Node.Name == "AnimationCurveNode")
                {
                    result.Add(new FBXAnimCurveNode(node.Node));
                }

                result.AddRange(file.GetAnimationCurveNodes(node.Node));
            }

            return(result);
        }
Example #4
0
        public static List <Bone> GetBoneHierarchy(FBXFile file, FBXTreeNode current = null)
        {
            var bones = new List <Bone>();

            if (current == null)
            {
                current = file.RootNode;
            }

            var children = current.Children
                           .Where(a => a.Node.Name == "Model")
                           .Select(a => new Model(a.Node, file))
                           .Where(a => a.ModelType == Model.FBXModelType.LimbNode || (a.ModelType == Model.FBXModelType.None && !a.HasGeometry));

            foreach (var node in children)
            {
                var t = node.LclTranslation;
                var r = node.LclRotation.ToRadians().QuaternionFromEuler(EulerOrder.XYZ);
                var s = node.LclScaling;

                var bone = new Bone()
                {
                    Parent      = current.Node == null ? "" : current.Node.Id.ToString(),
                    JointMatrix = new float[] { }.MatrixCompose(t, r, s),
                    Id          = node.Id.ToString(),
                    Name        = node.Name
                };

                bone.Keyframes = GetBoneKeyFrames(bone, file);

                var childrenHier = GetBoneHierarchy(file, current.Children.Where(a => a.Node.Id == node.Id).FirstOrDefault());

                bone.Children = childrenHier.Where(a => a.Parent == bone.Id).Select(a => a.Id).ToList();

                bones.Add(bone);

                bones.AddRange(childrenHier);
            }

            return(bones);
        }
Example #5
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;
        }
Example #6
0
 public AnimationData GetAnimationData(FBXFile file)
 {
     return(new AnimationData(Bone.GetBoneHierarchy(file), GetAnimations(file)));
 }
Example #7
0
 public Animation GetAnimations(FBXFile file)
 {
     return(new Animation(file, Bone.GetBoneHierarchy(file).Select(a => a.Id).ToList()));
 }
Example #8
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);
        }
Example #9
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()