From f6f657812c1973172d25d7895aabb37f900071a7 Mon Sep 17 00:00:00 2001 From: Treeki Date: Fri, 11 Feb 2011 04:33:24 +0100 Subject: lots of progress. semi-working Wavefront OBJ exporter --- NW4RTools/BrresReader.cs | 11 +- NW4RTools/Models/VertexData.cs | 49 +++---- NW4RTools/NW4RTools.csproj | 3 + NW4RTools/ObjWriter.cs | 65 +++++++++- NW4RTools/VertexSettings.cs | 234 ++++++++++++++++++++++++++++++++++ NW4RTools/bin/Debug/NW4RTools.dll | Bin 36352 -> 40448 bytes NW4RTools/bin/Debug/NW4RTools.dll.mdb | Bin 12709 -> 13672 bytes 7 files changed, 320 insertions(+), 42 deletions(-) create mode 100644 NW4RTools/VertexSettings.cs (limited to 'NW4RTools') diff --git a/NW4RTools/BrresReader.cs b/NW4RTools/BrresReader.cs index 49f2edb..288ff1e 100644 --- a/NW4RTools/BrresReader.cs +++ b/NW4RTools/BrresReader.cs @@ -340,6 +340,8 @@ namespace NW4RTools { private void LoadVertexDataBase(InputStream ins, Models.VertexDataBase n) { + int startPos = ins.Position; + UInt32 size = ins.ReadUInt32(); Int32 mdlOffset = ins.ReadInt32(); @@ -349,13 +351,18 @@ namespace NW4RTools { // Note: we're relying on this value to be correct, for Shape mappings n.Index = ins.ReadUInt32(); - n.ComponentCount = (CompCount)ins.ReadUInt32(); - n.ComponentType = (CompType)ins.ReadUInt32(); + n.ComponentCount = (VertexSettings.CompCount)ins.ReadUInt32(); + n.ComponentType = (VertexSettings.CompType)ins.ReadUInt32(); n.Fraction = ins.ReadByte(); n.EntrySize = ins.ReadByte(); n.EntryCount = ins.ReadUInt16(); + int structEndPos = ins.Position; + + ins.Seek(startPos + dataOffset); n.Data = ins.ReadBytes(n.EntrySize * n.EntryCount); + + ins.Seek(structEndPos); } private Dictionary VtxPosIndexLookup; diff --git a/NW4RTools/Models/VertexData.cs b/NW4RTools/Models/VertexData.cs index b1f65cd..5b1a50a 100644 --- a/NW4RTools/Models/VertexData.cs +++ b/NW4RTools/Models/VertexData.cs @@ -1,31 +1,11 @@ using System; namespace NW4RTools.Models { - public enum CompCount { - Position2 = 0, - Position3 = 1, - Normal3 = 0, - Color3 = 0, - Color4 = 1, - TexCoord1 = 0, - TexCoord2 = 1 - } - - - public enum CompType { - UInt8 = 0, - Int8 = 1, - UInt16 = 2, - Int16 = 3, - Float32 = 4 - } - - public abstract class VertexDataBase { public UInt32 Index; - public CompCount ComponentCount; - public CompType ComponentType; + public VertexSettings.CompCount ComponentCount; + public VertexSettings.CompType ComponentType; public byte Fraction /* Not used for colours */, EntrySize; public UInt16 EntryCount; @@ -46,18 +26,19 @@ namespace NW4RTools.Models { for (int i = 0; i < ret.Length; i++) { switch (ComponentType) { - case CompType.UInt8: + case VertexSettings.CompType.UInt8: break; - case CompType.Int8: + case VertexSettings.CompType.Int8: ret[i] = (float)ins.ReadSByte() * scale; break; - case CompType.UInt16: + case VertexSettings.CompType.UInt16: ret[i] = (float)ins.ReadUInt16() * scale; break; - case CompType.Int16: + case VertexSettings.CompType.Int16: ret[i] = (float)ins.ReadInt16() * scale; + //Console.WriteLine("Output into {0}: {3:X} {1} with scale {2}", i, ret[i], scale, v); break; - case CompType.Float32: + case VertexSettings.CompType.Float32: ret[i] = ins.ReadFloat(); break; default: @@ -80,9 +61,9 @@ namespace NW4RTools.Models { public override int GetRealCount() { switch (ComponentCount) { - case CompCount.Position2: + case VertexSettings.CompCount.Position2: return 2; - case CompCount.Position3: + case VertexSettings.CompCount.Position3: return 3; default: return -1; @@ -97,7 +78,7 @@ namespace NW4RTools.Models { public override int GetRealCount() { switch (ComponentCount) { - case CompCount.Normal3: + case VertexSettings.CompCount.Normal3: return 3; default: return -1; @@ -112,9 +93,9 @@ namespace NW4RTools.Models { public override int GetRealCount() { switch (ComponentCount) { - case CompCount.Color3: + case VertexSettings.CompCount.Color3: return 3; - case CompCount.Color4: + case VertexSettings.CompCount.Color4: return 4; default: return -1; @@ -131,9 +112,9 @@ namespace NW4RTools.Models { public override int GetRealCount() { switch (ComponentCount) { - case CompCount.TexCoord1: + case VertexSettings.CompCount.TexCoord1: return 1; - case CompCount.TexCoord2: + case VertexSettings.CompCount.TexCoord2: return 2; default: return -1; diff --git a/NW4RTools/NW4RTools.csproj b/NW4RTools/NW4RTools.csproj index 954271d..8f9aa75 100644 --- a/NW4RTools/NW4RTools.csproj +++ b/NW4RTools/NW4RTools.csproj @@ -20,6 +20,7 @@ prompt 4 false + true none @@ -28,6 +29,7 @@ prompt 4 false + true @@ -53,6 +55,7 @@ + diff --git a/NW4RTools/ObjWriter.cs b/NW4RTools/ObjWriter.cs index 72a134c..297ae58 100644 --- a/NW4RTools/ObjWriter.cs +++ b/NW4RTools/ObjWriter.cs @@ -93,7 +93,26 @@ namespace NW4RTools { private void WriteShape(Models.Shape shape) { - // parse the DisplayList + // first, parse the first DisplayList to get the attr info + // for now we'll hardcode the offsets. must be fixed later + + var firstDL = new InputStream(shape.DisplayList1); + firstDL.Seek(0x0C); + UInt32 vtxDesc1 = firstDL.ReadUInt32(); + firstDL.Seek(0x12); + UInt32 vtxDesc2 = firstDL.ReadUInt32(); + firstDL.Seek(0x22); + UInt32 vtxAttr1 = firstDL.ReadUInt32(); + firstDL.Seek(0x28); + UInt32 vtxAttr2 = firstDL.ReadUInt32(); + firstDL.Seek(0x2E); + UInt32 vtxAttr3 = firstDL.ReadUInt32(); + + var vs = new VertexSettings(); + vs.SetDesc(vtxDesc1, vtxDesc2); + vs.SetAttrFmt(vtxAttr1, vtxAttr2, vtxAttr3); + + // now parse the second DisplayList int posOffset = VtxPosOffsets[shape.PosData]; int nrmOffset = shape.NrmData == null ? -1 : VtxNrmOffsets[shape.NrmData]; @@ -106,22 +125,56 @@ namespace NW4RTools { break; byte cmd = dl.ReadByte(); - PrimitiveType prim = (PrimitiveType)cmd; + if (cmd == 0) + break; + + PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7); int vtxCount = dl.ReadUInt16(); Output.WriteLine("# Primitive: {0} ({1} vertices)", prim, vtxCount); - // I wonder if INDEX8 is ever used here? - // Going with INDEX16 for now. + // first, parse it into a list of vertices + GXIndexedVertex[] vtxs = new GXIndexedVertex[vtxCount]; + string[] pVtxs = new string[vtxCount]; + + for (int i = 0; i < vtxCount; i++) { + vtxs[i].LoadFrom(dl, vs); + + string tc = (vtxs[i].TexCoords[0] == -1) ? "" : (tcOffset + vtxs[i].TexCoords[0]).ToString(); + string n = (vtxs[i].Normal == -1) ? "" : (nrmOffset + vtxs[i].Normal).ToString(); + pVtxs[i] = String.Format(" {0}/{1}/{2}", posOffset + vtxs[i].Position, tc, n); + } switch (prim) { + case PrimitiveType.Triangles: + for (int i = 0; i < vtxCount; i += 3) { + Output.WriteLine("f {0} {1} {2}", pVtxs[i], pVtxs[i + 1], pVtxs[i + 2]); + } + + break; + case PrimitiveType.TriangleStrip: // De-stripify it! - + for (int i = 2; i < vtxCount; i++) { + Output.Write("f"); + if ((i & 1) == 0) { + // Even number + Output.Write(pVtxs[i - 2]); + Output.Write(pVtxs[i - 1]); + Output.Write(pVtxs[i]); + } else { + // Odd number + Output.Write(pVtxs[i - 1]); + Output.Write(pVtxs[i - 2]); + Output.Write(pVtxs[i]); + } + Output.WriteLine(); + } break; default: - throw new NotImplementedException(); + Output.WriteLine("# UNIMPLEMENTED"); + return; } } } diff --git a/NW4RTools/VertexSettings.cs b/NW4RTools/VertexSettings.cs new file mode 100644 index 0000000..5eac02a --- /dev/null +++ b/NW4RTools/VertexSettings.cs @@ -0,0 +1,234 @@ +using System; + +namespace NW4RTools { + public struct GXIndexedVertex { + public int Position; + public int Normal; + + public int[] Colors; + public int[] TexCoords; + + + + public void LoadFrom(InputStream ins, VertexSettings vs) { + if (vs.PNMatrixIndexExists) + throw new NotImplementedException(); + if (vs.TexCoordMatrixIndexExists[0]) + throw new NotImplementedException(); + // won't bother with the rest + + switch (vs.PositionDesc) { + case VertexSettings.DescType.Direct: + throw new NotImplementedException(); + case VertexSettings.DescType.None: + throw new NotImplementedException(); + case VertexSettings.DescType.Index8: + Position = ins.ReadByte(); + if (Position == 0xFF) + Position = -1; + break; + case VertexSettings.DescType.Index16: + Position = ins.ReadUInt16(); + if (Position == 0xFFFF) + Position = -1; + break; + } + + // not sure how to detect NBT3 yet + switch (vs.NormalDesc) { + case VertexSettings.DescType.Direct: + throw new NotImplementedException(); + case VertexSettings.DescType.None: + Normal = -1; + break; + case VertexSettings.DescType.Index8: + Normal = ins.ReadByte(); + if (Normal == 0xFF) + Normal = -1; + break; + case VertexSettings.DescType.Index16: + Normal = ins.ReadUInt16(); + if (Normal == 0xFFFF) + Normal = -1; + break; + } + + Colors = new int[2]; + + for (int i = 0; i < 2; i++) { + switch (vs.ColorDesc[i]) { + case VertexSettings.DescType.Direct: + throw new NotImplementedException(); + case VertexSettings.DescType.None: + Colors[i] = -1; + break; + case VertexSettings.DescType.Index8: + Colors[i] = ins.ReadByte(); + if (Colors[i] == 0xFF) + Colors[i] = -1; + break; + case VertexSettings.DescType.Index16: + Colors[i] = ins.ReadUInt16(); + if (Colors[i] == 0xFFFF) + Colors[i] = -1; + break; + } + } + + TexCoords = new int[8]; + + for (int i = 0; i < 8; i++) { + switch (vs.TexCoordDesc[i]) { + case VertexSettings.DescType.Direct: + throw new NotImplementedException(); + case VertexSettings.DescType.None: + TexCoords[i] = -1; + break; + case VertexSettings.DescType.Index8: + TexCoords[i] = ins.ReadByte(); + if (TexCoords[i] == 0xFF) + TexCoords[i] = -1; + break; + case VertexSettings.DescType.Index16: + TexCoords[i] = ins.ReadUInt16(); + if (TexCoords[i] == 0xFFFF) + TexCoords[i] = -1; + break; + } + } + } + } + + + + public class VertexSettings { + public enum DescType { + None, + Direct, + Index8, + Index16 + } + + public enum CompCount { + Position2 = 0, + Position3 = 1, + Normal3 = 0, + NBT = 1, + NBT3 = 2, + Color3 = 0, + Color4 = 1, + TexCoord1 = 0, + TexCoord2 = 1 + } + + public enum CompType { + UInt8 = 0, + Int8 = 1, + UInt16 = 2, + Int16 = 3, + Float32 = 4 + } + + + public bool PNMatrixIndexExists; + public bool[] TexCoordMatrixIndexExists; + public DescType PositionDesc, NormalDesc; + public DescType[] ColorDesc, TexCoordDesc; + + public CompCount PositionCount, NormalCount; + public CompCount[] ColorCount, TexCoordCount; + + public CompType PositionFormat, NormalFormat; + public CompType[] ColorFormat, TexCoordFormat; + + public byte PositionFrac; + public byte[] TexCoordFrac; + + + + public VertexSettings() { + TexCoordMatrixIndexExists = new bool[8]; + + ColorDesc = new DescType[2]; + TexCoordDesc = new DescType[8]; + + ColorCount = new CompCount[2]; + TexCoordCount = new CompCount[8]; + + ColorFormat = new CompType[2]; + TexCoordFormat = new CompType[8]; + + TexCoordFrac = new byte[8]; + } + + + public void SetDesc(UInt32 val1, UInt32 val2) { + PNMatrixIndexExists = ((val1 & 1) != 0); + + for (int i = 0; i < 8; i++) + TexCoordMatrixIndexExists[i] = ((val1 & (2 << i)) != 0); + + PositionDesc = (DescType)((val1 & 0x600) >> 9); + NormalDesc = (DescType)((val1 & 0x1800) >> 11); + ColorDesc[0] = (DescType)((val1 & 0x6000) >> 13); + ColorDesc[1] = (DescType)((val1 & 0x18000) >> 15); + + for (int i = 0; i < 8; i++) + TexCoordDesc[i] = (DescType)((val2 & (3 << (i * 2))) >> (i * 2)); + } + + public void SetAttrFmt(UInt32 val1, UInt32 val2, UInt32 val3) { + PositionCount = (CompCount)(val1 & 1); + PositionFormat = (CompType)((val1 & 0xE) >> 3); + PositionFrac = (byte)((val1 & 0x1F0) >> 4); + + // note: this field is special + bool IsNormalSet = ((val1 & 0x200) != 0); + bool UseNormalIndex3 = ((val1 & 0x80000000) != 0); + NormalCount = IsNormalSet ? (UseNormalIndex3 ? CompCount.NBT3 : CompCount.NBT) : CompCount.Normal3; + NormalFormat = (CompType)((val1 & 0x1C00) >> 10); + + ColorCount[0] = (CompCount)((val1 & 0x2000) >> 13); + ColorFormat[0] = (CompType)((val1 & 0x1C000) >> 14); + + ColorCount[1] = (CompCount)((val1 & 0x20000) >> 17); + ColorFormat[1] = (CompType)((val1 & 0x1C0000) >> 18); + + TexCoordCount[0] = (CompCount)((val1 & 0x200000) >> 21); + TexCoordFormat[0] = (CompType)((val1 & 0x1C00000) >> 22); + TexCoordFrac[0] = (byte)((val1 & 0x3E000000) >> 25); + + // set in various cases, see libogc gx.c for info + bool ByteDequant = ((val1 & 0x40000000) != 0); + + TexCoordCount[1] = (CompCount)(val2 & 0x1); + TexCoordFormat[1] = (CompType)((val2 & 0xE) >> 1); + TexCoordFrac[1] = (byte)((val2 & 0x1F0) >> 4); + + TexCoordCount[2] = (CompCount)((val2 & 0x200) >> 9); + TexCoordFormat[2] = (CompType)((val2 & 0x1C00) >> 10); + TexCoordFrac[2] = (byte)((val2 & 0x3E000) >> 13); + + TexCoordCount[3] = (CompCount)((val2 & 0x40000) >> 18); + TexCoordFormat[3] = (CompType)((val2 & 0x380000) >> 19); + TexCoordFrac[3] = (byte)((val2 & 0x3E000000) >> 22); + + TexCoordCount[4] = (CompCount)((val2 & 0x8000000) >> 27); + TexCoordFormat[4] = (CompType)((val2 & 0x70000000) >> 28); + TexCoordFrac[4] = (byte)(val3 & 0x1F); + + TexCoordCount[5] = (CompCount)((val3 & 0x20) >> 5); + TexCoordFormat[5] = (CompType)((val3 & 0x1C0) >> 6); + TexCoordFrac[5] = (byte)((val3 & 0x3E00) >> 9); + + TexCoordCount[6] = (CompCount)((val3 & 0x4000) >> 14); + TexCoordFormat[6] = (CompType)((val3 & 0x38000) >> 15); + TexCoordFrac[6] = (byte)((val3 & 0x7C0000) >> 18); + + TexCoordCount[7] = (CompCount)((val3 & 0x800000) >> 23); + TexCoordFormat[7] = (CompType)((val3 & 0x7000000) >> 24); + TexCoordFrac[7] = (byte)((val3 & 0xF8000000) >> 27); + } + } +} + diff --git a/NW4RTools/bin/Debug/NW4RTools.dll b/NW4RTools/bin/Debug/NW4RTools.dll index a1602c8..b0fe3d4 100755 Binary files a/NW4RTools/bin/Debug/NW4RTools.dll and b/NW4RTools/bin/Debug/NW4RTools.dll differ diff --git a/NW4RTools/bin/Debug/NW4RTools.dll.mdb b/NW4RTools/bin/Debug/NW4RTools.dll.mdb index f4fb376..9b65235 100644 Binary files a/NW4RTools/bin/Debug/NW4RTools.dll.mdb and b/NW4RTools/bin/Debug/NW4RTools.dll.mdb differ -- cgit v1.2.3