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 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 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()