diff --git a/File_Format_Library/FileFormats/Collision/KCL.cs b/File_Format_Library/FileFormats/Collision/KCL.cs index a222f351..b0860438 100644 --- a/File_Format_Library/FileFormats/Collision/KCL.cs +++ b/File_Format_Library/FileFormats/Collision/KCL.cs @@ -93,7 +93,7 @@ namespace FirstPlugin { public STToolStripItem[] NewFileMenuExtensions => null; public STToolStripItem[] NewFromFileMenuExtensions => newFileExt; - public STToolStripItem[] ToolsMenuExtensions => null; + public STToolStripItem[] ToolsMenuExtensions => toolExt; public STToolStripItem[] TitleBarExtensions => null; public STToolStripItem[] CompressionMenuExtensions => null; public STToolStripItem[] ExperimentalMenuExtensions => null; @@ -101,11 +101,65 @@ namespace FirstPlugin public ToolStripButton[] IconButtonMenuExtensions => null; STToolStripItem[] newFileExt = new STToolStripItem[2]; + STToolStripItem[] toolExt = new STToolStripItem[1]; public MenuExt() { newFileExt[0] = new STToolStripItem("KCL (Switch)", CreateNew); newFileExt[1] = new STToolStripItem("KCL (Wii U)", CreateNew); + + toolExt[0] = new STToolStripItem("KCL (Monoscript MKT) to OBJ", MontoscriptToOBJ); + } + + public void MontoscriptToOBJ(object sender, EventArgs args) + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "All files(*.*)|*.*"; + if (ofd.ShowDialog() == DialogResult.OK) + { + KclMonoscript monscript = new KclMonoscript(); + monscript.ReadKCL(ofd.FileName); + + SaveFileDialog sfd = new SaveFileDialog(); + if (sfd.ShowDialog() == DialogResult.OK) + { + var model = new STGenericModel(); + var mesh = new STGenericObject(); + mesh.faces = new List(); + model.Objects = new List() { mesh }; + int ft = 0; + foreach (var prisim in monscript.Prisims) + { + var triangle = monscript.GetTriangle(prisim); + var normal = triangle.Normal; + var pointA = triangle.PointA; + var pointB = triangle.PointB; + var pointC = triangle.PointC; + + Vertex vtx = new Vertex(); + Vertex vtx2 = new Vertex(); + Vertex vtx3 = new Vertex(); + + vtx.pos = pointA; + vtx2.pos = pointB; + vtx3.pos = pointC; + vtx.nrm = normal; + vtx2.nrm = normal; + vtx3.nrm = normal; + + mesh.faces.Add(ft); + mesh.faces.Add(ft + 1); + mesh.faces.Add(ft + 2); + mesh.vertices.Add(vtx); + mesh.vertices.Add(vtx2); + mesh.vertices.Add(vtx3); + + ft += 3; + } + + OBJ.ExportModel(sfd.FileName, model, new List()); + } + } } public void CreateNew(object sender, EventArgs args) diff --git a/File_Format_Library/FileFormats/Collision/KclMonoscript.cs b/File_Format_Library/FileFormats/Collision/KclMonoscript.cs index d8fbecda..c81bd888 100644 --- a/File_Format_Library/FileFormats/Collision/KclMonoscript.cs +++ b/File_Format_Library/FileFormats/Collision/KclMonoscript.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; +using OpenTK; namespace FirstPlugin { @@ -12,17 +13,55 @@ namespace FirstPlugin /// public class KclMonoscript { - public class HeaderV2 - { + public List Vertices = new List(); + public List Normals = new List(); + public List Prisims = new List(); + public List Faces = new List(); + + public class Prisim + { + public float Length; + public ushort VertexIndex; + public ushort DirectionIndex; + public ushort NormalAIndex; + public ushort NormalBIndex; + public ushort NormalCIndex; + public ushort CollisionType; + public uint TriangleIndex; } - public class HeaderV1 + public class Triangle { + public Vector3 PointA; + public Vector3 PointB; + public Vector3 PointC; + public Triangle(Vector3 A, Vector3 B, Vector3 C) + { + PointA = A; + PointB = B; + PointC = C; + } + + public Vector3 Normal + { + get + { + return Vector3.Cross(PointB - PointA, PointC - PointA).Normalized(); + } + } } - public HeaderV2 Header; + public Triangle GetTriangle(Prisim Plane) + { + Vector3 A = Vertices[Plane.VertexIndex]; + Vector3 CrossA = Vector3.Cross(Normals[Plane.NormalAIndex], Normals[Plane.DirectionIndex]); + Vector3 CrossB = Vector3.Cross(Normals[Plane.NormalBIndex], Normals[Plane.DirectionIndex]); + Vector3 B = A + CrossB * (Plane.Length / Vector3.Dot(CrossB, Normals[Plane.NormalCIndex])); + Vector3 C = A + CrossA * (Plane.Length / Vector3.Dot(CrossA, Normals[Plane.NormalCIndex])); + return new Triangle(A, B, C); + } public void ReadKCL(string fileName) { @@ -31,13 +70,96 @@ namespace FirstPlugin while (!reader.EndOfStream) { string line = reader.ReadLine(); - if (line.Contains("KCollisionV2Header ")) - { - Header = new HeaderV2(); + if (line.Contains("mPosData")) + { + reader.ReadLine();//Array + uint numVertex = GetValueUint(reader.ReadLine()); + + for (int i = 0; i < numVertex; i++) + { + reader.ReadLine();//Index value + reader.ReadLine();//Vector + float X = GetValue32(reader.ReadLine()); //X + float Y = GetValue32(reader.ReadLine()); //Y + float Z = GetValue32(reader.ReadLine()); //Z + Vertices.Add(new Vector3(X,Y,Z)); + } + } + if (line.Contains("mNrmData")) + { + reader.ReadLine();//Array + uint numVertex = GetValueUint(reader.ReadLine()); + + for (int i = 0; i < numVertex; i++) + { + reader.ReadLine();//Index value + reader.ReadLine();//Vector + float X = GetValue32(reader.ReadLine()); //X + float Y = GetValue32(reader.ReadLine()); //Y + float Z = GetValue32(reader.ReadLine()); //Z + Normals.Add(new Vector3(X, Y, Z)); + } + } + if (line.Contains("mPrismData")) + { + reader.ReadLine();//Array + uint numPrisims = GetValueUint(reader.ReadLine()); + uint faceIndex = 0; + for (int i = 0; i < numPrisims; i++) + { + reader.ReadLine();//Index value + reader.ReadLine();//data + + Prisim prisim = new Prisim(); + prisim.Length = GetValue32(reader.ReadLine()); + prisim.VertexIndex = GetValueUint16(reader.ReadLine()); + prisim.DirectionIndex = GetValueUint16(reader.ReadLine()); + prisim.NormalAIndex = GetValueUint16(reader.ReadLine()); + prisim.NormalBIndex = GetValueUint16(reader.ReadLine()); + prisim.NormalCIndex = GetValueUint16(reader.ReadLine()); + prisim.CollisionType = GetValueUint16(reader.ReadLine()); + prisim.TriangleIndex = GetValueUint(reader.ReadLine()); + Prisims.Add(prisim); + + Faces.Add(faceIndex); + Faces.Add(faceIndex + 1); + Faces.Add(faceIndex + 2); + + faceIndex += 3; + } } } } } + + private ushort GetValueUint16(string line) + { + string value = line.Split('=').Last(); + ushort valueU = 0; + ushort.TryParse(value, out valueU); + return valueU; + } + + private uint GetValueUint(string line) + { + string value = line.Split('=').Last(); + uint valueU = 0; + uint.TryParse(value, out valueU); + return valueU; + } + + private float GetValue32(string line) + { + string value = line.Split('=').Last(); + float valueF = 0; + float.TryParse(value, out valueF); + return valueF; + } + + private string GetValue(string line) + { + return line.Split('=').Last(); + } } } diff --git a/Switch_Toolbox_Library/FileFormats/OBJ.cs b/Switch_Toolbox_Library/FileFormats/OBJ.cs index 5520bc4a..73d45ffa 100644 --- a/Switch_Toolbox_Library/FileFormats/OBJ.cs +++ b/Switch_Toolbox_Library/FileFormats/OBJ.cs @@ -20,7 +20,7 @@ namespace Toolbox.Library //Write materials StringBuilder writerMtl = new StringBuilder(); - SaveMaterials(writerMtl, Model); + // SaveMaterials(writerMtl, Model); File.WriteAllText(fileMtlPath, writerMtl.ToString()); } @@ -40,10 +40,9 @@ namespace Toolbox.Library writer.AppendLine($"mtllib {MtlName}"); int VertexCount = 1; - foreach (STGenericObject mesh in Model.Nodes[0].Nodes) + foreach (STGenericObject mesh in Model.Objects) { - var mat = GetMaterial(mesh.MaterialIndex, Model); - SaveMesh(writer, mesh, mat, VertexCount); + SaveMesh(writer, mesh, null, VertexCount); } } @@ -81,7 +80,11 @@ namespace Toolbox.Library private static STGenericMaterial GetMaterial(int MaterialIndex, STGenericModel Model) { - if (MaterialIndex < Model.Nodes[1].Nodes.Count) + int numMaterials = 0; + foreach (var mat in Model.Materials) + numMaterials++; + + if (MaterialIndex < numMaterials) return (STGenericMaterial)Model.Nodes[1].Nodes[MaterialIndex]; else return null;