/// <summary> /// /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="boneMapFrom"></param> /// <param name="boneMapTo"></param> public SkeletonPorter(HSD_JOBJ from, HSD_JOBJ to, BoneMap boneMapFrom, BoneMap boneMapTo) { var bonesFrom = from.BreathFirstList; var bonesTo = to.BreathFirstList; var fromDict = GetWorldTransforms(from, Matrix4x4.Identity); var toDict = GetWorldTransforms(to, Matrix4x4.Identity); foreach (var t in boneMapTo.GetNames()) { var toIndex = boneMapTo.GetIndex(t); var fromIndex = boneMapFrom.GetIndex(t); if (toIndex != -1 && fromIndex != -1) { var jobjFrom = bonesFrom[fromIndex]; var jobjTo = bonesTo[toIndex]; var transformFrom = fromDict[jobjFrom]; var transformTo = toDict[jobjTo]; System.Diagnostics.Debug.WriteLine(t + " " + transformFrom + " " + transformTo); Matrix4x4.Invert(transformFrom.Item1, out Matrix4x4 invFrom1); Matrix4x4.Invert(transformFrom.Item2, out Matrix4x4 invFrom2); boneToReorient.Add(t, invFrom1 * transformTo.Item1); boneToReorientParent.Add(t, invFrom2 * transformTo.Item2); } } }
/// <summary> /// /// </summary> /// <param name="figatree"></param> /// <param name="jobjFrom"></param> /// <param name="jobjTo"></param> /// <param name="bmFrom"></param> /// <param name="bmTo"></param> /// <returns></returns> public static HSD_FigaTree Port(HSD_FigaTree figatree, HSD_JOBJ jobjFrom, HSD_JOBJ jobjTo, BoneMap bmFrom, BoneMap bmTo) { AnimationPlayer sourceAnim = new AnimationPlayer(jobjFrom, figatree); AnimationPlayer targetAnim = new AnimationPlayer(jobjTo, figatree.FrameCount); int jobjIndex = 0; foreach (var to in jobjTo.BreathFirstList) { var name = bmTo.GetName(jobjIndex); var index = bmFrom.GetIndex(name); FigaTreeNode node = new FigaTreeNode(); if (index != -1) { var jfrom = jobjFrom.BreathFirstList[index]; if (targetAnim.PortBoneTo(to, sourceAnim, jfrom)) { Debug.WriteLine($"Retargeting {name}"); } } jobjIndex++; } return(targetAnim.ToFigaTree());; }
/// <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); }