From 550ebf65b33971fcf70a067f35b5cb7a362df509 Mon Sep 17 00:00:00 2001 From: Dr-HyperCake Date: Fri, 29 Mar 2024 10:45:17 +1100 Subject: [PATCH] Add NUD float UV support --- Smash Forge/Filetypes/Models/Nuds/Material.cs | 4 +- Smash Forge/Filetypes/Models/Nuds/NUD.cs | 86 ++++++++++++------- Smash Forge/Filetypes/Models/Nuds/Polygon.cs | 15 +++- 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/Smash Forge/Filetypes/Models/Nuds/Material.cs b/Smash Forge/Filetypes/Models/Nuds/Material.cs index ddf590a5..cb4f9cfb 100644 --- a/Smash Forge/Filetypes/Models/Nuds/Material.cs +++ b/Smash Forge/Filetypes/Models/Nuds/Material.cs @@ -44,11 +44,11 @@ public uint Flags public int AlphaFunc = 0; public int AlphaTest { get { return AlphaFunc >> 8; } - set { AlphaFunc = value << 8; } + set { AlphaFunc = (value << 8) | (AlphaFunc & 0xFF); } } public int AlphaFunction { get { return AlphaFunc & 0xFF; } - set { AlphaFunc = value & 0xFF; } + set { AlphaFunc = (AlphaFunc & 0xFF00) | (value & 0xFF); } } public int RefAlpha { get; set; } diff --git a/Smash Forge/Filetypes/Models/Nuds/NUD.cs b/Smash Forge/Filetypes/Models/Nuds/NUD.cs index 68cd8a41..bc2b1a46 100644 --- a/Smash Forge/Filetypes/Models/Nuds/NUD.cs +++ b/Smash Forge/Filetypes/Models/Nuds/NUD.cs @@ -802,7 +802,7 @@ public void ApplyMta(MTA m, int frame) // Helpers for reading private struct ObjectData { - public int singlebind; + public short singlebind; public int polyCount; public int positionb; public string name; @@ -899,7 +899,7 @@ public override void Read(string filename) m.Text = o.name; Nodes.Add(m); m.boneflag = boneflags[meshIndex]; - m.singlebind = (short)o.singlebind; + m.singlebind = o.singlebind; m.boundingSphere = boundingSpheres[meshIndex++]; for (int i = 0; i < o.polyCount; i++) @@ -1039,17 +1039,20 @@ private static Polygon ReadVertex(FileData d, PolyData p, ObjectData o) if (m.boneType > 0) { foreach (Vertex v in vertices) - ReadUV(d, p, o, m, v); + ReadUV(d, m, v); d.Seek(p.verAddStart); foreach (Vertex v in vertices) - ReadVertex(d, p, o, m, v); + ReadVertex(d, m, v); } else { foreach (Vertex v in vertices) { - ReadVertex(d, p, o, m, v); - ReadUV(d, p, o, m, v); + ReadVertex(d, m, v); + ReadUV(d, m, v); + + v.boneIds.Add(o.singlebind); + v.boneWeights.Add(1); } } @@ -1066,28 +1069,36 @@ private static Polygon ReadVertex(FileData d, PolyData p, ObjectData o) return m; } - private static void ReadUV(FileData d, PolyData p, ObjectData o, Polygon m, Vertex v) + private static void ReadUV(FileData d, Polygon poly, Vertex v) { - int uvCount = (p.UVSize >> 4); - int colorType = (p.UVSize) & 0xF; + int uvCount = poly.uvCount; + int colorType = poly.colorType; + int uvType = poly.uvType; - if (colorType == 0x0) + if (colorType == (int)Polygon.VertexColorTypes.None) {} - else if (colorType == 0x2) + else if (colorType == (int)Polygon.VertexColorTypes.Byte) v.color = new Vector4(d.ReadByte(), d.ReadByte(), d.ReadByte(), d.ReadByte()); - else if (colorType == 0x4) + else if (colorType == (int)Polygon.VertexColorTypes.HalfFloat) v.color = new Vector4(d.ReadHalfFloat() * 0xFF, d.ReadHalfFloat() * 0xFF, d.ReadHalfFloat() * 0xFF, d.ReadHalfFloat() * 0xFF); else - throw new NotImplementedException("UV type not supported " + colorType); + throw new NotImplementedException($"Unsupported vertex color type: {colorType}"); - for (int j = 0; j < uvCount; j++) - v.uv.Add(new Vector2(d.ReadHalfFloat(), d.ReadHalfFloat())); + for (int i = 0; i < uvCount; i++) + { + if (uvType == (int)Polygon.UVTypes.HalfFloat) + v.uv.Add(new Vector2(d.ReadHalfFloat(), d.ReadHalfFloat())); + else if (uvType == (int)Polygon.UVTypes.Float) + v.uv.Add(new Vector2(d.ReadFloat(), d.ReadFloat())); + else + throw new NotImplementedException($"Unsupported UV type: {uvType}"); + } } - private static void ReadVertex(FileData d, PolyData p, ObjectData o, Polygon m, Vertex v) + private static void ReadVertex(FileData d, Polygon poly, Vertex v) { - int boneType = p.vertSize & 0xF0; - int vertexType = p.vertSize & 0xF; + int boneType = poly.boneType; + int vertexType = poly.normalType; v.pos.X = d.ReadFloat(); v.pos.Y = d.ReadFloat(); @@ -1166,8 +1177,6 @@ private static void ReadVertex(FileData d, PolyData p, ObjectData o, Polygon m, if (boneType == (int)Polygon.BoneTypes.NoBones) { - v.boneIds.Add((short)o.singlebind); - v.boneWeights.Add(1); } else if (boneType == (int)Polygon.BoneTypes.Float) { @@ -1392,20 +1401,21 @@ public override byte[] Rebuild() private static void WriteUV(FileOutput d, Polygon poly, Vertex v) { - int uvCount = (poly.UVSize >> 4); - int colorType = (poly.UVSize) & 0xF; + int uvCount = poly.uvCount; + int colorType = poly.colorType; + int uvType = poly.uvType; - if (colorType == 0x0) + if (colorType == (int)Polygon.VertexColorTypes.None) { } - else if (colorType == 0x2) + else if (colorType == (int)Polygon.VertexColorTypes.Byte) { d.WriteByte((int)v.color.X); d.WriteByte((int)v.color.Y); d.WriteByte((int)v.color.Z); d.WriteByte((int)v.color.W); } - else if (colorType == 0x4) + else if (colorType == (int)Polygon.VertexColorTypes.HalfFloat) { d.WriteHalfFloat(v.color.X / 0xFF); d.WriteHalfFloat(v.color.Y / 0xFF); @@ -1414,20 +1424,32 @@ private static void WriteUV(FileOutput d, Polygon poly, Vertex v) } else { - throw new NotImplementedException("UV type not supported " + colorType); + throw new NotImplementedException($"Unsupported vertex color type: {colorType}"); } - for (int j = 0; j < uvCount; j++) + for (int i = 0; i < uvCount; i++) { - d.WriteHalfFloat(v.uv[j].X); - d.WriteHalfFloat(v.uv[j].Y); + if (uvType == (int)Polygon.UVTypes.HalfFloat) + { + d.WriteHalfFloat(v.uv[i].X); + d.WriteHalfFloat(v.uv[i].Y); + } + else if (uvType == (int)Polygon.UVTypes.Float) + { + d.WriteFloat(v.uv[i].X); + d.WriteFloat(v.uv[i].Y); + } + else + { + throw new NotImplementedException($"Unsupported UV type: {uvType}"); + } } } private static void WriteVertex(FileOutput d, Polygon poly, Vertex v) { - int boneType = poly.vertSize & 0xF0; - int vertexType = poly.vertSize & 0xF; + int boneType = poly.boneType; + int vertexType = poly.normalType; d.WriteFloat(v.pos.X); d.WriteFloat(v.pos.Y); @@ -1820,8 +1842,8 @@ private static void SingleBindMesh(Mesh m, int singleBindBone) m.singlebind = (short)singleBindBone; foreach (Polygon p in m.Nodes) { + p.boneType = 0; p.polflag = 0; - p.vertSize = p.vertSize & 0x0F; } } diff --git a/Smash Forge/Filetypes/Models/Nuds/Polygon.cs b/Smash Forge/Filetypes/Models/Nuds/Polygon.cs index 02b2dc54..4954a464 100644 --- a/Smash Forge/Filetypes/Models/Nuds/Polygon.cs +++ b/Smash Forge/Filetypes/Models/Nuds/Polygon.cs @@ -13,7 +13,7 @@ public class Polygon : TreeNode, IBoundableModel { public enum BoneTypes { - NoBones = 0x00, + NoBones = 0x00, Float = 0x10, HalfFloat = 0x20, Byte = 0x40 @@ -28,6 +28,12 @@ public enum VertexTypes NormalsTanBiTanHalfFloat = 0x7 } + public enum UVTypes + { + HalfFloat = 0, + Float = 1 // Only seen in Wangan Midnight + } + public enum VertexColorTypes { None = 0, @@ -67,10 +73,11 @@ public int vertSize { public int uvCount = 1; public int colorType = (int)VertexColorTypes.Byte; - // uvCount is upper nybble, normalType is lower nybble + public int uvType = (int)UVTypes.HalfFloat; + // uvCount is upper nybble, colorType and uvType is lower nybble public int UVSize { - get { return (uvCount << 4) | (colorType & 0xF); } - set { uvCount = value >> 4; colorType = value & 0xF; } + get { return (uvCount << 4) | (colorType & 0xE) | uvType; } + set { uvCount = value >> 4; colorType = value & 0xE; uvType = value & 1;} } public int strip = (int)PrimitiveTypes.Triangles;