/// <summary> /// モーフライブラリを読み込みます。 /// </summary> /// <param name="source_path">フォルダ名</param> public void Load(string source_path) { foreach (string group_path in Directory.GetDirectories(source_path)) { //Debug.WriteLine("group_path: " + group_path); string group_name = Path.GetFileName(group_path); Debug.WriteLine("group_name: " + group_name); NodesRange nodes_range = NodesRange.Load(Path.Combine(group_path, @"NodesRange.xml")); MorphGroup group = new MorphGroup(group_name, nodes_range); groups.Add(group); foreach (string tmo_file in Directory.GetFiles(Path.Combine(source_path, group_path), @"*.tmo")) { //Debug.WriteLine("tmo_file: " + tmo_file); string morph_name = Path.GetFileNameWithoutExtension(tmo_file); Debug.WriteLine("morph_name: " + morph_name); TMOFile tmo = new TMOFile(); tmo.Load(tmo_file); tmo.LoadTransformationMatrixFromFrame(0); Morph morph = new Morph(morph_name, tmo); group.Items.Add(morph); } } }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMOFile tmo, TMOFrame tmo_frame) { if (tmo.nodes == null) { return; } if (tmo.w_hips_node != null) { //姉妹スライダによる変形 Matrix local = Matrix.Scaling(slide_matrices.Local); //移動変位を設定 local.M41 = translation.X; local.M42 = translation.Y; local.M43 = translation.Z; matrixStack.LoadMatrix(local); UpdateBoneMatrices(tmo.w_hips_node, tmo_frame); } foreach (TMONode tmo_node in tmo.root_nodes_except_w_hips) { //移動変位を設定 Matrix local = Matrix.Translation(translation); matrixStack.LoadMatrix(local); UpdateBoneMatricesWithoutSlideMatrices(tmo_node, tmo_frame); } }
static void Main(string[] args) { if (args.Length != 1) { System.Console.WriteLine("Usage: TMONodeDump <tmo file>"); return; } string tmo_file = args[0]; Console.WriteLine("Load File: " + tmo_file); TMOFile tmo = new TMOFile(); try { tmo.Load(tmo_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } foreach (TMONode node in tmo.nodes) { Console.WriteLine(node.Name); } }
/// <summary> /// 先頭のtsoからtmoを生成します。 /// </summary> public void RegenerateTmo() { if (TsoList.Count != 0) { Tmo = TsoList[0].GenerateTmo(); } }
/// <summary> /// フィギュアアクションを追加します。 /// </summary> /// <param name="frame_index">フレーム番号</param> /// <param name="tmo">tmo</param> public void Add(int frame_index, TMOFile tmo) { LinkedListNode <FigureAction> act = action_list.First; LinkedListNode <FigureAction> new_act = new LinkedListNode <FigureAction>(new FigureAction(frame_index, tmo)); LinkedListNode <FigureAction> found = null; while (act != null) { if (act.Value.frame_index <= frame_index) { found = act; } else { break; } act = act.Next; } if (found != null) { action_list.AddAfter(found, new_act); } else { action_list.AddFirst(new_act); current_action = new_act; } }
/// FTMOチャンクを書き込みます。 public void WriteFTMO(TMOFile tmo) { MemoryStream ms = new MemoryStream(); tmo.Save(ms); ms.Seek(0, SeekOrigin.Begin); WriteFTMO(ms); }
/// <summary> /// フィギュアに含まれるnode treeを描画する。 /// </summary> /// <param name="fig"></param> void DrawNodeTree(Figure fig) { TMOFile tmo = fig.Tmo; Line line = new Line(device); foreach (TMONode node in tmo.nodes) { if (HiddenNode(node)) { continue; } Vector3 p0 = GetNodePositionOnScreen(node); p0.Z = 0.0f; TMONode parent_node = node.parent; if (parent_node != null) { if (HiddenNode(parent_node)) { continue; } Vector3 p1 = GetNodePositionOnScreen(parent_node); p1.Z = 0.0f; Vector3 pd = p0 - p1; float len = Vector3.Length(pd); float scale = 4.0f / len; Vector2 p3 = new Vector2(p1.X + pd.Y * scale, p1.Y - pd.X * scale); Vector2 p4 = new Vector2(p1.X - pd.Y * scale, p1.Y + pd.X * scale); Vector2[] vertices = new Vector2[3]; vertices[0] = new Vector2(p3.X, p3.Y); vertices[1] = new Vector2(p0.X, p0.Y); vertices[2] = new Vector2(p4.X, p4.Y); line.Draw(vertices, LineColor); } } line.Dispose(); line = null; Rectangle rect = new Rectangle(0, 16, 15, 15); //node circle Vector3 rect_center = new Vector3(7, 7, 0); sprite.Begin(SpriteFlags.None); foreach (TMONode node in tmo.nodes) { if (HiddenNode(node)) { continue; } Vector3 p0 = GetNodePositionOnScreen(node); p0.Z = 0.0f; sprite.Draw(dot_texture, rect, rect_center, p0, Color.White); } sprite.End(); }
/// <summary> /// 現在の行列を新規フレームに保存します。 /// (実際に新規に増やしているのは、nodeのmatrixで、frameは増えてない) /// </summary> public static void SaveTransformationMatrixToFrameAdd(this TDCG.TMOFile tmo) { foreach (TMONode node in tmo.nodes) { TMOMat tm = new TMOMat(); tm.m = node.TransformationMatrix; node.matrices.Add(tm); } }
/// <summary> /// root nodeに対する解を得ます。 /// </summary> /// <param name="tmo">tmo</param> /// <param name="effector_name">エフェクタnode名称</param> public void SolveRootNode(TMOFile tmo, string effector_name) { Debug.Assert(tmo.nodemap != null, "tso.nodemap should not be null"); TMONode effector; if (tmo.nodemap.TryGetValue(effector_name, out effector)) { effector.Translation = target; } }
static void Main(string[] args) { if (args.Length != 2) { System.Console.WriteLine("Usage: TMOAppend <source tmo> <motion tmo>"); return; } string source_file = args[0]; string motion_file = args[1]; Console.WriteLine("Load File: " + source_file); TMOFile source = new TMOFile(); try { source.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } Console.WriteLine("Load File: " + motion_file); TMOFile motion = new TMOFile(); try { motion.Load(motion_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } try { source.AppendFrameFrom(motion); Console.WriteLine("source nodes {0}", source.nodes.Length); Console.WriteLine("motion nodes {0}", motion.nodes.Length); Console.WriteLine("source frames {0}", source.frames.Length); Console.WriteLine("motion frames {0}", motion.frames.Length); Console.WriteLine("Save File: " + source_file); source.Save(source_file); } catch (ArgumentException ex) { Console.WriteLine(ex.Message); return; } }
/// <summary> /// フィギュアを生成します。 /// </summary> public Figure() { if (SliderMatrixEnabled) { slider_matrix = new SliderMatrix(); } tmo = new TMOFile(); nodemap = new Dictionary <TSONode, TMONode>(); matrixStack = new MatrixStack(); LightDirection = new Vector3(0.0f, 0.0f, -1.0f); }
static void Main(string[] args) { if (args.Length < 2) { System.Console.WriteLine("Usage: TMOAnim <source tmo> <motion tmo> [append length]"); return; } string source_file = args[0]; string motion_file = args[1]; int append_length = 200; if (args.Length > 2) { append_length = int.Parse(args[2]); } Console.WriteLine("Load File: " + source_file); TMOFile source = new TMOFile(); try { source.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } Console.WriteLine("Load File: " + motion_file); TMOFile motion = new TMOFile(); try { motion.Load(motion_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } source.SlerpFrameEndTo(motion, append_length); Console.WriteLine("source nodes Length {0}", source.nodes.Length); Console.WriteLine("motion nodes Length {0}", motion.nodes.Length); Console.WriteLine("source frames Length {0}", source.frames.Length); Console.WriteLine("motion frames Length {0}", motion.frames.Length); Console.WriteLine("Save File: " + source_file); source.Save(source_file); }
static void Main(string[] args) { if (args.Length < 2) { System.Console.WriteLine("Usage: TMONodeCopy <source tmo> <motion tmo> [node name]"); return; } string source_file = args[0]; string motion_file = args[1]; string node_name = "face_oya"; List <string> except_node_names = new List <string>(); except_node_names.Add("Kami_Oya"); if (args.Length > 2) { node_name = args[2]; } Console.WriteLine("Load File: " + source_file); TMOFile source = new TMOFile(); try { source.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } Console.WriteLine("Load File: " + motion_file); TMOFile motion = new TMOFile(); try { motion.Load(motion_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } source.CopyNodeFrom(motion, node_name, except_node_names); Console.WriteLine("Save File: " + source_file); source.Save(source_file); }
/// <summary> /// tmoからtmoを生成します。 /// </summary> public TMOFile GenerateTMOFromTransformationMatrix() { TMOFile tmo = new TMOFile(); tmo.header = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; tmo.opt0 = 1; tmo.opt1 = 0; int node_count = nodes.Length; tmo.nodes = new TMONode[node_count]; for (int i = 0; i < node_count; i++) { tmo.nodes[i] = new TMONode(i); tmo.nodes[i].Path = nodes[i].Path; } tmo.GenerateNodemapAndTree(); int frame_count = 1; tmo.frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { tmo.frames[i] = new TMOFrame(i); int matrix_count = node_count; tmo.frames[i].matrices = new TMOMat[matrix_count]; for (int j = 0; j < matrix_count; j++) { Matrix m = nodes[j].TransformationMatrix; tmo.frames[i].matrices[j] = new TMOMat(ref m); } } foreach (TMONode node in tmo.nodes) { node.LinkMatrices(tmo.frames); } tmo.footer = new byte[4] { 0, 0, 0, 0 }; return(tmo); }
public static int UpdateTmo(string source_file, float angle, string node_name) { string dest_file = source_file + ".tmp"; TMOFile tmo = new TMOFile(); try { tmo.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return(-1); } if (tmo.nodes[0].ShortName != "W_Hips") { Console.WriteLine("Passed: root node is not W_Hips"); return(1); } Dictionary <string, TMONode> nodes = new Dictionary <string, TMONode>(); foreach (TMONode node in tmo.nodes) { try { nodes.Add(node.ShortName, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.ShortName); } } try { TMONode node; node = nodes[node_name]; node.RotateWorldY(DegreeToRadian(angle)); } catch (KeyNotFoundException) { Console.WriteLine("node not found."); } tmo.Save(dest_file); System.IO.File.Delete(source_file); System.IO.File.Move(dest_file, source_file); Console.WriteLine("updated " + source_file); return(0); }
/// <summary> /// モーフ変形の対象となるノードを選択します。 /// </summary> /// <param name="tmo">対象tmo</param> /// <returns>ノードリスト</returns> public List <TMONode> SelectNodes(TMOFile tmo) { List <TMONode> select_nodes = new List <TMONode>(); foreach (string root_name in nodes_range.root_names) { TMONode root_node = tmo.FindNodeByName(root_name); if (root_node != null) { AddTreeNodes(select_nodes, root_node); } } return(select_nodes); }
/// <summary> /// 接地の目標を設定します。 /// </summary> /// <param name="tmo">tmo</param> public void SaveFloorTargets(TMOFile tmo) { Debug.Assert(tmo.nodemap != null, "fig.Tmo.nodemap should not be null"); target_dictionary.Clear(); foreach (string effector_name in effector_list) { TMONode node; if (tmo.nodemap.TryGetValue(effector_name, out node)) { Matrix m = node.combined_matrix; target_dictionary[effector_name] = new Vector3(m.M41, 0, m.M43); } } }
/// <summary> /// 指定tmoからフレームを追加します。 /// </summary> /// <param name="motion">tmo</param> public void AppendFrameFrom(TMOFile motion) { int[] id_pair = CreateNodeIdPair(motion); TMOFrame source_frame = frames[0]; int append_length = motion.frames.Length; TMOFrame[] append_frames = new TMOFrame[append_length]; for (int i = 0; i < motion.frames.Length; i++) append_frames[i] = TMOFrame.Select(source_frame, motion.frames[i], id_pair); int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(append_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length-1; }
/// <summary> /// フィギュアを生成します。 /// </summary> public Figure() { tmo = new TMOFile(); nodemap = new Dictionary <TSONode, TMONode>(); matrixStack = new MatrixStack(); tpo_list.SetProportionList(ProportionList); string config_file = GetTPOConfigPath(); if (File.Exists(config_file)) { TPOConfig config = TPOConfig.Load(config_file); tpo_list.SetRatiosFromConfig(config); } }
/// <summary> /// フィギュアを生成します。 /// </summary> public Figure() { tmo = new TMOFile(); nodemap = new Dictionary<TSONode, TMONode>(); matrixStack = new Stack<Matrix>(); tpo_list.Load(); string config_file = GetTPOConfigPath(); if (File.Exists(config_file)) { TPOConfig config = TPOConfig.Load(config_file); tpo_list.SetRatiosFromConfig(config); } LightDirection = new Vector3(0.0f, 0.0f, -1.0f); }
/// <summary> /// 指定tmoにある指定名称(短い形式)のnodeを同じ名称のnodeに複写します。 /// ただし複写の対象は子node以降です。指定nodeは複写しません。 /// また、除外node以降のnodeは複写しません。 /// </summary> /// <param name="motion">tmo</param> /// <param name="name">node名称(短い形式)</param> /// <param name="except_names">除外node名称(短い形式)リスト</param> public void CopyChildrenNodeFrom(TMOFile motion, string name, List <string> except_names) { TMONode node = this.FindNodeByName(name); if (node == null) { return; } TMONode motion_node = motion.FindNodeByName(name); if (motion_node == null) { return; } node.CopyChildrenMatFrom(motion_node, except_names); }
/// <summary> /// 指定tmoにある指定名称(短い形式)のnodeを同じ名称のnodeに複写します。 /// </summary> /// <param name="motion">tmo</param> /// <param name="name">node名称(短い形式)</param> public void CopyNodeFrom(TMOFile motion, string name) { TMONode node = this.FindNodeByName(name); if (node == null) { return; } TMONode motion_node = motion.FindNodeByName(name); if (motion_node == null) { return; } node.CopyMatFrom(motion_node); }
/// <summary> /// フィギュアを生成します。 /// </summary> public Figure() { tmo = new TMOFile(); nodemap = new Dictionary <TSONode, TMONode>(); matrixStack = new MatrixStack(); tpo_list.Load(); string config_file = GetTPOConfigPath(); if (File.Exists(config_file)) { TPOConfig config = TPOConfig.Load(config_file); tpo_list.SetRatiosFromConfig(config); } LightDirection = new Vector3(0.0f, 0.0f, -1.0f); }
/// <summary> /// root nodeに対する解を得ます。 /// </summary> /// <param name="tmo">tmo</param> /// <param name="effector_name">エフェクタnode名称</param> public void SolveRootNode(TMOFile tmo, string effector_name) { Debug.Assert(tmo.nodemap != null, "tso.nodemap should not be null"); TMONode effector; if (tmo.nodemap.TryGetValue(effector_name, out effector)) { effector.Translation = target; } if (Grounded) { foreach (string ename in effector_list) { Solve(tmo, ename, target_dictionary[ename]); } } }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> protected void UpdateBoneMatricesWithoutSlider(TMOFile tmo, TMOFrame tmo_frame) { if (tmo.nodes == null) { return; } if (tmo.w_hips_node != null) { matrixStack.LoadIdentity(); UpdateBoneMatricesWithoutSlider(tmo.w_hips_node, tmo_frame); } foreach (TMONode tmo_node in tmo.root_nodes_except_w_hips) { matrixStack.LoadIdentity(); UpdateBoneMatricesWithoutSlider(tmo_node, tmo_frame); } }
public static int DisplayTranslation(string source_file) { TMOFile tmo = new TMOFile(); try { tmo.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return(-1); } if (tmo.nodes[0].ShortName != "W_Hips") { Console.WriteLine("Passed: root node is not W_Hips"); return(1); } Dictionary <string, TMONode> nodes = new Dictionary <string, TMONode>(); foreach (TMONode node in tmo.nodes) { try { nodes.Add(node.ShortName, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.ShortName); } } try { TMONode node; node = nodes["W_Hips"]; TMOMat mat = node.frame_matrices[0]; Matrix m = mat.m; Console.WriteLine("{0} {1} {2}", m.M41, m.M42, m.M43); } catch (KeyNotFoundException) { Console.WriteLine("node not found."); } return(0); }
/// <summary> /// 指定tmoからフレームを追加します。 /// </summary> /// <param name="motion">tmo</param> public void AppendFrameFrom(TMOFile motion) { int[] id_pair = CreateNodeIdPair(motion); TMOFrame source_frame = frames[0]; int append_length = motion.frames.Length; TMOFrame[] append_frames = new TMOFrame[append_length]; for (int i = 0; i < motion.frames.Length; i++) { append_frames[i] = TMOFrame.Select(source_frame, motion.frames[i], id_pair); } int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(append_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length - 1; }
/// <summary> /// node idのペアを作成します。 /// ペアのキーはnode id /// ペアの値はもうひとつのtmoにおいて名称(短い形式)が一致するnode idになります。 /// </summary> /// <param name="motion">もうひとつのtmo</param> /// <returns>tmo frame indexのペア</returns> public int[] CreateNodeIdPair(TMOFile motion) { Dictionary <string, TMONode> source_nodes = new Dictionary <string, TMONode>(); Dictionary <string, TMONode> motion_nodes = new Dictionary <string, TMONode>(); foreach (TMONode node in motion.nodes) { try { motion_nodes.Add(node.Name, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.Name); } } foreach (TMONode node in nodes) { if (!motion_nodes.ContainsKey(node.Name)) { throw new ArgumentException("error: node not found in motion: " + node.Name); } try { source_nodes.Add(node.Name, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.Name); } } int[] id_pair = new int[nodes.Length]; foreach (TMONode node in nodes) { id_pair[node.Id] = motion_nodes[node.Name].Id; } return(id_pair); }
static void Main(string[] args) { if (args.Length < 1) { System.Console.WriteLine("Usage: TMOPose <tmo file> [frame]"); return; } string source_file = args[0]; int frame_index = 0; if (args.Length > 1) { try { frame_index = Int32.Parse(args[1]); } catch (FormatException ex) { Console.WriteLine(ex.Message); return; } } Console.WriteLine("Load File: " + source_file); TMOFile source = new TMOFile(); try { source.Load(source_file); } catch (Exception ex) { Console.WriteLine(ex.Message); return; } source.TruncateFrame(frame_index); Console.WriteLine("Save File: " + source_file); source.Save(source_file); }
public void CopyMotionFrom(TMOFile motion) { int[] index_pair = CreateNodeIdPair(motion); TMOFrame source_frame = frames[0]; TMOFrame motion_frame = motion.frames[0]; int append_length = motion.frames.Length; TMOFrame[] interp_frames = new TMOFrame[append_length]; for (int i = 0; i < motion.frames.Length; i++) { interp_frames[i] = TMOFrame.AddSub(source_frame, motion.frames[i], motion_frame, index_pair); } int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(interp_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length - 1; }
/// <summary> /// 指定tmoと同じnode treeを持つか。 /// </summary> /// <param name="motion">tmo</param> /// <returns></returns> public bool IsSameNodeTree(TMOFile motion) { if (nodes.Length != motion.nodes.Length) { //Console.WriteLine("nodes length mismatch {0} {1}", nodes.Length, motion.nodes.Length); return(false); } int i = 0; foreach (TMONode node in nodes) { TMONode motion_node = motion.nodes[i]; //Console.WriteLine("node Name {0} {1}", node.Name, motion_node.Name); if (motion_node.Name != node.Name) { return(false); } i++; } return(true); }
/// <summary> /// 指定tmoへフレームを補間します。 /// </summary> /// <param name="motion">tmo</param> /// <param name="append_length">補間するフレーム長さ</param> /// <param name="p1">補間速度係数</param> public void SlerpFrameEndTo(TMOFile motion, int append_length, float p1) { int[] id_pair = CreateNodeIdPair(motion); int i0 = (frames.Length > 1) ? frames.Length - 1 - 1 : 0; int i1 = frames.Length - 1; int i2 = 0; int i3 = (motion.frames.Length > 1) ? 1 : 0; TMOFrame frame0 = frames[i0]; TMOFrame frame1 = frames[i1]; TMOFrame frame2 = motion.frames[i2]; TMOFrame frame3 = motion.frames[i3]; TMOFrame[] interp_frames = TMOFrame.Slerp(frame0, frame1, frame2, frame3, append_length, p1, id_pair); int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(interp_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length - 1; }
/// <summary> /// 指定tmoへフレームを補間します。 /// </summary> /// <param name="motion">tmo</param> /// <param name="append_length">補間するフレーム長さ</param> public void SlerpFrameEndTo(TMOFile motion, int append_length) { SlerpFrameEndTo(motion, append_length, 0.5f); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMOFile tmo, TMOFrame tmo_frame) { if (tmo.nodes == null) return; if (tmo.w_hips_node != null) { //姉妹スライダによる変形 Matrix local = Matrix.Scaling(slider_matrix.Local); //移動変位を設定 local.M41 = translation.X; local.M42 = translation.Y; local.M43 = translation.Z; matrixStack.Push(local); UpdateBoneMatrices(tmo.w_hips_node, tmo_frame); } foreach (TMONode tmo_node in tmo.root_nodes_except_w_hips) { //移動変位を設定 Matrix local = Matrix.Translation(translation); matrixStack.Push(local); UpdateBoneMatricesWithoutSlideMatrices(tmo_node, tmo_frame); } }
/// <summary> /// モーフを生成します。 /// </summary> public Morph(string name, TMOFile tmo) { this.name = name; this.tmo = tmo; ratio = 0.0f; }
/// <summary> /// モーフ変形を実行します。 /// </summary> /// <param name="tmo">対象tmo</param> public void Morph(TMOFile tmo) { tmo.LoadTransformationMatrixFromFrame(0); Dictionary<TMONode, Matrix> mmap = new Dictionary<TMONode, Matrix>(); foreach (MorphGroup group in groups) { List<TMONode> select_nodes = group.SelectNodes(tmo); foreach (TMONode select_node in select_nodes) { foreach (Morph morph in group.Items) { if (morph.Ratio == 0.0f) continue; TMONode node = morph.Tmo.FindNodeByName(select_node.Name); Matrix min = select_node.TransformationMatrix; Matrix max = node.TransformationMatrix; Matrix inv_min = Matrix.Invert(min); if (! mmap.ContainsKey(select_node)) mmap[select_node] = min; mmap[select_node] = mmap[select_node] * inv_min * SliderMatrix.GetMatrixRatio(min, max, morph.Ratio); } } } foreach (TMONode select_node in mmap.Keys) { select_node.TransformationMatrix = mmap[select_node]; } }
/// <summary> /// 指定tmoへフレームを補間します。 /// </summary> /// <param name="motion">tmo</param> /// <param name="append_length">補間するフレーム長さ</param> /// <param name="p1">補間速度係数</param> public void SlerpFrameEndTo(TMOFile motion, int append_length, float p1) { int[] id_pair = CreateNodeIdPair(motion); int i0 = (frames.Length > 1) ? frames.Length - 1 - 1 : 0; int i1 = frames.Length-1; int i2 = 0; int i3 = ( motion.frames.Length > 1 ) ? 1 : 0; TMOFrame frame0 = frames[i0]; TMOFrame frame1 = frames[i1]; TMOFrame frame2 = motion.frames[i2]; TMOFrame frame3 = motion.frames[i3]; TMOFrame[] interp_frames = TMOFrame.Slerp(frame0, frame1, frame2, frame3, append_length, p1, id_pair); int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(interp_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length-1; }
/// <summary> /// 指定tmoにある指定名称(短い形式)のnodeを同じ名称のnodeに複写します。 /// </summary> /// <param name="motion">tmo</param> /// <param name="name">node名称(短い形式)</param> public void CopyNodeFrom(TMOFile motion, string name) { TMONode node = this.FindNodeByName(name); if (node == null) return; TMONode motion_node = motion.FindNodeByName(name); if (motion_node == null) return; node.CopyMatFrom(motion_node); }
/// <summary> /// tmoからtmoを生成します。 /// </summary> public TMOFile GenerateTMOFromTransformationMatrix() { TMOFile tmo = new TMOFile(); tmo.header = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; tmo.opt0 = 1; tmo.opt1 = 0; int node_count = nodes.Length; tmo.nodes = new TMONode[node_count]; for (int i = 0; i < node_count; i++) { tmo.nodes[i] = new TMONode(i); tmo.nodes[i].Path = nodes[i].Path; } tmo.GenerateNodemapAndTree(); int frame_count = 1; tmo.frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { tmo.frames[i] = new TMOFrame(i); int matrix_count = node_count; tmo.frames[i].matrices = new TMOMat[matrix_count]; for (int j = 0; j < matrix_count; j++) { Matrix m = nodes[j].TransformationMatrix; tmo.frames[i].matrices[j] = new TMOMat(ref m); } } foreach (TMONode node in tmo.nodes) node.LinkMatrices(tmo.frames); tmo.footer = new byte[4] { 0, 0, 0, 0 }; return tmo; }
/// <summary> /// 指定パスからPNGFileを読み込みフィギュアを作成します。 /// </summary> /// <param name="source_file">PNGFileのパス</param> public void Load(string source_file) { if (File.Exists(source_file)) try { PNGFile png = new PNGFile(); Figure fig = null; png.Hsav += delegate(string type) { this.type = type; fig = new Figure(); this.figures.Add(fig); }; png.Pose += delegate(string type) { this.type = type; }; png.Scne += delegate(string type) { this.type = type; }; png.Cami += delegate(Stream dest, int extract_length) { byte[] buf = new byte[extract_length]; dest.Read(buf, 0, extract_length); List<float> factor = new List<float>(); for (int offset = 0; offset < extract_length; offset += sizeof(float)) { float flo = BitConverter.ToSingle(buf, offset); factor.Add(flo); } if (CameraUpdate != null) { Vector3 translation = new Vector3(-factor[0], -factor[1], -factor[2]); Vector3 angle = new Vector3(-factor[5], -factor[4], -factor[6]); CameraUpdate(translation, angle); } }; png.Lgta += delegate(Stream dest, int extract_length) { byte[] buf = new byte[extract_length]; dest.Read(buf, 0, extract_length); List<float> factor = new List<float>(); for (int offset = 0; offset < extract_length; offset += sizeof(float)) { float flo = BitConverter.ToSingle(buf, offset); factor.Add(flo); } Matrix m; m.M11 = factor[0]; m.M12 = factor[1]; m.M13 = factor[2]; m.M14 = factor[3]; m.M21 = factor[4]; m.M22 = factor[5]; m.M23 = factor[6]; m.M24 = factor[7]; m.M31 = factor[8]; m.M32 = factor[9]; m.M33 = factor[10]; m.M34 = factor[11]; m.M41 = factor[12]; m.M42 = factor[13]; m.M43 = factor[14]; m.M44 = factor[15]; this.LightDirection = Vector3.TransformCoordinate(new Vector3(0.0f, 0.0f, -1.0f), m); }; png.Ftmo += delegate(Stream dest, int extract_length) { this.Tmo = new TMOFile(); this.Tmo.Load(dest); }; png.Figu += delegate(Stream dest, int extract_length) { fig = new Figure(); fig.LightDirection = this.LightDirection; fig.Tmo = this.Tmo; this.figures.Add(fig); byte[] buf = new byte[extract_length]; dest.Read(buf, 0, extract_length); List<float> ratios = new List<float>(); for (int offset = 0; offset < extract_length; offset += sizeof(float)) { float flo = BitConverter.ToSingle(buf, offset); ratios.Add(flo); } /* ◆FIGU スライダの位置。値は float型で 0.0 .. 1.0 0: 姉妹 1: うで 2: あし 3: 胴まわり 4: おっぱい 5: つり目たれ目 6: やわらか */ fig.slider_matrix.TallRatio = ratios[0]; fig.slider_matrix.ArmRatio = ratios[1]; fig.slider_matrix.LegRatio = ratios[2]; fig.slider_matrix.WaistRatio = ratios[3]; fig.slider_matrix.BustRatio = ratios[4]; fig.slider_matrix.EyeRatio = ratios[5]; //fig.TransformTpo(); }; png.Ftso += delegate(Stream dest, int extract_length, byte[] opt1) { TSOFile tso = new TSOFile(); tso.Load(dest); tso.Row = opt1[0]; fig.TSOFileList.Add(tso); }; Debug.WriteLine("loading " + source_file); png.Load(source_file); if (this.type == "HSAV") { BMPSaveData data = new BMPSaveData(); using (Stream stream = File.OpenRead(source_file)) data.Read(stream); fig.slider_matrix.TallRatio = data.GetSliderValue(4); fig.slider_matrix.ArmRatio = data.GetSliderValue(5); fig.slider_matrix.LegRatio = data.GetSliderValue(6); fig.slider_matrix.WaistRatio = data.GetSliderValue(7); fig.slider_matrix.BustRatio = data.GetSliderValue(0); fig.slider_matrix.EyeRatio = data.GetSliderValue(8); for (int i = 0; i < fig.TSOFileList.Count; i++) { TSOFile tso = fig.TSOFileList[i]; string file = data.GetFileName(tso.Row); if (file != "") tso.FileName = Path.GetFileName(file); else tso.FileName = string.Format("{0:X2}", tso.Row); } } } catch (Exception ex) { Console.WriteLine("Error: " + ex); } }
/// <summary> /// 指定tmoにある指定名称(短い形式)のnodeを同じ名称のnodeに複写します。 /// ただし複写の対象は子node以降です。指定nodeは複写しません。 /// また、除外node以降のnodeは複写しません。 /// </summary> /// <param name="motion">tmo</param> /// <param name="name">node名称(短い形式)</param> /// <param name="except_names">除外node名称(短い形式)リスト</param> public void CopyChildrenNodeFrom(TMOFile motion, string name, List<string> except_names) { TMONode node = this.FindNodeByName(name); if (node == null) return; TMONode motion_node = motion.FindNodeByName(name); if (motion_node == null) return; node.CopyChildrenMatFrom(motion_node, except_names); }
/// <summary> /// 指定tmoへフレームを補間します。 /// </summary> /// <param name="motion">tmo</param> public void SlerpFrameEndTo(TMOFile motion) { SlerpFrameEndTo(motion, 200, 0.5f); }
/// <summary> /// モーフ変形の対象となるノードを選択します。 /// </summary> /// <param name="tmo">対象tmo</param> /// <returns>ノードリスト</returns> public List<TMONode> SelectNodes(TMOFile tmo) { List<TMONode> select_nodes = new List<TMONode>(); foreach (string root_name in nodes_range.root_names) { TMONode root_node = tmo.FindNodeByName(root_name); if (root_node != null) AddTreeNodes(select_nodes, root_node); } return select_nodes; }
/// <summary> /// 指定tmoと同じnode treeを持つか。 /// </summary> /// <param name="motion">tmo</param> /// <returns></returns> public bool IsSameNodeTree(TMOFile motion) { if (nodes.Length != motion.nodes.Length) { //Console.WriteLine("nodes length mismatch {0} {1}", nodes.Length, motion.nodes.Length); return false; } int i = 0; foreach (TMONode node in nodes) { TMONode motion_node = motion.nodes[i]; //Console.WriteLine("node Name {0} {1}", node.Name, motion_node.Name); if (motion_node.Name != node.Name) return false; i++; } return true; }
/// <summary> /// node idのペアを作成します。 /// ペアのキーはnode id /// ペアの値はもうひとつのtmoにおいて名称(短い形式)が一致するnode idになります。 /// </summary> /// <param name="motion">もうひとつのtmo</param> /// <returns>tmo frame indexのペア</returns> public int[] CreateNodeIdPair(TMOFile motion) { Dictionary<string, TMONode> source_nodes = new Dictionary<string, TMONode>(); Dictionary<string, TMONode> motion_nodes = new Dictionary<string, TMONode>(); foreach (TMONode node in motion.nodes) try { motion_nodes.Add(node.Name, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.Name); } foreach (TMONode node in nodes) { if (! motion_nodes.ContainsKey(node.Name)) { throw new ArgumentException("error: node not found in motion: " + node.Name); } try { source_nodes.Add(node.Name, node); } catch (ArgumentException) { Console.WriteLine("node {0} already exists.", node.Name); } } int[] id_pair = new int[nodes.Length]; foreach (TMONode node in nodes) id_pair[node.ID] = motion_nodes[node.Name].ID; return id_pair; }
/// <summary> /// 指定tmoのモーション(開始フレームからの変位)を複写します。 /// </summary> /// <param name="motion">tmo</param> public void CopyMotionFrom(TMOFile motion) { int[] id_pair = CreateNodeIdPair(motion); TMOFrame source_frame = frames[0]; TMOFrame motion_frame = motion.frames[0]; int append_length = motion.frames.Length; TMOFrame[] interp_frames = new TMOFrame[append_length]; for (int i = 0; i < motion.frames.Length; i++) interp_frames[i] = TMOFrame.AddSub(source_frame, motion.frames[i], motion_frame, id_pair); int old_length = frames.Length; Array.Resize(ref frames, frames.Length + append_length); Array.Copy(interp_frames, 0, frames, old_length, append_length); this.opt0 = frames.Length-1; }
/// <summary> /// 指定ストリームからTMOFileを読み込みます。 /// </summary> /// <param name="source_stream">ストリーム</param> public void LoadTMOFile(Stream source_stream) { Figure fig; if (TryGetFigure(out fig)) { try { TMOFile tmo = new TMOFile(); tmo.Load(source_stream); fig.Tmo = tmo; } catch (Exception ex) { Console.WriteLine("Error: " + ex); } fig.UpdateNodeMapAndBoneMatrices(); if (FigureEvent != null) FigureEvent(this, EventArgs.Empty); } }