/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <param name="flag"></param> /// <returns></returns> private static bool ChildHasFlag(HSD_JOBJ jobj, JOBJ_FLAG flag) { if (jobj == null) { return(false); } bool hasFlag = jobj.Flags.HasFlag(flag); foreach (var c in jobj.Children) { if (ChildHasFlag(c, flag)) { hasFlag = true; } } if (jobj.Next != null) { if (ChildHasFlag(jobj.Next, flag)) { hasFlag = true; } } return(hasFlag); }
/// <summary> /// /// </summary> public void SetJoint(HSD_JOBJ jobj, JointAnimManager animManager) { jointTree.BeginUpdate(); jointTree.Nodes.Clear(); var jobjs = jobj.BreathFirstList; Dictionary <HSD_JOBJ, JointNode> childToParent = new Dictionary <HSD_JOBJ, JointNode>(); for (int i = 0; i < Math.Min(animManager.NodeCount, jobjs.Count); i++) { var node = new JointNode() { JOBJ = jobjs[i], AnimNode = animManager.Nodes[i], Text = $"JOINT_{i}" }; foreach (var c in jobjs[i].Children) { childToParent.Add(c, node); } if (childToParent.ContainsKey(jobjs[i])) { childToParent[jobjs[i]].Nodes.Add(node); } else { jointTree.Nodes.Add(node); } } jointTree.ExpandAll(); jointTree.EndUpdate(); }
/// <summary> /// /// </summary> /// <param name="animJoint"></param> public static void OptimizeTracks(HSD_JOBJ model, HSD_AnimJoint animJoint, float epsilon = 0.001f) { var joints = model.BreathFirstList; var anim_joints = animJoint.BreathFirstList; if (joints.Count != anim_joints.Count) { return; } for (int i = 0; i < joints.Count; i++) { if (anim_joints[i].AOBJ != null) { Dictionary <JointTrackType, float> typeToDefaultValue = new Dictionary <JointTrackType, float>(); typeToDefaultValue.Add(JointTrackType.HSD_A_J_TRAX, joints[i].TX); typeToDefaultValue.Add(JointTrackType.HSD_A_J_TRAY, joints[i].TY); typeToDefaultValue.Add(JointTrackType.HSD_A_J_TRAZ, joints[i].TZ); typeToDefaultValue.Add(JointTrackType.HSD_A_J_ROTX, joints[i].RX); typeToDefaultValue.Add(JointTrackType.HSD_A_J_ROTY, joints[i].RY); typeToDefaultValue.Add(JointTrackType.HSD_A_J_ROTZ, joints[i].RZ); typeToDefaultValue.Add(JointTrackType.HSD_A_J_SCAX, joints[i].SX); typeToDefaultValue.Add(JointTrackType.HSD_A_J_SCAY, joints[i].SY); typeToDefaultValue.Add(JointTrackType.HSD_A_J_SCAZ, joints[i].SZ); var tracks = anim_joints[i].AOBJ.FObjDesc.List; HSD_FOBJDesc prev = null; foreach (var t in tracks) { var keys = t.GetDecodedKeys(); if (typeToDefaultValue.ContainsKey(t.JointTrackType) && ConstantTrack(keys, typeToDefaultValue[t.JointTrackType], epsilon)) { if (prev != null) { prev.Next = t; } else { anim_joints[i].AOBJ.FObjDesc = t; } } else { prev = t; } } if (anim_joints[i].AOBJ.FObjDesc != null) { System.Diagnostics.Debug.WriteLine($"{tracks.Count} -> {anim_joints[i].AOBJ.FObjDesc.List.Count}"); } else { anim_joints[i].AOBJ = null; } } } }
/// <summary> /// /// </summary> /// <param name="jobj"></param> public static void CleanRootNode(this HSD_JOBJ jobj) { var joints = jobj.BreathFirstList; Matrix4 rot = Matrix4.Identity;; for (int i = 0; i < joints.Count; i++) { var j = joints[i]; if (i == 0) { rot = Matrix4.CreateFromQuaternion(Math3D.FromEulerAngles(j.RZ, j.RY, j.RX)); j.RX = 0; j.RY = 0; j.RZ = 0; } else { // fix position var pos = Vector3.TransformNormal(new Vector3(j.TX, j.TY, j.TZ), rot); j.TX = pos.X; j.TY = pos.Y; j.TZ = pos.Z; } // clean scale j.SX = 1; j.SY = 1; j.SZ = 1; } }
/// <summary> /// Attaches SKELETON JOBJs to skeleton for rendering and editing /// </summary> /// <param name="jobj"></param> /// <param name="parent"></param> private void RecursivlyAddChildren(HSD_JOBJ jobj, SBHsdBone parent) { /*if (!(jobj.Flags.HasFlag(JOBJ_FLAG.SKELETON) || jobj.Flags.HasFlag(JOBJ_FLAG.SKELETON_ROOT))) * { * SBConsole.WriteLine(jobj.Flags.ToString()); * return; * }*/ SBHsdBone bone = new SBHsdBone(); bone.Name = "JOBJ_" + Skeleton.Bones.Length; bone.Transform = OpenTK.Matrix4.Identity; bone.Translation = new OpenTK.Vector3(jobj.TX, jobj.TY, jobj.TZ); bone.RotationEuler = new OpenTK.Vector3(jobj.RX, jobj.RY, jobj.RZ); bone.Scale = new OpenTK.Vector3(jobj.SX, jobj.SY, jobj.SZ); bone.SetJOBJ(jobj); if (parent == null) { ((SBSkeleton)Skeleton).AddRoot(bone); } else { bone.Parent = parent; } foreach (var child in jobj.Children) { RecursivlyAddChildren(child, bone); } }
/// <summary> /// /// </summary> private void RecursiveExport(HSD_JOBJ jobj, Node parent, Matrix4 parentTransform, Dictionary <int, string> indexToName) { Node root = new Node(); root.Name = "JOBJ_" + Jobjs.Count; if (indexToName.ContainsKey(Jobjs.Count)) { root.Name = indexToName[Jobjs.Count]; } else if (!string.IsNullOrEmpty(jobj.ClassName)) { root.Name = jobj.ClassName; } jobjToIndex.Add(jobj, Jobjs.Count); Matrix4 Transform = Matrix4.CreateScale(jobj.SX, jobj.SY, jobj.SZ) * Matrix4.CreateFromQuaternion(Math3D.FromEulerAngles(jobj.RZ, jobj.RY, jobj.RX)) * Matrix4.CreateTranslation(jobj.TX, jobj.TY, jobj.TZ); var worldTransform = Transform * parentTransform; JobjNodes.Add(root); Jobjs.Add(jobj); WorldTransforms.Add(worldTransform); root.Transform = Matrix4ToMatrix4x4(Transform); parent.Children.Add(root); foreach (var c in jobj.Children) { RecursiveExport(c, root, worldTransform, indexToName); } }
/// <summary> /// /// </summary> /// <param name="toReplace"></param> public static void ReplaceModelFromFile(HSD_JOBJ toReplace) { var f = Tools.FileIO.OpenFile(IOManager.GetModelImportFileFilter()); if (f != null) { var settings = new ModelImportSettings(); using (PropertyDialog d = new PropertyDialog("Model Import Options", settings)) { if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { ImportSettings ioSettings = new ImportSettings() { FlipUVs = settings.FlipUVs, FlipWindingOrder = !settings.FlipFaces, SmoothNormals = settings.SmoothNormals, Triangulate = true, //WeightLimit = true, }; ModelImporter imp = new ModelImporter(f, settings, ioSettings); using (ProgressBarDisplay pb = new ProgressBarDisplay(imp)) { pb.DoWork(); pb.ShowDialog(); } var newroot = imp.NewModel; toReplace._s.SetFromStruct(newroot._s); } } } }
/// <summary> /// /// </summary> /// <param name="rootjobj"></param> private static void ApplyNarutoMaterials(HSD_JOBJ rootjobj) { rootjobj.Flags = JOBJ_FLAG.SKELETON_ROOT | JOBJ_FLAG.ENVELOPE_MODEL | JOBJ_FLAG.LIGHTING | JOBJ_FLAG.OPA | JOBJ_FLAG.ROOT_OPA; foreach (var j in rootjobj.BreathFirstSearch) { if (j.Dobj != null) { foreach (var d in j.Dobj.List) { d.Mobj.RenderFlags = RENDER_MODE.ALPHA_COMPAT | RENDER_MODE.DIFFUSE; if (d.Mobj.Textures != null) { d.Mobj.RenderFlags |= RENDER_MODE.TEX0; } d.Mobj.Material.SPC_A = 255; d.Mobj.Material.SPC_B = 0; d.Mobj.Material.SPC_G = 0; d.Mobj.Material.SPC_R = 0; d.Mobj.Material.Shininess = 50; if (d.Mobj.Textures != null) { foreach (var t in d.Mobj.Textures.List) { t.Flags = TOBJ_FLAGS.COORD_UV | TOBJ_FLAGS.LIGHTMAP_DIFFUSE | TOBJ_FLAGS.COLORMAP_BLEND; } } } } } }
public static void ExportFile(HSD_JOBJ rootJOBJ, Dictionary <int, string> boneLabels = null) { StringBuilder sup = new StringBuilder(); AssimpContext importer = new AssimpContext(); var length = importer.GetSupportedExportFormats().Length; var index = 0; foreach (var v in importer.GetSupportedExportFormats()) { sup.Append($"{v.Description} (*.{v.FileExtension})|*.{v.FileExtension};"); index++; if (index != length) { sup.Append("|"); } } var f = Tools.FileIO.SaveFile(sup.ToString()); if (f != null) { var settings = new ModelExportSettings(); using (PropertyDialog d = new PropertyDialog("Model Import Options", settings)) { if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { ExportFile(f, rootJOBJ, settings, boneLabels); } } } }
/// <summary> /// /// </summary> /// <param name="bone"></param> /// <returns></returns> private HSD_JOBJ IOBoneToJOBJ(IOBone bone) { HSD_JOBJ jobj = new HSD_JOBJ() { TX = bone.TranslationX, TY = bone.TranslationY, TZ = bone.TranslationZ, RX = bone.RotationEuler.X, RY = bone.RotationEuler.Y, RZ = bone.RotationEuler.Z, SX = bone.ScaleX, SY = bone.ScaleY, SZ = bone.ScaleZ, }; if (Settings.ImportBoneNames) { jobj.ClassName = bone.Name; } _cache.NameToJOBJ.Add(bone.Name, jobj); _cache.jobjToWorldTransform.Add(jobj, MatrixNumericsToTKMatrix(bone.WorldTransform)); foreach (var child in bone.Children) { jobj.AddChild(IOBoneToJOBJ(child)); } return(jobj); }
/// <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="node"></param> /// <returns></returns> private static HSD_MatAnimJoint GenerateMatAnimJointFromJOBJ(HSD_JOBJ node) { HSD_MatAnimJoint joint = new HSD_MatAnimJoint(); if (node.Dobj != null) { foreach (var v in node.Dobj.List) { if (joint.MaterialAnimation == null) { joint.MaterialAnimation = new HSD_MatAnim(); } else { joint.MaterialAnimation.Add(new HSD_MatAnim() { }); } } } foreach (var v in node.Children) { joint.AddChild(GenerateMatAnimJointFromJOBJ(v)); } return(joint); }
/// <summary> /// /// </summary> /// <param name="frame"></param> /// <param name="boneIndex"></param> /// <param name="jobj"></param> /// <returns></returns> public virtual void GetAnimatedState(float frame, int boneIndex, HSD_JOBJ jobj, out float TX, out float TY, out float TZ, out float RX, out float RY, out float RZ, out float SX, out float SY, out float SZ) { TX = jobj.TX; TY = jobj.TY; TZ = jobj.TZ; RX = jobj.RX; RY = jobj.RY; RZ = jobj.RZ; SX = jobj.SX; SY = jobj.SY; SZ = jobj.SZ; // use bone lookup if enabled if (EnableBoneLookup) { if (BoneLookup.ContainsKey(boneIndex)) { boneIndex = BoneLookup[boneIndex]; } else { return; } } // set keys to animated values if (boneIndex < Nodes.Count) { AnimNode node = Nodes[boneIndex]; foreach (FOBJ_Player t in node.Tracks) { switch (t.JointTrackType) { case JointTrackType.HSD_A_J_ROTX: RX = t.GetValue(frame); break; case JointTrackType.HSD_A_J_ROTY: RY = t.GetValue(frame); break; case JointTrackType.HSD_A_J_ROTZ: RZ = t.GetValue(frame); break; case JointTrackType.HSD_A_J_TRAX: TX = t.GetValue(frame); break; case JointTrackType.HSD_A_J_TRAY: TY = t.GetValue(frame); break; case JointTrackType.HSD_A_J_TRAZ: TZ = t.GetValue(frame); break; case JointTrackType.HSD_A_J_SCAX: SX = t.GetValue(frame); break; case JointTrackType.HSD_A_J_SCAY: SY = t.GetValue(frame); break; case JointTrackType.HSD_A_J_SCAZ: SZ = t.GetValue(frame); break; } } } // apply frame modifiers foreach (var fm in FrameModifier) { fm.OverrideAnim(frame, boneIndex, jobj, ref TX, ref TY, ref TZ, ref RX, ref RY, ref RZ, ref SX, ref SY, ref SZ); } }
/// <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> /// Removes a JOBJ from the tree /// </summary> /// <param name="jobj"></param> public void RemoveJOBJ(HSD_JOBJ jobj) { // find parent or prev in list HSD_JOBJ next = null; HSD_JOBJ parent = null; foreach (var v in RootJOBJ.BreathFirstSearch) { if (v.Next == jobj) { next = v; } if (v.Child == jobj) { parent = v; } } if (next != null) { next.Next = jobj.Next; } if (parent != null) { parent.Child = jobj.Next; } ClearRenderingCache(); }
private void ParseJOBJs(HSD_JOBJ jobj, HSD_JOBJ parent) { //Debug.WriteLine(node.GetType()); { if (FirstJOBJ == null) { FirstJOBJ = jobj; } var bone = new GenericBone(); bone.Name = "JOBJ_" + skeleton.Bones.Count; jobjToIndex.Add(jobj, skeleton.Bones.Count); skeleton.Bones.Add(bone); bone.Position = new Vector3(jobj.Transforms.TX, jobj.Transforms.TY, jobj.Transforms.TZ); bone.Rotation = new Vector3(jobj.Transforms.RX, jobj.Transforms.RY, jobj.Transforms.RZ); bone.Scale = new Vector3(jobj.Transforms.SX, jobj.Transforms.SY, jobj.Transforms.SZ); if (parent != null && jobjToIndex.ContainsKey(parent)) { bone.ParentIndex = jobjToIndex[parent]; } } if (jobj != null) { foreach (var child in jobj.Children) { ParseJOBJs(child, jobj); } } }
/// <summary> /// /// </summary> /// <param name="bone"></param> /// <returns></returns> private HSD_JOBJ IOBoneToJOBJ(IOBone bone) { #if DEBUG // if (Settings.CleanRoot) { if (bone.Parent == null) { _cache.CleanRotMatrix = Matrix4.CreateFromQuaternion(new Quaternion(bone.Rotation.X, bone.Rotation.Y, bone.Rotation.Z, bone.Rotation.W)); bone.Rotation = System.Numerics.Quaternion.Identity; } else { // fix position var pos = Vector3.TransformNormal(new Vector3(bone.TranslationX, bone.TranslationY, bone.TranslationZ), _cache.CleanRotMatrix); bone.Translation = new System.Numerics.Vector3(pos.X, pos.Y, pos.Z); } // clean scale bone.Scale = new System.Numerics.Vector3(1, 1, 1); } // if (bone.Parent == null && Settings.Meleeify) { Meleeify(bone); } #endif HSD_JOBJ jobj = new HSD_JOBJ() { TX = bone.TranslationX, TY = bone.TranslationY, TZ = bone.TranslationZ, RX = bone.RotationEuler.X, RY = bone.RotationEuler.Y, RZ = bone.RotationEuler.Z, SX = bone.ScaleX, SY = bone.ScaleY, SZ = bone.ScaleZ, }; if (Settings.ImportBoneNames) { jobj.ClassName = bone.Name; } Console.WriteLine(bone.Name + " " + jobj.Children.Length); _cache.NameToJOBJ.Add(bone.Name, jobj); _cache.jobjToWorldTransform.Add(jobj, MatrixNumericsToTKMatrix(bone.WorldTransform)); foreach (var child in bone.Children) { jobj.AddChild(IOBoneToJOBJ(child)); } return(jobj); }
/// <summary> /// /// </summary> /// <param name="frame"></param> /// <param name="boneIndex"></param> /// <param name="jobj"></param> /// <returns></returns> public virtual Matrix4 GetAnimatedMatrix(float frame, int boneIndex, HSD_JOBJ jobj) { GetAnimatedState(frame, boneIndex, jobj, out float TX, out float TY, out float TZ, out float RX, out float RY, out float RZ, out float SX, out float SY, out float SZ); return(Matrix4.CreateScale(SX, SY, SZ) * Matrix4.CreateFromQuaternion(Math3D.FromEulerAngles(RZ, RY, RX)) * Matrix4.CreateTranslation(TX, TY, TZ)); }
/// <summary> /// /// </summary> /// <param name="frame"></param> /// <param name="boneIndex"></param> /// <param name="jobj"></param> /// <returns></returns> public virtual void GetAnimatedValues(float frame, int boneIndex, HSD_JOBJ jobj, out Vector3 trans, out Quaternion rot, out Vector3 scale) { GetAnimatedState(frame, boneIndex, jobj, out float TX, out float TY, out float TZ, out float RX, out float RY, out float RZ, out float SX, out float SY, out float SZ); trans = new Vector3(TX, TY, TZ); rot = Math3D.FromEulerAngles(RZ, RY, RX); scale = new Vector3(SX, SY, SZ); }
/// <summary> /// /// </summary> public static Dictionary <HSD_JOBJ, Matrix4> ApplyMeleeFighterTransforms(HSD_JOBJ root) { Dictionary <HSD_JOBJ, Matrix4> newTransforms = new Dictionary <HSD_JOBJ, Matrix4>(); ZeroOutRotations(newTransforms, root, Matrix4.Identity, Matrix4.Identity); return(newTransforms); }
public override Matrix4 GetAnimatedMatrix(float frame, int boneIndex, HSD_JOBJ jobj) { float TX = jobj.TX; float TY = jobj.TY; float TZ = jobj.TZ; float RX = jobj.RX; float RY = jobj.RY; float RZ = jobj.RZ; float SX = jobj.SX; float SY = jobj.SY; float SZ = jobj.SZ; Quaternion rotationOverride = Math3D.FromEulerAngles(RZ, RY, RX); var joints = _motFile.Joints.FindAll(e => e.BoneID >= 0 && e.BoneID < _motJointTable.Length && _motJointTable[e.BoneID] == boneIndex); foreach (var j in joints) { var key = j.GetKey(frame / 60f); if (key == null) { continue; } if (j.TrackFlag.HasFlag(MOT_FLAGS.TRANSLATE)) { TX += key.X; TY += key.Y; TZ += key.Z; } if (j.TrackFlag.HasFlag(MOT_FLAGS.SCALE)) { SX += key.X; SY += key.Y; SZ += key.Z; } if (j.TrackFlag.HasFlag(MOT_FLAGS.ROTATE)) { rotationOverride = Math3D.FromEulerAngles(RZ, RY, RX); var dir = new Vector3(key.X, key.Y, key.Z); var angle = key.W; float rot_angle = (float)Math.Acos(Vector3.Dot(Vector3.UnitX, dir)); if (Math.Abs(rot_angle) > 0.000001f) { Vector3 rot_axis = Vector3.Cross(Vector3.UnitX, dir).Normalized(); rotationOverride *= Quaternion.FromAxisAngle(rot_axis, rot_angle); } rotationOverride *= Quaternion.FromEulerAngles(angle * (float)Math.PI / 180, 0, 0); } } return(Matrix4.CreateScale(SX, SY, SZ) * Matrix4.CreateFromQuaternion(rotationOverride) * Matrix4.CreateTranslation(TX, TY, TZ)); }
/* * * def flip_euler(euler, rotation_mode): * ret = euler.copy() * inner_axis = rotation_mode[0] * outer_axis = rotation_mode[2] * middle_axis = rotation_mode[1] * * ret[euler_axis_index(z)] += pi * ret[euler_axis_index(x)] += pi * ret[euler_axis_index(y)] *= -1 * ret[euler_axis_index(y)] += pi * return ret * */ /// <summary> /// /// </summary> private static void RemoveUnusedTracks(HSD_JOBJ model, HSD_AnimJoint animJoint) { JointAnimManager manager = new JointAnimManager(); manager.FromAnimJoint(animJoint); var joints = model.BreathFirstList; if (joints.Count != manager.Nodes.Count) { return; } for (int i = 0; i < joints.Count; i++) { var fobjs = manager.Nodes[i].Tracks; var toRem = new List <FOBJ_Player>(); foreach (var f in fobjs) { bool remove = false; switch (f.JointTrackType) { case JointTrackType.HSD_A_J_TRAX: remove = RemoveTrack(f, joints[i].TX); break; case JointTrackType.HSD_A_J_TRAY: remove = RemoveTrack(f, joints[i].TY); break; case JointTrackType.HSD_A_J_TRAZ: remove = RemoveTrack(f, joints[i].TZ); break; case JointTrackType.HSD_A_J_ROTX: remove = RemoveTrack(f, joints[i].RX); break; case JointTrackType.HSD_A_J_ROTY: remove = RemoveTrack(f, joints[i].RY); break; case JointTrackType.HSD_A_J_ROTZ: remove = RemoveTrack(f, joints[i].RZ); break; case JointTrackType.HSD_A_J_SCAX: remove = RemoveTrack(f, joints[i].SX); break; case JointTrackType.HSD_A_J_SCAY: remove = RemoveTrack(f, joints[i].SY); break; case JointTrackType.HSD_A_J_SCAZ: remove = RemoveTrack(f, joints[i].SZ); break; } if (remove) { toRem.Add(f); } } foreach (var v in toRem) { fobjs.Remove(v); } } var newAnimJoint = manager.ToAnimJoint(model, AOBJ_Flags.ANIM_LOOP); animJoint._s = newAnimJoint._s; }
/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <param name="parent"></param> private void LoadParents(HSD_JOBJ jobj, HSD_JOBJ parent = null) { jobjToParent.Add(jobj, parent); foreach (var c in jobj.Children) { LoadParents(c, jobj); } }
/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <param name="figatree"></param> public AnimationPlayer(HSD_JOBJ jobj, float frameCount) { FrameCount = (int)frameCount; foreach (var j in jobj.BreathFirstList) { TrackNode t = new TrackNode(j); jobjToTrack.Add(j, t); } LoadParents(jobj); }
/// <summary> /// /// </summary> /// <param name="root"></param> /// <returns></returns> private Scene WriteRootNode(HSD_JOBJ root, ModelExportSettings settings, Dictionary <int, string> boneLabels) { Scene.RootNode = RootNode; RecursiveExport(root, RootNode, Matrix4.Identity, boneLabels); WriteDOBJNodes(settings); return(Scene); }
/// <summary> /// /// </summary> /// <param name="node"></param> /// <returns></returns> public static HSD_AnimJoint GenerateAnimJointFromJOBJ(HSD_JOBJ node) { HSD_AnimJoint joint = new HSD_AnimJoint(); foreach (var v in node.Children) { joint.AddChild(GenerateAnimJointFromJOBJ(v)); } return(joint); }
/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <returns></returns> public int IndexOf(HSD_JOBJ jobj) { if (jobjToCache.ContainsKey(jobj)) { return(jobjToCache[jobj].Index); } else { return(-1); } }
/// <summary> /// /// </summary> /// <param name="root"></param> /// <param name="nodes"></param> /// <param name="flags"></param> /// <returns></returns> private HSD_AnimJoint ToAnimJointRecursive(HSD_JOBJ root, AOBJ_Flags flags) { HSD_AnimJoint joint = new HSD_AnimJoint(); joint.Flags = 1; AnimNode n = null; if (index >= Nodes.Count) { n = new AnimNode(); } else { n = Nodes[index++]; } // set flags if (n.Tracks.Count > 0) { joint.AOBJ = new HSD_AOBJ(); joint.AOBJ.Flags = flags; } // add all tracks foreach (var t in n.Tracks) { joint.AOBJ.EndFrame = Math.Max(joint.AOBJ.EndFrame, t.FrameCount); HSD_FOBJDesc fobj = t.ToFobjDesc(); if (joint.AOBJ.FObjDesc == null) { joint.AOBJ.FObjDesc = fobj; } else { joint.AOBJ.FObjDesc.Add(fobj); } } // set particle flag if (n.Tracks.Any(e => e.JointTrackType == JointTrackType.HSD_A_J_PTCL)) { joint.AOBJ.EndFrame += 0.1f; } foreach (var c in root.Children) { joint.AddChild(ToAnimJointRecursive(c, flags)); } return(joint); }
/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <returns></returns> public Matrix4 GetBindTransform(HSD_JOBJ jobj) { if (jobjToCache.ContainsKey(jobj)) { return(jobjToCache[jobj].BindTransform); } else { return(Matrix4.Identity); } }
/// <summary> /// /// </summary> /// <param name="joint"></param> public TrackNode(HSD_JOBJ joint) { X.Keys = GenerateKEY(joint.TX); Y.Keys = GenerateKEY(joint.TY); Z.Keys = GenerateKEY(joint.TZ); RX.Keys = GenerateKEY(joint.RX); RY.Keys = GenerateKEY(joint.RY); RZ.Keys = GenerateKEY(joint.RZ); SX.Keys = GenerateKEY(joint.SX); SY.Keys = GenerateKEY(joint.SY); SZ.Keys = GenerateKEY(joint.SZ); }