Add obj converter tool for monscript KCL files (Mario Kart Tour collision)
This commit is contained in:
parent
46e7970581
commit
fff96d1a0d
@ -93,7 +93,7 @@ namespace FirstPlugin
|
|||||||
{
|
{
|
||||||
public STToolStripItem[] NewFileMenuExtensions => null;
|
public STToolStripItem[] NewFileMenuExtensions => null;
|
||||||
public STToolStripItem[] NewFromFileMenuExtensions => newFileExt;
|
public STToolStripItem[] NewFromFileMenuExtensions => newFileExt;
|
||||||
public STToolStripItem[] ToolsMenuExtensions => null;
|
public STToolStripItem[] ToolsMenuExtensions => toolExt;
|
||||||
public STToolStripItem[] TitleBarExtensions => null;
|
public STToolStripItem[] TitleBarExtensions => null;
|
||||||
public STToolStripItem[] CompressionMenuExtensions => null;
|
public STToolStripItem[] CompressionMenuExtensions => null;
|
||||||
public STToolStripItem[] ExperimentalMenuExtensions => null;
|
public STToolStripItem[] ExperimentalMenuExtensions => null;
|
||||||
@ -101,11 +101,65 @@ namespace FirstPlugin
|
|||||||
public ToolStripButton[] IconButtonMenuExtensions => null;
|
public ToolStripButton[] IconButtonMenuExtensions => null;
|
||||||
|
|
||||||
STToolStripItem[] newFileExt = new STToolStripItem[2];
|
STToolStripItem[] newFileExt = new STToolStripItem[2];
|
||||||
|
STToolStripItem[] toolExt = new STToolStripItem[1];
|
||||||
|
|
||||||
public MenuExt()
|
public MenuExt()
|
||||||
{
|
{
|
||||||
newFileExt[0] = new STToolStripItem("KCL (Switch)", CreateNew);
|
newFileExt[0] = new STToolStripItem("KCL (Switch)", CreateNew);
|
||||||
newFileExt[1] = new STToolStripItem("KCL (Wii U)", 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<int>();
|
||||||
|
model.Objects = new List<STGenericObject>() { 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<STGenericTexture>());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateNew(object sender, EventArgs args)
|
public void CreateNew(object sender, EventArgs args)
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace FirstPlugin
|
namespace FirstPlugin
|
||||||
{
|
{
|
||||||
@ -12,17 +13,55 @@ namespace FirstPlugin
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class KclMonoscript
|
public class KclMonoscript
|
||||||
{
|
{
|
||||||
public class HeaderV2
|
public List<Vector3> Vertices = new List<Vector3>();
|
||||||
{
|
public List<Vector3> Normals = new List<Vector3>();
|
||||||
|
public List<Prisim> Prisims = new List<Prisim>();
|
||||||
|
|
||||||
|
public List<uint> Faces = new List<uint>();
|
||||||
|
|
||||||
|
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 HeaderV2 Header;
|
public Vector3 Normal
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Vector3.Cross(PointB - PointA, PointC - PointA).Normalized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
public void ReadKCL(string fileName)
|
||||||
{
|
{
|
||||||
@ -31,13 +70,96 @@ namespace FirstPlugin
|
|||||||
while (!reader.EndOfStream)
|
while (!reader.EndOfStream)
|
||||||
{
|
{
|
||||||
string line = reader.ReadLine();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace Toolbox.Library
|
|||||||
|
|
||||||
//Write materials
|
//Write materials
|
||||||
StringBuilder writerMtl = new StringBuilder();
|
StringBuilder writerMtl = new StringBuilder();
|
||||||
SaveMaterials(writerMtl, Model);
|
// SaveMaterials(writerMtl, Model);
|
||||||
File.WriteAllText(fileMtlPath, writerMtl.ToString());
|
File.WriteAllText(fileMtlPath, writerMtl.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,10 +40,9 @@ namespace Toolbox.Library
|
|||||||
writer.AppendLine($"mtllib {MtlName}");
|
writer.AppendLine($"mtllib {MtlName}");
|
||||||
|
|
||||||
int VertexCount = 1;
|
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, null, VertexCount);
|
||||||
SaveMesh(writer, mesh, mat, VertexCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,11 @@ namespace Toolbox.Library
|
|||||||
|
|
||||||
private static STGenericMaterial GetMaterial(int MaterialIndex, STGenericModel Model)
|
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];
|
return (STGenericMaterial)Model.Nodes[1].Nodes[MaterialIndex];
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
|
Loading…
Reference in New Issue
Block a user