diff options
Diffstat (limited to '')
-rwxr-xr-x | NW4RTools/ObjImporter.cs | 389 |
1 files changed, 177 insertions, 212 deletions
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<byte>(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<byte>(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; |