From 7d391e33a0b3d9793c95fce832abb2c6d9002186 Mon Sep 17 00:00:00 2001 From: Treeki Date: Tue, 8 Mar 2011 05:17:56 +0100 Subject: late night commit! obj importer is basic but working. also, tidied up DL stuff --- NW4RTools.userprefs | 15 +- NW4RTools/DisplayListWriter.cs | 83 ++++++++ NW4RTools/Enums.cs | 8 +- NW4RTools/Models/Material.cs | 2 +- NW4RTools/Models/OpenGL/GLModel.cs | 10 +- NW4RTools/NW4RTools.csproj | 1 + NW4RTools/NW4RTools.pidb | Bin 579951 -> 579951 bytes NW4RTools/ObjImporter.cs | 389 ++++++++++++++++------------------ NW4RTools/OutputStream.cs | 6 +- NW4RTools/bin/Debug/NW4RTools.dll | Bin 232960 -> 235008 bytes NW4RTools/bin/Debug/NW4RTools.dll.mdb | Bin 112922 -> 113704 bytes TestApp/Main.cs | 73 +++++-- TestApp/RenderWindow.cs | 20 +- TestApp/TestApp.pidb | Bin 4240 -> 4427 bytes TestApp/bin/Debug/NW4RTools.dll | Bin 232960 -> 233472 bytes TestApp/bin/Debug/NW4RTools.dll.mdb | Bin 112922 -> 112974 bytes TestApp/bin/Debug/TestApp.exe | Bin 5632 -> 7168 bytes TestApp/bin/Debug/TestApp.exe.mdb | Bin 979 -> 1243 bytes 18 files changed, 359 insertions(+), 248 deletions(-) create mode 100644 NW4RTools/DisplayListWriter.cs diff --git a/NW4RTools.userprefs b/NW4RTools.userprefs index d7da209..5273e53 100644 --- a/NW4RTools.userprefs +++ b/NW4RTools.userprefs @@ -2,21 +2,22 @@ - + - + - + - + - - - + + + + diff --git a/NW4RTools/DisplayListWriter.cs b/NW4RTools/DisplayListWriter.cs new file mode 100644 index 0000000..d75bc8d --- /dev/null +++ b/NW4RTools/DisplayListWriter.cs @@ -0,0 +1,83 @@ +using System; +namespace NW4RTools { + public class DisplayListWriter : OutputStream { + public DisplayListWriter() : base(ByteEndian.BigEndian) { + } + + + public void End() { + AlignTo(0x20); + } + + + public void Nop() { + WriteByte(0); + } + + public void LoadBPReg(UInt32 value) { + WriteByte((byte)GXCommand.LoadBPReg); + WriteUInt32(value); + } + + public void LoadCPReg(byte command, UInt32 value) { + WriteByte((byte)GXCommand.LoadCPReg); + WriteByte(command); + WriteUInt32(value); + } + + public void LoadXFReg(ushort address, byte[] data) { + if ((data.Length & 3) != 0) { + throw new ArgumentException("Data length passed to LoadXFReg() is not aligned to 4 bytes", "data"); + } + + if (data.Length < 4 || data.Length > 0x44) { + throw new ArgumentException("Data length passed to LoadXFReg() must be at least 4 bytes and at most 0x44 bytes", "data"); + } + + WriteByte((byte)GXCommand.LoadXFReg); + WriteByte(0); + WriteByte((byte)((data.Length / 4) - 1)); + WriteUInt16(address); + WriteBytes(data); + } + + public void LoadPosMtxFromArray(uint number) { + WriteByte((byte)GXCommand.LoadPosMtxFromArray); + WriteUInt32(number); + } + + public void LoadNrmMtxFromArray(uint number) { + WriteByte((byte)GXCommand.LoadNrmMtxFromArray); + WriteUInt32(number); + } + + public void LoadTexCoordMtxFromArray(uint number) { + WriteByte((byte)GXCommand.LoadTexCoordMtxFromArray); + WriteUInt32(number); + } + + public void LoadLightFromArray(uint number) { + WriteByte((byte)GXCommand.LoadLightFromArray); + WriteUInt32(number); + } + + public void CallDisplayList(uint pointer, uint size) { + WriteByte((byte)GXCommand.CallDL); + WriteUInt32(pointer); + WriteUInt32(size); + } + + public void UnknownMetrics() { + WriteByte((byte)GXCommand.UnknownMetrics); + } + + public void BeginPrimitives(PrimitiveType type, int vatIndex, ushort vtxCount) { + byte command = (byte)GXCommand.DrawPrimitiveMask; + command |= (byte)((byte)type << (byte)GXCommand.PrimitiveShiftAmount); + command |= (byte)vatIndex; + WriteByte(command); + WriteUInt16(vtxCount); + } + } +} + diff --git a/NW4RTools/Enums.cs b/NW4RTools/Enums.cs index 1ee089f..80c2283 100644 --- a/NW4RTools/Enums.cs +++ b/NW4RTools/Enums.cs @@ -13,11 +13,17 @@ namespace NW4RTools { public enum GXCommand { - // Missing many!! + Nop = 0, + LoadBPReg = 0x61, + LoadCPReg = 0x08, + LoadXFReg = 0x10, LoadPosMtxFromArray = 0x20, LoadNrmMtxFromArray = 0x28, LoadTexCoordMtxFromArray = 0x30, LoadLightFromArray = 0x38, + CallDL = 0x40, + UnknownMetrics = 0x44, + InvalidateVC = 0x48, DrawPrimitiveMask = 0x80, // TODO: Figure out some better way to store this PrimitiveShiftAmount = 3 diff --git a/NW4RTools/Models/Material.cs b/NW4RTools/Models/Material.cs index 519790c..a28240c 100644 --- a/NW4RTools/Models/Material.cs +++ b/NW4RTools/Models/Material.cs @@ -24,7 +24,7 @@ namespace NW4RTools.Models { ScaleY = 1.0f; CameraID = 0xFF; - LightID = 0xFf; + LightID = 0xFF; Flags = 1; TexMatrix.Identity(); diff --git a/NW4RTools/Models/OpenGL/GLModel.cs b/NW4RTools/Models/OpenGL/GLModel.cs index 072ea00..18e5f6f 100644 --- a/NW4RTools/Models/OpenGL/GLModel.cs +++ b/NW4RTools/Models/OpenGL/GLModel.cs @@ -199,14 +199,14 @@ namespace NW4RTools.Models.OpenGL { displayList.Begin(); if (m.TextureInfos.Count > 0) { - GL.Enable(EnableCap.Texture2D); - TextureInfo[] texInfoArray = new TextureInfo[8]; foreach (var texInfo in m.TextureInfos) { texInfoArray[texInfo.TexMapID] = texInfo; } + GL.Enable(EnableCap.Texture2D); + for (int i = 0; i < 8; i++) { GL.ActiveTexture(TextureUnits[i]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); @@ -215,6 +215,7 @@ namespace NW4RTools.Models.OpenGL { GL.BindTexture(TextureTarget.Texture2D, 0); } else { BindTextureInfo(texInfoArray[i]); + GL.Enable(EnableCap.Texture2D); } } @@ -302,8 +303,9 @@ namespace NW4RTools.Models.OpenGL { GL.MultiTexCoord2(TextureUnits[j], shape.TexCoordData[j].Data[vtxs[i].TexCoords[j]]); } } - - // TODO: normals + + if (vs.NormalDesc != VertexSettings.DescType.None) + GL.Normal3(shape.NrmData.Data[vtxs[i].Normal]); GL.Vertex3(shape.PosData.Data[vtxs[i].Position]); } diff --git a/NW4RTools/NW4RTools.csproj b/NW4RTools/NW4RTools.csproj index 07fec58..02239cf 100644 --- a/NW4RTools/NW4RTools.csproj +++ b/NW4RTools/NW4RTools.csproj @@ -77,6 +77,7 @@ + diff --git a/NW4RTools/NW4RTools.pidb b/NW4RTools/NW4RTools.pidb index 757d6c2..e7aef3c 100644 Binary files a/NW4RTools/NW4RTools.pidb and b/NW4RTools/NW4RTools.pidb differ diff --git a/NW4RTools/ObjImporter.cs b/NW4RTools/ObjImporter.cs index 41b9ea4..81fcf81 100755 --- a/NW4RTools/ObjImporter.cs +++ b/NW4RTools/ObjImporter.cs @@ -12,6 +12,8 @@ namespace NW4RTools { + private const bool Lightmaps = true; + string BasePath; ResFile CurrentFile; Models.Model CurrentModel; @@ -54,6 +56,27 @@ namespace NW4RTools { // Set current material (usemtl): // -- A different material will be assigned for the current shape. + if (Lightmaps) { + var lm01m = new Texture(); + + lm01m.Images = new System.Drawing.Bitmap[1]; + lm01m.Images[0] = new System.Drawing.Bitmap(Path.Combine(BasePath, "images/lm_01m.png")); + + lm01m.Format = TextureFormat.I8; + + var lm02m = new Texture(); + + lm02m.Images = new System.Drawing.Bitmap[1]; + lm02m.Images[0] = new System.Drawing.Bitmap(Path.Combine(BasePath, "images/lm_02m.png")); + + lm02m.Format = TextureFormat.I8; + + CurrentFile.GetTextureGroup().Add("lm_01m", lm01m); + CurrentFile.GetTextureGroup().Add("lm_02m", lm02m); + } + + + CurrentModel = new Model(); modelGroup.Add(modelName, CurrentModel); @@ -138,20 +161,22 @@ namespace NW4RTools { if (line.Length == 0 || line[0] == '#') continue; - var parsed = line.Split(' '); + var parsed = line.Split(new char[] { ' '}, StringSplitOptions.RemoveEmptyEntries); switch (parsed[0]) { case "mtllib": LoadMaterialLibrary(string.Join(" ", parsed, 1, parsed.Length - 1)); break; case "v": - Positions.Add(ParseFloatArray(parsed, 1)); + Positions.Add(ParseFloatArray(parsed, 1, 3)); break; case "vn": - Normals.Add(ParseFloatArray(parsed, 1)); + Normals.Add(ParseFloatArray(parsed, 1, 3)); break; case "vt": - TexCoords.Add(ParseFloatArray(parsed, 1)); + var vtEntry = ParseFloatArray(parsed, 1, 2); + vtEntry[1] = 1.0f - vtEntry[1]; + TexCoords.Add(vtEntry); break; case "f": AddFace(parsed); @@ -178,10 +203,14 @@ namespace NW4RTools { private float[] ParseFloatArray(string[] src, int index) { - var output = new float[src.Length - index]; + return ParseFloatArray(src, index, src.Length - index); + } - for (int i = index; i < src.Length; i++) { - output[i - index] = float.Parse(src[i]); + private float[] ParseFloatArray(string[] src, int index, int count) { + var output = new float[count]; + + for (int i = 0; i < count; i++) { + output[i] = float.Parse(src[i + index]); } return output; @@ -203,7 +232,7 @@ namespace NW4RTools { if (line.Length == 0 || line[0] == '#') continue; - var parsed = line.Split(' '); + var parsed = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); switch (parsed[0]) { case "newmtl": @@ -216,7 +245,7 @@ namespace NW4RTools { currentMaterial.TevStageCount = 2; currentMaterial.IndStageCount = 0; -// This might need changing + // This might need changing currentMaterial.CullMode = 2; currentMaterial.SRTSettings[0] = new SRTSettingInfo(); @@ -233,106 +262,68 @@ namespace NW4RTools { currentMaterial.ChanCtrls[1].MatColor.Rgba = 0x000000FF; currentMaterial.ChanCtrls[1].AmbColor.Rgba = 0x00000000; currentMaterial.ChanCtrls[1].FlagC = 0; - currentMaterial.ChanCtrls[1].FlagA = 0; + currentMaterial.ChanCtrls[1].FlagA = 0; + + currentMaterial.LightSetID = 1; -// Default display lists, taken from test_lift - // The current version of MonoDevelop likes to make an awful mess - // of the indentation. There's nothing I can do about it. :/ - currentMaterial.PixDL = new byte[] { - 0x61, 0xF3, 0x1E, 0xFF, 0x80, - 0x61, 0x40, 0x00, 0x00, 0x17, - 0x61, 0xFE, 0x00, 0xFF, 0xE3, - 0x61, 0x41, 0x00, 0x34, 0xA0, - 0x61, 0x42, 0x00, 0x00, 0x00, -/* Padding */ - 0, 0, 0, 0, 0, - 0, 0 - }; - - currentMaterial.TevColorDL = new byte[] { - 0x61, 0xE2, 0x00, 0x00, 0xFF, - 0x61, 0xE3, 0x0F, 0xF0, 0xFF, - 0x61, 0xE3, 0x0F, 0xF0, 0xFF, - 0x61, 0xE3, 0x0F, 0xF0, 0xFF, - 0x61, 0xE4, 0x00, 0x00, 0x00, - 0x61, 0xE5, 0x00, 0x00, 0x00, - 0x61, 0xE5, 0x00, 0x00, 0x00, - 0x61, 0xE5, 0x00, 0x00, 0x00, - 0x61, 0xE6, 0x00, 0x00, 0x00, - 0x61, 0xE7, 0x00, 0x00, 0x00, - 0x61, 0xE7, 0x00, 0x00, 0x00, - 0x61, 0xE7, 0x00, 0x00, 0x00, - /* Padding */ - 0, 0, 0, 0, - 0x61, 0xE0, 0x80, 0x00, 0x00, - 0x61, - 0xE1, 0x80, 0x00, 0x00, - 0x61, 0xE2, 0x80, 0x00, 0x00, - 0x61, - 0xE3, 0x80, 0x00, 0x00, - 0x61, 0xE4, 0x80, 0x00, 0x00, - 0x61, - 0xE5, 0x80, 0x00, 0x00, - 0x61, 0xE6, 0x80, 0x00, 0x00, - 0x61, - 0xE7, 0x80, 0x00, 0x00, -/* More padding */ - 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - - currentMaterial.IndMtxAndScaleDL = new byte[] { - 0x61, 0x25, 0x00, 0x00, 0x00, - 0x61, 0x26, 0x00, 0x00, 0x00, - /* Padding */ - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - currentMaterial.TexCoordGenDL = new byte[] { - 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x52, - 0x80, 0x10, - 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, -/* Padding? */ - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -CurrentModel.Materials.Add(parsed[1], currentMaterial); - - -Shader thisShader = CreateShader(); + // Default display lists, taken from test_lift + var pixDL = new DisplayListWriter(); + pixDL.LoadBPReg(0xF31EFF80); + pixDL.LoadBPReg(0x40000017); + pixDL.LoadBPReg(0xFE00FFE3); + pixDL.LoadBPReg(0x410034A0); + pixDL.LoadBPReg(0x42000000); + pixDL.End(); + + currentMaterial.PixDL = pixDL.GetBuffer(); + + var tevColorDL = new DisplayListWriter(); + tevColorDL.LoadBPReg(0xE20000FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE4000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE6000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.AddPadding(4); + tevColorDL.LoadBPReg(0xE0800000); + tevColorDL.LoadBPReg(0xE1800000); + tevColorDL.LoadBPReg(0xE2800000); + tevColorDL.LoadBPReg(0xE3800000); + tevColorDL.LoadBPReg(0xE4800000); + tevColorDL.LoadBPReg(0xE5800000); + tevColorDL.LoadBPReg(0xE6800000); + tevColorDL.LoadBPReg(0xE7800000); + tevColorDL.AddPadding(24); + tevColorDL.End(); + + currentMaterial.TevColorDL = tevColorDL.GetBuffer(); + + var indMtxAndScaleDL = new DisplayListWriter(); + indMtxAndScaleDL.LoadBPReg(0x25000000); + indMtxAndScaleDL.LoadBPReg(0x26000000); + indMtxAndScaleDL.AddPadding(54); + indMtxAndScaleDL.End(); + + currentMaterial.IndMtxAndScaleDL = indMtxAndScaleDL.GetBuffer(); + + var texCoordGenDL = new DisplayListWriter(); + texCoordGenDL.LoadXFReg(0x1040, new byte[] { 0x00, 0x00, 0x52, 0x80 }); + texCoordGenDL.LoadXFReg(0x1050, new byte[] { 0x00, 0x00, 0x00, 0x00 }); + texCoordGenDL.AddPadding(110); + texCoordGenDL.End(); + + currentMaterial.TexCoordGenDL = texCoordGenDL.GetBuffer(); + + CurrentModel.Materials.Add(parsed[1], currentMaterial); + + + Shader thisShader = CreateShader(); CurrentModel.Shaders.Add(parsed[1], thisShader); currentMaterial.ShaderRef = thisShader; @@ -340,7 +331,7 @@ Shader thisShader = CreateShader(); case "map_Kd": var rawTexName = string.Join(" ", parsed, 1, parsed.Length - 1); -// TODO: fix this to use the mtllib path + // TODO: fix this to use the mtllib path var texPath = Path.Combine(BasePath, rawTexName); var texName = Path.GetFileNameWithoutExtension(texPath); @@ -386,43 +377,39 @@ Shader thisShader = CreateShader(); shader.TevStageCount = 2; shader.Unk1 = 0x00FFFFFF; shader.Unk2 = 0xFFFFFFFF; - shader.DisplayList = new byte[] { - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xF6, 0x00, 0x00, 0x04, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xF7, 0x00, 0x00, 0x0E, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xF8, 0x00, 0x00, 0x00, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xF9, 0x00, 0x00, 0x0C, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xFA, 0x00, 0x00, 0x05, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xFB, 0x00, 0x00, 0x0D, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xFC, 0x00, 0x00, 0x0A, - 0x61, 0xFE, 0x00, 0x00, 0x0F, - 0x61, 0xFD, 0x00, 0x00, 0x0E, - 0x61, 0x27, 0xFF, 0xFF, 0xFF, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0x61, 0xFE, 0xFF, 0xFF, - 0xF0, - 0x61, 0xF6, 0xE3, 0x38, 0xC0, - 0x61, 0x28, 0x03, 0xF0, - 0x40, - 0x61, 0xC0, 0x08, 0xF8, 0xAF, - 0x61, 0xC2, 0x08, 0xF2, - 0x0F, - 0x61, 0xC1, 0x08, 0xF2, 0xF0, - 0x61, 0xC3, 0x08, 0x1F, - 0xF0, -0x61, 0x10, 0x00, 0x00, 0x00, -0x61, 0x11, 0x00, 0x00, - 0x00 -}; - - Array.Resize(ref shader.DisplayList, 0x1E0); + + var dl = new DisplayListWriter(); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xF6000004); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xF700000E); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xF8000000); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xF900000C); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xFA000005); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xFB00000D); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xFC00000A); + dl.LoadBPReg(0xFE00000F); + dl.LoadBPReg(0xFD00000E); + dl.LoadBPReg(0x27FFFFFF); + dl.AddPadding(11); + dl.LoadBPReg(0xFEFFFFF0); + dl.LoadBPReg(0xF6E338C0); + dl.LoadBPReg(0x2803F040); + dl.LoadBPReg(0xC008F8AF); + dl.LoadBPReg(0xC208F20F); + dl.LoadBPReg(0xC108F2F0); + dl.LoadBPReg(0xC3081FF0); + dl.LoadBPReg(0x10000000); + dl.LoadBPReg(0x11000000); + dl.PadToSize(0x1E0); + dl.End(); + + shader.DisplayList = dl.GetBuffer(); return shader; } @@ -555,53 +542,31 @@ Shader thisShader = CreateShader(); vs.GetDesc(out vd1, out vd2); vs.GetAttrFmt(out vat1, out vat2, out vat3); - - // Todo: a Display List generator class - - CurrentShape.DLBufferSize1 = 0xE0; - CurrentShape.DisplayList1 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x08, 0x50, - (byte)((vd1 & 0xFF000000) >> 24), - (byte)((vd1 & 0x00FF0000) >> 16), - (byte)((vd1 & 0x0000FF00) >> 8), - (byte)((vd1 & 0x000000FF)), - 0x08, 0x60, - (byte)((vd2 & 0xFF000000) >> 24), - (byte)((vd2 & 0x00FF0000) >> 16), - (byte)((vd2 & 0x0000FF00) >> 8), - (byte)((vd2 & 0x000000FF)), - 0x10, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, - 0x14, 0, - 0x08, 0x70, - (byte)((vat1 & 0xFF000000) >> 24), - (byte)((vat1 & 0x00FF0000) >> 16), - (byte)((vat1 & 0x0000FF00) >> 8), - (byte)((vat1 & 0x000000FF)), - 0x08, 0x80, - (byte)((vat2 & 0xFF000000) >> 24), - (byte)((vat2 & 0x00FF0000) >> 16), - (byte)((vat2 & 0x0000FF00) >> 8), - (byte)((vat2 & 0x000000FF)), - 0x08, 0x90, - (byte)((vat3 & 0xFF000000) >> 24), - (byte)((vat3 & 0x00FF0000) >> 16), - (byte)((vat3 & 0x0000FF00) >> 8), - (byte)((vat3 & 0x000000FF)) - }; - - // I might need to create XFMEM_VTXSPECS... // test_lift uses 0x14. According to Dolphin's src, this means: // numcolors = 0, numnormals = 1 (just normal), numtextures = 1. Makes sense. byte vtxSpecs = 0 | (1 << 2) | (1 << 4); - CurrentShape.DisplayList1[0x1E] = vtxSpecs; + + var dl1 = new DisplayListWriter(); + dl1.AddPadding(10); + dl1.LoadCPReg(0x50, vd1); + dl1.LoadCPReg(0x60, vd2); + dl1.LoadXFReg(0x1008, new byte[] { 0x00, 0x00, 0x00, vtxSpecs }); + dl1.Nop(); + dl1.LoadCPReg(0x70, vat1); + dl1.LoadCPReg(0x80, vat2); + dl1.LoadCPReg(0x90, vat3); // extend it // should it be bigger if more texcoords are used? maybe... - Array.Resize(ref CurrentShape.DisplayList1, 0x80); + dl1.PadToSize(0x80); + dl1.End(); + + CurrentShape.DLBufferSize1 = 0xE0; + CurrentShape.DisplayList1 = dl1.GetBuffer(); -// Display List 2 is where all the primitive-related fun happens + // Display List 2 is where all the primitive-related fun happens // However, before we do that, let's compute the vertex data arrays ushort[] posIndexes, texCoordIndexes, normalIndexes; @@ -619,7 +584,7 @@ Shader thisShader = CreateShader(); posData.Data = posDataArray; posData.Save(); - CurrentModel.VtxPosData.Add("Pos" + CurrentModel.VtxPosData.Count.ToString(), posData); + CurrentModel.VtxPosData.Add("P_" + CurrentModel.VtxPosData.Count.ToString(), posData); var tcData = new VertexTexCoordData(); tcData.ComponentCount = VertexSettings.CompCount.TexCoord2; @@ -630,9 +595,7 @@ Shader thisShader = CreateShader(); tcData.Data = tcDataArray; tcData.Save(); - CurrentModel.VtxTexCoordData.Add("TexCoord" + CurrentModel.VtxTexCoordData.Count.ToString(), tcData); - - // TODO: Flip texcoords + CurrentModel.VtxTexCoordData.Add("T_" + CurrentModel.VtxTexCoordData.Count.ToString(), tcData); var nrmData = new VertexNrmData(); nrmData.ComponentCount = VertexSettings.CompCount.Normal3; @@ -643,52 +606,54 @@ Shader thisShader = CreateShader(); nrmData.Data = nrmDataArray; nrmData.Save(); - CurrentModel.VtxNrmData.Add("Nrm" + CurrentModel.VtxNrmData.Count.ToString(), nrmData); + CurrentModel.VtxNrmData.Add("N_" + CurrentModel.VtxNrmData.Count.ToString(), nrmData); CurrentShape.PosData = posData; CurrentShape.TexCoordData[0] = tcData; CurrentShape.NrmData = nrmData; - var dl = new OutputStream(); - + var dl = new DisplayListWriter(); + + // face writing here is reversed because the wind order seems to be wrong + // dunno if it applies to models exported from everything, or just Maya + // or maybe it's a setting specified in one of the structs + if (Triangles.Count > 0) { - dl.WriteByte((byte)GXCommand.DrawPrimitiveMask | ((byte)PrimitiveType.Triangles << (byte)GXCommand.PrimitiveShiftAmount)); - dl.WriteUInt16((ushort)(Triangles.Count * 3)); - + dl.BeginPrimitives(PrimitiveType.Triangles, 0, (ushort)(Triangles.Count * 3)); + foreach (var tri in Triangles) { - dl.WriteUInt16(posIndexes[tri[0]]); - dl.WriteUInt16(normalIndexes[tri[1]]); - dl.WriteUInt16(texCoordIndexes[tri[2]]); - dl.WriteUInt16(posIndexes[tri[3]]); - dl.WriteUInt16(normalIndexes[tri[4]]); - dl.WriteUInt16(texCoordIndexes[tri[5]]); dl.WriteUInt16(posIndexes[tri[6]]); dl.WriteUInt16(normalIndexes[tri[7]]); dl.WriteUInt16(texCoordIndexes[tri[8]]); + dl.WriteUInt16(posIndexes[tri[3]]); + dl.WriteUInt16(normalIndexes[tri[4]]); + dl.WriteUInt16(texCoordIndexes[tri[5]]); + dl.WriteUInt16(posIndexes[tri[0]]); + dl.WriteUInt16(normalIndexes[tri[1]]); + dl.WriteUInt16(texCoordIndexes[tri[2]]); } } if (Quads.Count > 0) { - dl.WriteByte((byte)GXCommand.DrawPrimitiveMask | ((byte)PrimitiveType.Quads << (byte)GXCommand.PrimitiveShiftAmount)); - dl.WriteUInt16((ushort)(Quads.Count * 3)); + dl.BeginPrimitives(PrimitiveType.Quads, 0, (ushort)(Quads.Count * 4)); foreach (var quad in Quads) { - dl.WriteUInt16(posIndexes[quad[0]]); - dl.WriteUInt16(normalIndexes[quad[1]]); - dl.WriteUInt16(texCoordIndexes[quad[2]]); - dl.WriteUInt16(posIndexes[quad[3]]); - dl.WriteUInt16(normalIndexes[quad[4]]); - dl.WriteUInt16(texCoordIndexes[quad[5]]); - dl.WriteUInt16(posIndexes[quad[6]]); - dl.WriteUInt16(normalIndexes[quad[7]]); - dl.WriteUInt16(texCoordIndexes[quad[8]]); dl.WriteUInt16(posIndexes[quad[9]]); dl.WriteUInt16(normalIndexes[quad[10]]); dl.WriteUInt16(texCoordIndexes[quad[11]]); + dl.WriteUInt16(posIndexes[quad[6]]); + dl.WriteUInt16(normalIndexes[quad[7]]); + dl.WriteUInt16(texCoordIndexes[quad[8]]); + dl.WriteUInt16(posIndexes[quad[3]]); + dl.WriteUInt16(normalIndexes[quad[4]]); + dl.WriteUInt16(texCoordIndexes[quad[5]]); + dl.WriteUInt16(posIndexes[quad[0]]); + dl.WriteUInt16(normalIndexes[quad[1]]); + dl.WriteUInt16(texCoordIndexes[quad[2]]); } } - dl.AlignTo(0x20); + dl.End(); CurrentShape.DisplayList2 = dl.GetBuffer(); CurrentShape.DLBufferSize2 = (uint)CurrentShape.DisplayList2.Length; diff --git a/NW4RTools/OutputStream.cs b/NW4RTools/OutputStream.cs index e934158..2243d90 100644 --- a/NW4RTools/OutputStream.cs +++ b/NW4RTools/OutputStream.cs @@ -49,7 +49,7 @@ namespace NW4RTools { } public void AddPadding(int count) { - if (count == 0) + if (count <= 0) return; else if (count == 1) WriteByte(0); @@ -58,6 +58,10 @@ namespace NW4RTools { WriteByte(0); } + public void PadToSize(int size) { + AddPadding(size - Position); + } + public void WriteBytes(byte[] data) { BaseStream.Write(data, 0, data.Length); } diff --git a/NW4RTools/bin/Debug/NW4RTools.dll b/NW4RTools/bin/Debug/NW4RTools.dll index e4c2ea1..497cebb 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 62014b8..e36c23e 100644 Binary files a/NW4RTools/bin/Debug/NW4RTools.dll.mdb and b/NW4RTools/bin/Debug/NW4RTools.dll.mdb differ diff --git a/TestApp/Main.cs b/TestApp/Main.cs index a5db889..fbaa7dc 100644 --- a/TestApp/Main.cs +++ b/TestApp/Main.cs @@ -11,39 +11,30 @@ namespace TestApp { public static void Main(string[] args) { string mdlPath = "/home/me/Games/Newer/ModelRev/"; - /*//string mdlName = "CS_W1"; - //string mdlName = "bgB_4502"; - //string mdlName = "cobKoopaCastle"; - string mdlName = "waterPlate_W4boss"; - mdlName = "test_lift"; + //skawo(); + //oldBehaviour(); + //return; - string whatever = (mdlName == "CS_W2" || mdlName == "CS_W3" || mdlName == "CS_W6") ? "a" : ""; - byte[] file = File.ReadAllBytes(mdlPath + mdlName + ".brres"); - ResFile rf = BrresReader.LoadFile(file); + // Going to create a model! + //string filename = "crapmap", resmdlname = "CrapMap"; + string filename = "GoldwoodBase", resmdlname = "GoldwoodBase"; - File.WriteAllBytes(mdlPath + mdlName + "_rewritten.brres", BrresWriter.WriteFile(rf));*/ - // Going to create a model! ResFile rf = new ResFile(); - ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + "crapmap.obj"), rf, "CrapMap"); + ObjImporter.ImportModel(mdlPath, File.OpenText(mdlPath + filename + ".obj"), rf, resmdlname); - File.WriteAllBytes(mdlPath + "crapmap.brres", BrresWriter.WriteFile(rf)); + File.WriteAllBytes(mdlPath + filename + ".brres", BrresWriter.WriteFile(rf)); - ResFile rf2 = BrresReader.LoadFile(File.ReadAllBytes(mdlPath + "crapmap.brres")); + ResFile rf2 = BrresReader.LoadFile(File.ReadAllBytes(mdlPath + filename + ".brres")); using (var gw = new RenderWindow()) { - gw.Title = "crapmap"; - gw.SetModel(rf2, "CrapMap"); + gw.Title = filename; + gw.SetModel(rf2, resmdlname); gw.Run(1, 1); } - /*using (var gw = new RenderWindow()) { - gw.Title = mdlName; - gw.SetModel(rf, mdlName); - gw.Run(1, 1); - }*/ @@ -60,6 +51,48 @@ namespace TestApp { ColladaWriter.WriteModel(objFile, rf, mdlName + whatever); objFile.Close();*/ } + + + private static void skawo() { + string mdlPath = "/home/me/Games/Newer/ModelRev/"; + string skawopath = "/home/me/Dropbox/NEWERsmbw/Nowy folder/obj/"; + ResFile rf = new ResFile(); + + ObjImporter.ImportModel(skawopath, File.OpenText(skawopath + "edited.obj"), rf, "Skawo"); + + File.WriteAllBytes(skawopath + "skawo.brres", BrresWriter.WriteFile(rf)); + + + ResFile rf2 = BrresReader.LoadFile(File.ReadAllBytes(skawopath + "skawo.brres")); + using (var gw = new RenderWindow()) { + gw.Title = "Skawo"; + gw.SetModel(rf2, "Skawo"); + gw.Run(1, 1); + } + } + + private static void oldBehaviour() { + string mdlPath = "/home/me/Games/Newer/ModelRev/"; + string mdlName = "CS_W1"; + //string mdlName = "bgB_4502"; + //string mdlName = "cobKoopaCastle"; + //string mdlName = "waterPlate_W4boss"; + //mdlName = "test_lift"; + + string whatever = (mdlName == "CS_W2" || mdlName == "CS_W3" || mdlName == "CS_W6") ? "a" : ""; + + byte[] file = File.ReadAllBytes(mdlPath + mdlName + ".brres"); + ResFile rf = BrresReader.LoadFile(file); + + using (var gw = new RenderWindow()) { + gw.Title = mdlName; + gw.SetModel(rf, mdlName); + gw.Run(1, 1); + } + + //File.WriteAllBytes(mdlPath + mdlName + "_rewritten.brres", BrresWriter.WriteFile(rf)); + + } } } diff --git a/TestApp/RenderWindow.cs b/TestApp/RenderWindow.cs index 2f29d0f..6013724 100644 --- a/TestApp/RenderWindow.cs +++ b/TestApp/RenderWindow.cs @@ -27,6 +27,22 @@ namespace TestApp { GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); + GL.Disable(EnableCap.CullFace); + + GL.Enable(EnableCap.Lighting); + + GL.ShadeModel(ShadingModel.Smooth); + + GL.Light(LightName.Light0, LightParameter.Position, new Vector4(0, 500, 1000, 0)); + GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, new Color4(1, 1, 1, 1)); + GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, 50); + GL.Enable(EnableCap.Light0); + + GL.Light(LightName.Light1, LightParameter.Position, new Vector4(1000, 500, 0, 0)); + GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, new Color4(1, 1, 1, 1)); + GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, 50); + GL.Enable(EnableCap.Light1); + m_glModel.Prepare(Context); } @@ -45,8 +61,8 @@ namespace TestApp { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - //Matrix4 modelview = Matrix4.LookAt(new Vector3(1000, 600, 1000), new Vector3(1000, 0, 0), Vector3.UnitY); - Matrix4 modelview = Matrix4.LookAt(new Vector3(0, 2, 4), new Vector3(0, 0, 0), Vector3.UnitY); + Matrix4 modelview = Matrix4.LookAt(new Vector3(1000, 400, 1000), new Vector3(1000, 0, 0), Vector3.UnitY); + //Matrix4 modelview = Matrix4.LookAt(new Vector3(-3, 2, 3), new Vector3(0, 0, 0), Vector3.UnitY); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref modelview); diff --git a/TestApp/TestApp.pidb b/TestApp/TestApp.pidb index bbc694a..e8df7af 100644 Binary files a/TestApp/TestApp.pidb and b/TestApp/TestApp.pidb differ diff --git a/TestApp/bin/Debug/NW4RTools.dll b/TestApp/bin/Debug/NW4RTools.dll index e4c2ea1..40356de 100755 Binary files a/TestApp/bin/Debug/NW4RTools.dll and b/TestApp/bin/Debug/NW4RTools.dll differ diff --git a/TestApp/bin/Debug/NW4RTools.dll.mdb b/TestApp/bin/Debug/NW4RTools.dll.mdb index 62014b8..92742d0 100644 Binary files a/TestApp/bin/Debug/NW4RTools.dll.mdb and b/TestApp/bin/Debug/NW4RTools.dll.mdb differ diff --git a/TestApp/bin/Debug/TestApp.exe b/TestApp/bin/Debug/TestApp.exe index a5251b0..5b808e0 100755 Binary files a/TestApp/bin/Debug/TestApp.exe and b/TestApp/bin/Debug/TestApp.exe differ diff --git a/TestApp/bin/Debug/TestApp.exe.mdb b/TestApp/bin/Debug/TestApp.exe.mdb index 7508ce0..8ec2779 100644 Binary files a/TestApp/bin/Debug/TestApp.exe.mdb and b/TestApp/bin/Debug/TestApp.exe.mdb differ -- cgit v1.2.3