protected void UpdateBoneMatrices(TSONode tso_node, TMOFrame tmo_frame) { matrixStack.Push(); Matrix transform; if (tmo_frame != tmo_frame_one) { // TMO animation TMONode tmo_node; if (nodemap.TryGetValue(tso_node, out tmo_node)) { transform = tmo_frame.matrices[tmo_node.ID].m; } else { transform = tso_node.transformation_matrix; } } else { transform = tso_node.transformation_matrix; } matrixStack.MultiplyMatrixLocal(transform); combinedMatrices[tmo_frame][tso_node] = matrixStack.Top; foreach (TSONode child_node in tso_node.child_nodes) { UpdateBoneMatrices(child_node, tmo_frame); } matrixStack.Pop(); }
public static Matrix GetBoneOffsetMatrix(TSONode bone) { Matrix mat = Matrix.Identity; while (bone != null) { mat.Multiply(bone.transformation_matrix); bone = bone.parent; } return(Matrix.Invert(mat)); }
public Matrix GetCombinedMatrix(TSONode tso_node) { TMOFrame tmo_frame; if (tso_node.slow > 0) { tmo_frame = GetTMOFrameSlow(tso_node.slow); } else { tmo_frame = GetTMOFrame(); } return(combinedMatrices[tmo_frame][tso_node]); }
public void Render() { device.BeginScene(); { Matrix world_view_matrix = world_matrix * Transform_View; Matrix world_view_projection_matrix = world_view_matrix * Transform_Projection; effect.SetValue("wld", world_matrix); effect.SetValue("wv", world_view_matrix); effect.SetValue("wvp", world_view_projection_matrix); } device.SetRenderTarget(0, dev_surface); device.DepthStencilSurface = dev_zbuf; device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.LightGray, 1.0f, 0); device.RenderState.AlphaBlendEnable = true; foreach (TSOFigure fig in TSOFigureList) { foreach (TSOFile tso in fig.TSOList) { tso.BeginRender(); foreach (TSOMesh tm in tso.meshes) { foreach (TSOMesh tm_sub in tm.sub_meshes) { device.RenderState.VertexBlend = (VertexBlend)(4 - 1); tso.SwitchShader(tm_sub); Matrix[] clipped_boneMatrices = new Matrix[tm_sub.maxPalettes]; int i = 0; for (int numPalettes = 0; numPalettes < tm_sub.maxPalettes; numPalettes++) { //device.Transform.SetWorldMatrixByIndex(numPalettes, combined_matrix); TSONode bone = tm_sub.GetBone(numPalettes); boneMatrices[numPalettes] = bone.GetOffsetMatrix() * fig.GetCombinedMatrix(bone); } Array.Copy(boneMatrices, clipped_boneMatrices, tm_sub.maxPalettes); effect.SetValue(handle_LocalBoneMats, clipped_boneMatrices); int npass = effect.Begin(0); for (int ipass = 0; ipass < npass; ipass++) { effect.BeginPass(ipass); tm_sub.dm.DrawSubset(i); effect.EndPass(); } effect.End(); } } tso.EndRender(); } } int height = 24; for (int i = 0; i < keys.Length; i++) { if (keys[i]) { font.DrawText(null, ((Keys)i).ToString(), 0, height, Color.Black); height += 24; } } device.EndScene(); device.Present(); Thread.Sleep(30); }
public int Load(Stream source_stream) { try { reader = new BinaryReader(source_stream, System.Text.Encoding.Default); } catch (Exception) { Console.WriteLine("Error: This file cannot be read or does not exist."); return(-1); } byte[] file_header = new byte[4]; file_header = reader.ReadBytes(4); if (!System.Text.Encoding.ASCII.GetString(file_header).Contains("TSO1")) { Console.WriteLine("Error: This seems not to be a TSO file."); } int node_count = reader.ReadInt32(); nodes = new TSONode[node_count]; nodemap = new Dictionary <string, TSONode>(); for (int i = 0; i < node_count; i++) { nodes[i] = new TSONode(); 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].sname); } 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.child_nodes.Add(nodes[i]); } { TSONode node; if (nodemap.TryGetValue("|W_Hips|W_Spine_Dummy|W_Spine1|W_Spine2|W_Spine3|Chichi_Right1", out node)) { node.SlowChildren(); } if (nodemap.TryGetValue("|W_Hips|W_Spine_Dummy|W_Spine1|W_Spine2|W_Spine3|Chichi_Left1", out node)) { node.SlowChildren(); } } int node_matrix_count = reader.ReadInt32(); for (int i = 0; i < node_matrix_count; i++) { nodes[i].transformation_matrix = ReadMatrix(); } for (int i = 0; i < node_matrix_count; i++) { nodes[i].ComputeOffsetMatrix(); } UInt32 texture_count = reader.ReadUInt32(); textures = new TSOTex[texture_count]; for (int i = 0; i < texture_count; i++) { textures[i] = read_texture(); } UInt32 script_count = reader.ReadUInt32(); scripts = new TSOScript[script_count]; for (int i = 0; i < script_count; i++) { scripts[i] = read_script(); } UInt32 sub_script_count = reader.ReadUInt32(); TSOScript[] sub_scripts = new TSOScript[sub_script_count]; for (int i = 0; i < sub_script_count; i++) { sub_scripts[i] = read_sub_script(); } scripts[0].sub_scripts = sub_scripts; UInt32 mesh_count = reader.ReadUInt32(); meshes = new TSOMesh[mesh_count]; for (int i = 0; i < mesh_count; i++) { TSOMesh mesh = read_mesh(); meshes[i] = mesh; //Console.WriteLine("mesh name {0} len {1}", mesh.name, mesh.sub_meshes.Length); } reader.Close(); return(0); }
public TSOMesh read_mesh() { TSOMesh mesh = new TSOMesh(); mesh.name = ReadString(); mesh.name = mesh.name.Replace(":", "_colon_").Replace("#", "_sharp_"); //should be compatible with directx naming conventions mesh.transform_matrix = ReadMatrix(); mesh.unknown1 = reader.ReadUInt32(); mesh.sub_mesh_count = reader.ReadUInt32(); mesh.sub_meshes = new TSOMesh[mesh.sub_mesh_count]; mesh.spec = 0; mesh.bone_index_LUT = new List <UInt32>(); mesh.bone_LUT = new List <TSONode>(); mesh.vertices = new vertex_field[0]; for (int a = 0; a < mesh.sub_mesh_count; a++) { TSOMesh act_mesh = new TSOMesh(); mesh.sub_meshes[a] = act_mesh; act_mesh.name = mesh.name + "_sub_" + a.ToString(); act_mesh.transform_matrix = mesh.transform_matrix; act_mesh.unknown1 = mesh.unknown1; act_mesh.sub_mesh_count = 0; act_mesh.spec = reader.ReadInt32(); int bone_index_LUT_entry_count = reader.ReadInt32(); //numbones act_mesh.maxPalettes = 16; if (act_mesh.maxPalettes > bone_index_LUT_entry_count) { act_mesh.maxPalettes = bone_index_LUT_entry_count; } act_mesh.bone_index_LUT = new List <UInt32>(); act_mesh.bone_LUT = new List <TSONode>(); for (int i = 0; i < bone_index_LUT_entry_count; i++) { act_mesh.bone_index_LUT.Add(reader.ReadUInt32()); } int vertex_count = reader.ReadInt32(); //numvertices act_mesh.vertices = new vertex_field[vertex_count]; for (int i = 0; i < vertex_count; i++) { ReadVertex(ref act_mesh.vertices[i]); } } for (int a = 0; a < mesh.sub_mesh_count; a++) { TSOMesh sub_mesh = mesh.sub_meshes[a]; for (int i = 0; i < sub_mesh.bone_index_LUT.Count; i++) { UInt32 bone_index = sub_mesh.bone_index_LUT[i]; TSONode bone = nodes[bone_index]; sub_mesh.bone_LUT.Add(bone); } } return(mesh); }
public void ComputeOffsetMatrix() { offset_matrix = TSONode.GetBoneOffsetMatrix(this); }