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; * }*/ } }
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); }
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); }
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); }
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; }
public AnimationData GetAnimationData(FBXFile file) { return(new AnimationData(Bone.GetBoneHierarchy(file), GetAnimations(file))); }
public Animation GetAnimations(FBXFile file) { return(new Animation(file, Bone.GetBoneHierarchy(file).Select(a => a.Id).ToList())); }
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); }
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()