/// <summary> /// /// </summary> /// <param name="key"></param> /// <returns></returns> private static FOBJKey CloneKey(FOBJKey key) { return(new FOBJKey() { Frame = key.Frame, Value = key.Value, Tan = key.Tan, InterpolationType = key.InterpolationType }); }
/// <summary> /// Trims frames to given region /// </summary> /// <param name="startFrame"></param> /// <param name="endFrame"></param> public virtual void Trim(int startFrame, int endFrame) { if (startFrame == 0 && endFrame == FrameCount) { return; } FrameCount = endFrame - startFrame; foreach (var n in Nodes) { foreach (var t in n.Tracks) { // the new set of keys after trimming List <FOBJKey> newKeys = t.Keys.Where(e => e.Frame >= startFrame && e.Frame <= endFrame).ToList(); // if there's not a key on the startframe, it'll create a new one if (!t.Keys.Any(k => k.Frame == startFrame)) { FOBJKey start = new FOBJKey() { Frame = startFrame, Tan = 0, Value = t.GetValue(startFrame), InterpolationType = GXInterpolationType.HSD_A_OP_LIN }; newKeys.Insert(0, start); } // same but for the last frame if (!t.Keys.Any(k => k.Frame == endFrame)) { FOBJKey end = new FOBJKey() { Frame = endFrame, Tan = 0, Value = t.GetValue(endFrame), InterpolationType = GXInterpolationType.HSD_A_OP_LIN }; newKeys.Add(end); } // finally shifts all the keys foreach (var k in newKeys) { k.Frame -= startFrame; } // assigns the new keys t.Keys = newKeys; } } }
/// <summary> /// /// </summary> /// <returns></returns> public static List <FOBJKey> LoadKeys(string filePath) { List <FOBJKey> keys = new List <FOBJKey>(); var lines = File.ReadAllLines(filePath); foreach (var v in lines) { var a = v.Split(' '); if (a.Length >= 3) { if (int.TryParse(a[0], out int frame) && float.TryParse(a[1], out float value) && Enum.TryParse("HSD_A_OP_" + a[2], out GXInterpolationType interpolation)) { var key = new FOBJKey() { Frame = frame, Value = value, InterpolationType = interpolation }; if (HasSlope(interpolation)) { if (a.Length >= 4 && float.TryParse(a[3], out float slope)) { key.Tan = slope; } } keys.Add(key); } } } return(keys); }
/// <summary> /// /// </summary> /// <param name="filePath"></param> public static JointAnimManager ImportFromMayaAnim(string filePath) { var mayaFile = new MayaAnim(); mayaFile.Open(filePath); JointAnimManager animation = new JointAnimManager(); animation.FrameCount = mayaFile.header.endTime - mayaFile.header.startTime; // process and encode FOBJ keys foreach (var mNode in mayaFile.Nodes) { AnimNode node = new AnimNode(); //Debug.WriteLine(mNode.name); foreach (var mTrack in mNode.atts) { FOBJ_Player t = new FOBJ_Player(); t.Keys = new List <FOBJKey>(); t.JointTrackType = jointTrackToMayaTrack.FirstOrDefault(e => e.Value == mTrack.type).Key; //Debug.WriteLine("\t" + mTrack.type); var degrees = mayaFile.header.angularUnit == "deg"; var trackUnit = (mTrack.IsAngular() && degrees); for (int i = 0; i < mTrack.keys.Count; i++) { var mKey = mTrack.keys[i]; var mKeyNext = i + 1 < mTrack.keys.Count ? mTrack.keys[i + 1] : mTrack.keys[i]; var k = new FOBJKey(); k.Frame = mKey.input - mayaFile.header.startTime; k.Value = trackUnit ? MathHelper.DegreesToRadians(mKey.output) : mKey.output; switch (mKey.outtan) { case "auto": case "linear": k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); break; case "step": if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } else { k.InterpolationType = GXInterpolationType.HSD_A_OP_CON; } t.Keys.Add(k); break; case "fixed": case "spline": k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL; k.Tan = AngleToTan(mKey.t1, degrees); if ((mKeyNext.input - mKey.input) <= 1) // optimization { //k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); } else if (mKey.t2 == 0) { k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL0; t.Keys.Add(k); } else if (mKey.t1 != mKey.t2) { t.Keys.Add(k); var slp = new FOBJKey(); slp.Frame = mKeyNext.input - 1; slp.InterpolationType = GXInterpolationType.HSD_A_OP_SLP; slp.Tan = AngleToTan(mKey.t2, degrees); t.Keys.Add(slp); } else { t.Keys.Add(k); } break; default: Console.WriteLine(mKey.outtan + " not supported!"); break; } if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } //foreach (var key in t.Keys) // Debug.WriteLine($"\t\t{key.Frame} {key.Value}"); } node.Tracks.Add(t); } animation.Nodes.Add(node); } return(animation); }
/// <summary> /// /// </summary> /// <param name="filePath"></param> public static HSD_FigaTree ImportFromMayaAnim(string filePath, BoneMap jointMap) { var mayaFile = new MayaAnim(); mayaFile.Open(filePath); HSD_FigaTree animation = new HSD_FigaTree(); animation.FrameCount = mayaFile.header.endTime - mayaFile.header.startTime; List <FigaTreeNode> nodes = new List <FigaTreeNode>(); var nodeCount = jointMap == null || jointMap.Count == 0 ? mayaFile.Nodes.Count : Math.Max(mayaFile.Nodes.Count, jointMap.Count); for (int i = 0; i < nodeCount; i++) { nodes.Add(new FigaTreeNode()); } // process and encode FOBJ keys int index = 0; foreach (var mNode in mayaFile.Nodes) { var node = animation.Nodes[index++]; //Debug.WriteLine(mNode.name); if (jointMap != null) { var nodeIndex = jointMap.GetIndex(mNode.name); if (nodeIndex != -1) { node = animation.Nodes[nodeIndex]; } } foreach (var mTrack in mNode.atts) { FOBJ_Player t = new FOBJ_Player(); t.Keys = new List <FOBJKey>(); t.JointTrackType = jointTrackToMayaTrack.FirstOrDefault(e => e.Value == mTrack.type).Key; //Debug.WriteLine("\t" + mTrack.type); var degrees = mayaFile.header.angularUnit == "deg"; var trackUnit = (mTrack.IsAngular() && degrees); for (int i = 0; i < mTrack.keys.Count; i++) { var mKey = mTrack.keys[i]; var mKeyNext = i + 1 < mTrack.keys.Count ? mTrack.keys[i + 1] : mTrack.keys[i]; var k = new FOBJKey(); k.Frame = mKey.input - mayaFile.header.startTime; k.Value = trackUnit ? (float)(mKey.output * Math.PI / 180) : mKey.output; switch (mKey.outtan) { case "auto": case "linear": k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); break; case "step": if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } else { k.InterpolationType = GXInterpolationType.HSD_A_OP_CON; } t.Keys.Add(k); break; case "fixed": case "spline": k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL; k.Tan = AngleToTan(mKey.t1, degrees); if ((mKeyNext.input - mKey.input) <= 1) // optimization { //k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); } else if (mKey.t2 == 0) { k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL0; t.Keys.Add(k); } else if (mKey.t1 != mKey.t2) { t.Keys.Add(k); var slp = new FOBJKey(); slp.Frame = mKeyNext.input - 1; slp.InterpolationType = GXInterpolationType.HSD_A_OP_SLP; slp.Tan = AngleToTan(mKey.t2, degrees); t.Keys.Add(slp); } else { t.Keys.Add(k); } break; default: Console.WriteLine(mKey.outtan + " not supported!"); break; } if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } //foreach (var key in t.Keys) // Debug.WriteLine($"\t\t{key.Frame} {key.Value}"); } var track = new HSD_Track(); track.FromFOBJ(t.ToFobj()); node.Tracks.Add(track); } } animation.Nodes = nodes; animation.Type = 1; return(animation); }