private static void WriteOBJHeader(ObjBuilder builder, int verts, int faces) { builder.Comment($"Generated by LSDView {Version.String}, created by Figglewatts, 2020"); builder.Comment("https://github.com/Figglewatts/LSDView"); builder.Comment($"Vertices: {verts}"); builder.Comment($"Faces: {faces}"); }
public static string TMDToOBJFile(TMD tmd) { int vertCount = (int)tmd.NumberOfVertices; int faceCount = 0; foreach (var tmdObj in tmd.ObjectTable) { faceCount += (int)tmdObj.NumPrimitives; } ObjBuilder obj = new ObjBuilder(); WriteOBJHeader(obj, vertCount, faceCount); List <Vector3> positions = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); foreach (var tmdObj in tmd.ObjectTable) { foreach (Vec3 vert in tmdObj.Vertices) { positions.Add(new Vector3(vert.X, vert.Y, vert.Z)); } foreach (var norm in tmdObj.Normals) { normals.Add(new Vector3(norm.X, norm.Y, norm.Z)); } } foreach (var pos in positions) { obj.Vertex(pos); } foreach (var norm in normals) { obj.Normal(norm); } foreach (var tmdObj in tmd.ObjectTable) { foreach (var prim in tmdObj.Primitives) { if (prim.PacketData is ITMDTexturedPrimitivePacket uvPacket) { for (int j = 0; j < prim.PacketData.Vertices.Length; j++) { int uvIndex = j * 2; obj.UV(new Vector2(uvPacket.UVs[uvIndex] / 255f, uvPacket.UVs[uvIndex + 1] / 255f)); } } } } ObjFaceBuilder faceBuilder = new ObjFaceBuilder(); int indexBase = 0; for (int i = 0; i < tmd.Header.NumObjects; i++) { obj.Group($"Object {i}"); int uvCount = 1; foreach (var prim in tmd.ObjectTable[i].Primitives) { ITMDPrimitivePacket primitivePacket = prim.PacketData; ITMDTexturedPrimitivePacket texPrimitivePacket = prim.PacketData as ITMDTexturedPrimitivePacket; ITMDLitPrimitivePacket litPrimitivePacket = prim.PacketData as ITMDLitPrimitivePacket; int[] indices = new int[primitivePacket.Vertices.Length]; for (int vert = 0; vert < primitivePacket.Vertices.Length; vert++) { int v = indexBase + primitivePacket.Vertices[vert] + 1; indices[vert] = v; int?t = null; int?n = null; if (texPrimitivePacket != null) { t = uvCount++; } if (litPrimitivePacket != null) { n = litPrimitivePacket.Normals[vert] + 1; } } bool isQuad = (prim.Options & TMDPrimitivePacket.OptionsFlags.Quad) != 0; bool isDoubleSided = (prim.Flags & TMDPrimitivePacket.PrimitiveFlags.DoubleSided) != 0; faceBuilder.Vertex(indices[1]); faceBuilder.Vertex(indices[0]); faceBuilder.Vertex(indices[2]); obj.Face(faceBuilder.Build()); faceBuilder.Clear(); if (isQuad) { faceBuilder.Vertex(indices[1]); faceBuilder.Vertex(indices[2]); faceBuilder.Vertex(indices[3]); obj.Face(faceBuilder.Build()); faceBuilder.Clear(); } if (isDoubleSided) { obj.Comment("DOuble sided!"); faceBuilder.Vertex(indices[0]); faceBuilder.Vertex(indices[1]); faceBuilder.Vertex(indices[2]); obj.Face(faceBuilder.Build()); faceBuilder.Clear(); if (isQuad) { faceBuilder.Vertex(indices[2]); faceBuilder.Vertex(indices[1]); faceBuilder.Vertex(indices[3]); obj.Face(faceBuilder.Build()); faceBuilder.Clear(); } } faceBuilder.Clear(); } indexBase += tmd.ObjectTable[i].Vertices.Length; } return(obj.ToString()); }