/// <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); } }
/// <summary> /// フレームを補間します。 /// </summary> /// <param name="frame0">フレーム0</param> /// <param name="frame1">フレーム1</param> /// <param name="frame2">フレーム2</param> /// <param name="frame3">フレーム3</param> /// <param name="length">分割数</param> /// <param name="p1">補間速度係数</param> /// <param name="id_pair">node idのペア</param> /// <returns></returns> public static TMOFrame[] Slerp(TMOFrame frame0, TMOFrame frame1, TMOFrame frame2, TMOFrame frame3, int length, float p1, int[] id_pair) { TMOFrame[] frames = new TMOFrame[length]; for (int frame_index = 0; frame_index < length; frame_index++) { frames[frame_index] = new TMOFrame(frame_index); frames[frame_index].matrices = new TMOMat[frame1.matrices.Length]; } for (int i = 0; i < frame1.matrices.Length; i++) { TMOMat[] interpolated_matrices = TMOMat.Slerp( frame0.matrices[i], frame1.matrices[i], frame2.matrices[id_pair[i]], frame3.matrices[id_pair[i]], length, p1); for (int frame_index = 0; frame_index < length; frame_index++) { frames[frame_index].matrices[i] = interpolated_matrices[frame_index]; } } return(frames); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMONode tmo_node, TMOFrame tmo_frame) { matrixStack.Push(); if (tmo_frame != null) { // tmo animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.Id].m; } Matrix m = tmo_node.TransformationMatrix; if (slider_matrix != null) { bool chichi_p = re_chichi.IsMatch(tmo_node.Name); if (chichi_p) { slider_matrix.ScaleChichi(tmo_node, ref m); if (slider_matrix.Flat()) { if (clothed) { slider_matrix.TransformChichiFlatClothed(tmo_node, ref m); } else { slider_matrix.TransformChichiFlat(tmo_node, ref m); } } } else { slider_matrix.TransformFace(tmo_node, ref m); } matrixStack.MultiplyMatrixLocal(m); m = matrixStack.Top; if (!chichi_p) { slider_matrix.Scale(tmo_node, ref m); } } else { matrixStack.MultiplyMatrixLocal(m); m = matrixStack.Top; } tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
/// <summary> /// frame1の行列で構成された新たなframeを得ます。 /// 新たなframeはframe0と同じnode並びとなります。 /// </summary> /// <param name="frame0"></param> /// <param name="frame1"></param> /// <param name="id_pair">node idのペア</param> /// <returns>新たなframe</returns> public static TMOFrame Select(TMOFrame frame0, TMOFrame frame1, int[] id_pair) { TMOFrame ret = new TMOFrame(0); ret.matrices = new TMOMat[frame0.matrices.Length]; for (int i = 0; i < frame0.matrices.Length; i++) { ret.matrices[i] = frame1.matrices[id_pair[i]]; } return(ret); }
/// <summary> /// 加減算の結果として新たなframeを得ます。 /// 新たなframeはframe0と同じnode並びとなります。 /// </summary> /// <param name="frame0">frame0</param> /// <param name="frame1">frame1</param> /// <param name="frame2">frame2</param> /// <param name="id_pair">node idのペア</param> /// <returns>新たなframe</returns> public static TMOFrame AddSub(TMOFrame frame0, TMOFrame frame1, TMOFrame frame2, int[] id_pair) { TMOFrame ret = new TMOFrame(0); ret.matrices = new TMOMat[frame0.matrices.Length]; for (int i = 0; i < frame0.matrices.Length; i++) { ret.matrices[i] = TMOMat.AddSub(frame0.matrices[i], frame1.matrices[id_pair[i]], frame2.matrices[id_pair[i]]); } return(ret); }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> /// <param name="forced">falseの場合frame indexに変更なければ更新しません。</param> public void UpdateBoneMatricesWithoutSlider(bool forced = false) { if (!forced && frame_index == current_frame_index) { return; } current_frame_index = frame_index; TMOFrame tmo_frame = GetTMOFrame(); UpdateBoneMatricesWithoutSlider(tmo, tmo_frame); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMONode tmo_node, TMOFrame tmo_frame) { if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; bool chichi_p = re_chichi.IsMatch(tmo_node.Name); if (chichi_p) { if (slider_matrix.Flat()) { slider_matrix.TransformChichiFlat(tmo_node, ref m); } else { slider_matrix.TranslateChichi(ref m); } } else { // todo: face_p slider_matrix.TransformFace(tmo_node, ref m); } matrixStack.Push(m * matrixStack.Peek()); m = matrixStack.Peek(); if (chichi_p) { if (!slider_matrix.Flat()) { slider_matrix.ScaleChichi(ref m); } } else { // todo: scale1map slider_matrix.Scale(tmo_node, ref m); } tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
/// <summary> /// bone行列を更新します。 /// </summary> /// <param name="forced">falseの場合frame indexに変更なければ更新しません。</param> public void UpdateBoneMatrices(bool forced) { if (!forced && frame_index == current_frame_index) { return; } current_frame_index = frame_index; TMOFrame tmo_frame = GetTMOFrame(); UpdateBoneMatrices(tmo, tmo_frame); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMONode tmo_node, TMOFrame tmo_frame) { matrixStack.Push(); if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; bool is_chichi = re_chichi.IsMatch(tmo_node.Name); if (is_chichi) { if (slide_matrices.Flat()) { slide_matrices.TransformChichiFlat(tmo_node, ref m); } } else { slide_matrices.TransformFace(tmo_node, ref m); } matrixStack.MultiplyMatrixLocal(m); m = matrixStack.Top; if (is_chichi) { if (!slide_matrices.Flat()) { slide_matrices.ScaleChichi(ref m); } } else { slide_matrices.Scale(tmo_node, ref m); } tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
/// <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> /// bone行列を更新します。 /// </summary> /// <param name="forced">falseの場合frame indexに変更なければ更新しません。</param> public void UpdateBoneMatrices(bool forced = false) { if (!forced && frame_index == current_frame_index) { return; } current_frame_index = frame_index; TMOFrame tmo_frame = GetTMOFrame(); UpdateBoneMatrices(tmo, tmo_frame); if (UpdateBoneMatricesEvent != null) { UpdateBoneMatricesEvent(this, EventArgs.Empty); } }
/// <summary> /// 指定ストリームから読み込みます。 /// </summary> /// <param name="source_stream">ストリーム</param> public void Load(Stream source_stream) { this.reader = new BinaryReader(source_stream, System.Text.Encoding.Default); byte[] magic = reader.ReadBytes(4); if (magic[0] != (byte)'T' || magic[1] != (byte)'M' || magic[2] != (byte)'O' || magic[3] != (byte)'1') { throw new Exception("File is not TMO"); } this.header = reader.ReadBytes(8); this.opt0 = reader.ReadInt32(); this.opt1 = reader.ReadInt32(); int node_count = reader.ReadInt32(); nodes = new TMONode[node_count]; for (int i = 0; i < node_count; i++) { nodes[i] = new TMONode(i); nodes[i].Read(reader); } GenerateNodemapAndTree(); int frame_count = reader.ReadInt32(); frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { frames[i] = new TMOFrame(i); frames[i].Read(reader); } foreach (TMONode node in nodes) { node.LinkMatrices(frames); } this.footer = reader.ReadBytes(4); }
/// <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); } }
/// <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; }
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; }
//初期モーション行列値を保持する領域を確保します。 private void CreateFrames() { if (tmo.frames == null) { return; } int frame_count = tmo.frames.Length; frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { int matrix_count = tmo.frames[i].matrices.Length; frames[i] = new TMOFrame(i); frames[i].matrices = new TMOMat[matrix_count]; for (int j = 0; j < matrix_count; j++) { frames[i].matrices[j] = new TMOMat(); } } }
/// <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> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMOFile tmo, TMOFrame tmo_frame) { if (tmo.nodes == null) { return; } //先頭nodeをrootとみなす TMONode tmo_node = tmo.nodes[0]; //姉妹スライダによる変形 Matrix local = Matrix.Scaling(slide_matrices.Local); //移動変位を設定 local.M41 = translation.X; local.M42 = translation.Y; local.M43 = translation.Z; matrixStack.LoadMatrix(local); UpdateBoneMatrices(tmo_node, tmo_frame); }
/// <summary> /// 指定番号のフレームに含まれるモーション行列値を変形します。 /// </summary> /// <param name="frame_index">フレーム番号</param> public void Transform(int frame_index) { if (ratio == 0) { return; } if (tmo.frames == null) { return; } TMOFrame frame = tmo.frames[frame_index]; Debug.Assert(frame.matrices.Length == nodes.Length); for (int j = 0; j < frame.matrices.Length; j++) { TPONode node = nodes[j]; TMOMat mat = frame.matrices[j]; node.Transform(mat, ratio); } }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> protected void UpdateBoneMatricesWithoutSlideMatrices(TMONode tmo_node, TMOFrame tmo_frame) { //matrixStack.Push(); if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; matrixStack.Push(m * matrixStack.Peek()); m = matrixStack.Peek(); tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> protected void UpdateBoneMatricesWithoutSlider(TMONode tmo_node, TMOFrame tmo_frame) { matrixStack.Push(); if (tmo_frame != null) { // tmo animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.Id].m; } Matrix m = tmo_node.TransformationMatrix; matrixStack.MultiplyMatrixLocal(m); m = matrixStack.Top; tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatricesWithoutSlider(child_node, tmo_frame); } matrixStack.Pop(); }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> protected void UpdateBoneMatricesWithoutSlider(TMOFile tmo, TMOFrame tmo_frame) { if (tmo.nodes == null) { return; } if (tmo.w_hips_node != null) { //移動変位を設定 Matrix local = Matrix.Translation(translation); matrixStack.LoadMatrix(local); UpdateBoneMatricesWithoutSlider(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); UpdateBoneMatricesWithoutSlider(tmo_node, tmo_frame); } }
//初期モーション行列値を保持する領域を確保します。 private void CreateFrames() { if (tmo.frames == null) return; int frame_count = tmo.frames.Length; frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { int matrix_count = tmo.frames[i].matrices.Length; frames[i] = new TMOFrame(i); frames[i].matrices = new TMOMat[matrix_count]; for (int j = 0; j < matrix_count; j++) { frames[i].matrices[j] = new TMOMat(); } } }
public void Load(Stream source_stream) { this.reader = new BinaryReader(source_stream, System.Text.Encoding.Default); byte[] magic = reader.ReadBytes(4); if (magic[0] != (byte)'T' || magic[1] != (byte)'M' || magic[2] != (byte)'O' || magic[3] != (byte)'1') { throw new Exception("File is not TMO"); } this.header = reader.ReadBytes(8); this.opt0 = reader.ReadInt32(); this.opt1 = reader.ReadInt32(); int node_count = reader.ReadInt32(); nodes = new TMONode[node_count]; nodemap = new Dictionary <string, TMONode>(); for (int i = 0; i < node_count; i++) { nodes[i] = new TMONode(); nodes[i].id = i; nodes[i].name = ReadString(); nodes[i].sname = nodes[i].name.Substring(nodes[i].name.LastIndexOf('|') + 1); nodemap.Add(nodes[i].name, nodes[i]); //Console.WriteLine(i + ": " + nodes[i].name); } for (int i = 0; i < node_count; i++) { int index = nodes[i].name.LastIndexOf('|'); if (index <= 0) { continue; } string pname = nodes[i].name.Substring(0, index); nodes[i].parent = nodemap[pname]; nodes[i].parent.children.Add(nodes[i]); } int frame_count = reader.ReadInt32(); frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { frames[i] = new TMOFrame(); frames[i].id = i; int matrix_count = reader.ReadInt32(); frames[i].matrices = new TMOMat[matrix_count]; for (int j = 0; j < matrix_count; j++) { frames[i].matrices[j] = new TMOMat(ReadMatrix()); nodes[j].frame_matrices.Add(frames[i].matrices[j]); //Console.WriteLine(frames[i].matrices[j].m); } } this.footer = reader.ReadBytes(4); reader.Close(); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMONode tmo_node, TMOFrame tmo_frame) { matrixStack.Push(); if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; bool is_chichi = re_chichi.IsMatch(tmo_node.Name); if (is_chichi && slide_matrices.Flat()) { switch (tmo_node.Name) { case "Chichi_Right1": m *= slide_matrices.ChichiR1; break; case "Chichi_Right2": m *= slide_matrices.ChichiR2; break; case "Chichi_Right3": m *= slide_matrices.ChichiR3; break; case "Chichi_Right4": m *= slide_matrices.ChichiR4; break; case "Chichi_Right5": m *= slide_matrices.ChichiR5; break; case "Chichi_Right5_end": m *= slide_matrices.ChichiR5E; break; case "Chichi_Left1": m *= slide_matrices.ChichiL1; break; case "Chichi_Left2": m *= slide_matrices.ChichiL2; break; case "Chichi_Left3": m *= slide_matrices.ChichiL3; break; case "Chichi_Left4": m *= slide_matrices.ChichiL4; break; case "Chichi_Left5": m *= slide_matrices.ChichiL5; break; case "Chichi_Left5_End": m *= slide_matrices.ChichiL5E; break; } // translationを維持する必要があるため // translationに対してscalingを打ち消す演算を行う。 Vector3 scaling = slide_matrices.Chichi; m.M41 /= scaling.X; m.M42 /= scaling.Y; m.M43 /= scaling.Z; switch (tmo_node.Name) { case "Chichi_Right1": case "Chichi_Left1": m *= Matrix.Scaling(scaling); break; } } switch (tmo_node.Name) { case "face_oya": Scale1(ref m, slide_matrices.FaceOya); break; case "eyeline_sita_L": case "L_eyeline_oya_L": case "Me_Right_Futi": m *= slide_matrices.EyeR; break; case "eyeline_sita_R": case "R_eyeline_oya_R": case "Me_Left_Futi": m *= slide_matrices.EyeL; break; } matrixStack.MultiplyMatrixLocal(m); m = matrixStack.Top; // スライダによる体型変更 // translationを維持する必要があるため // このscalingはmatrixStackに適用しない。 switch (tmo_node.Name) { case "W_Spine_Dummy": Scale1(ref m, slide_matrices.SpineDummy); break; case "W_Spine1": case "W_Spine2": Scale1(ref m, slide_matrices.Spine1); break; case "W_LeftHips_Dummy": case "W_RightHips_Dummy": Scale1(ref m, slide_matrices.HipsDummy); break; case "W_LeftUpLeg": case "W_RightUpLeg": Scale1(ref m, slide_matrices.UpLeg); break; case "W_LeftUpLegRoll": case "W_RightUpLegRoll": case "W_LeftLeg": case "W_RightLeg": Scale1(ref m, slide_matrices.UpLegRoll); break; case "W_LeftLegRoll": case "W_RightLegRoll": case "W_LeftFoot": case "W_RightFoot": case "W_LeftToeBase": case "W_RightToeBase": Scale1(ref m, slide_matrices.LegRoll); break; case "W_LeftArm_Dummy": case "W_RightArm_Dummy": Scale1(ref m, slide_matrices.ArmDummy); break; case "W_LeftArm": case "W_RightArm": case "W_LeftArmRoll": case "W_RightArmRoll": case "W_LeftForeArm": case "W_RightForeArm": case "W_LeftForeArmRoll": case "W_RightForeArmRoll": Scale1(ref m, slide_matrices.Arm); break; } if (is_chichi && !slide_matrices.Flat()) { Scale1(ref m, slide_matrices.Chichi); } tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
/// <summary> /// frame1の行列で構成された新たなframeを得ます。 /// 新たなframeはframe0と同じnode並びとなります。 /// </summary> /// <param name="frame0"></param> /// <param name="frame1"></param> /// <param name="id_pair">node idのペア</param> /// <returns>新たなframe</returns> public static TMOFrame Select(TMOFrame frame0, TMOFrame frame1, int[] id_pair) { TMOFrame ret = new TMOFrame(0); ret.matrices = new TMOMat[frame0.matrices.Length]; for (int i = 0; i < frame0.matrices.Length; i++) { ret.matrices[i] = frame1.matrices[id_pair[i]]; } return ret; }
/// <summary> /// bone行列を更新します(体型変更なし)。 /// </summary> protected void UpdateBoneMatricesWithoutSlideMatrices(TMONode tmo_node, TMOFrame tmo_frame) { //matrixStack.Push(); if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; matrixStack.Push(m * matrixStack.Peek()); m = matrixStack.Peek(); tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) UpdateBoneMatrices(child_node, tmo_frame); matrixStack.Pop(); }
/// <summary> /// bone行列を更新します。 /// </summary> protected void UpdateBoneMatrices(TMONode tmo_node, TMOFrame tmo_frame) { if (tmo_frame != null) { // TMO animation tmo_node.TransformationMatrix = tmo_frame.matrices[tmo_node.ID].m; } Matrix m = tmo_node.TransformationMatrix; bool chichi_p = re_chichi.IsMatch(tmo_node.Name); if (chichi_p) { if (slider_matrix.Flat()) slider_matrix.TransformChichiFlat(tmo_node, ref m); else slider_matrix.TranslateChichi(ref m); } else // todo: face_p slider_matrix.TransformFace(tmo_node, ref m); matrixStack.Push(m * matrixStack.Peek()); m = matrixStack.Peek(); if (chichi_p) { if (! slider_matrix.Flat()) { slider_matrix.ScaleChichi(ref m); } } else // todo: scale1map slider_matrix.Scale(tmo_node, ref m); tmo_node.combined_matrix = m; foreach (TMONode child_node in tmo_node.children) UpdateBoneMatrices(child_node, tmo_frame); matrixStack.Pop(); }
public static void Write(BinaryWriter bw, TMOFrame item) { Write(bw, item.matrices); }
/// <summary> /// 加減算の結果として新たなframeを得ます。 /// 新たなframeはframe0と同じnode並びとなります。 /// </summary> /// <param name="frame0">frame0</param> /// <param name="frame1">frame1</param> /// <param name="frame2">frame2</param> /// <param name="id_pair">node idのペア</param> /// <returns>新たなframe</returns> public static TMOFrame AddSub(TMOFrame frame0, TMOFrame frame1, TMOFrame frame2, int[] id_pair) { TMOFrame ret = new TMOFrame(0); ret.matrices = new TMOMat[frame0.matrices.Length]; for (int i = 0; i < frame0.matrices.Length; i++) { ret.matrices[i] = TMOMat.AddSub( frame0.matrices[i], frame1.matrices[id_pair[i]], frame2.matrices[id_pair[i]] ); } return ret; }
/// <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> /// 行列をリンクします。 /// </summary> public void LinkMatrices(TMOFrame[] frames) { this.matrices.Clear(); foreach (TMOFrame frame in frames) this.matrices.Add(frame.matrices[id]); }
/// <summary> /// 指定ストリームから読み込みます。 /// </summary> /// <param name="source_stream">ストリーム</param> public void Load(Stream source_stream) { this.reader = new BinaryReader(source_stream, System.Text.Encoding.Default); byte[] magic = reader.ReadBytes(4); if (magic[0] != (byte)'T' || magic[1] != (byte)'M' || magic[2] != (byte)'O' || magic[3] != (byte)'1') throw new Exception("File is not TMO"); this.header = reader.ReadBytes(8); this.opt0 = reader.ReadInt32(); this.opt1 = reader.ReadInt32(); int node_count = reader.ReadInt32(); nodes = new TMONode[node_count]; for (int i = 0; i < node_count; i++) { nodes[i] = new TMONode(i); nodes[i].Read(reader); } GenerateNodemapAndTree(); int frame_count = reader.ReadInt32(); frames = new TMOFrame[frame_count]; for (int i = 0; i < frame_count; i++) { frames[i] = new TMOFrame(i); frames[i].Read(reader); } foreach (TMONode node in nodes) node.LinkMatrices(frames); this.footer = reader.ReadBytes(4); }
/// <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> /// <param name="frame0">フレーム0</param> /// <param name="frame1">フレーム1</param> /// <param name="frame2">フレーム2</param> /// <param name="frame3">フレーム3</param> /// <param name="length">分割数</param> /// <param name="p1">補間速度係数</param> /// <param name="id_pair">node idのペア</param> /// <returns></returns> public static TMOFrame[] Slerp(TMOFrame frame0, TMOFrame frame1, TMOFrame frame2, TMOFrame frame3, int length, float p1, int[] id_pair) { TMOFrame[] frames = new TMOFrame[length]; for (int frame_index = 0; frame_index < length; frame_index++) { frames[frame_index] = new TMOFrame(frame_index); frames[frame_index].matrices = new TMOMat[frame1.matrices.Length]; } for (int i = 0; i < frame1.matrices.Length; i++) { TMOMat[] interpolated_matrices = TMOMat.Slerp( frame0.matrices[i], frame1.matrices[i], frame2.matrices[id_pair[i]], frame3.matrices[id_pair[i]], length, p1); for (int frame_index = 0; frame_index < length; frame_index++) frames[frame_index].matrices[i] = interpolated_matrices[frame_index]; } return frames; }