diff options
30 files changed, 640 insertions, 29 deletions
diff --git a/NW4RTools.userprefs b/NW4RTools.userprefs index 843535e..b0eba72 100644 --- a/NW4RTools.userprefs +++ b/NW4RTools.userprefs @@ -1,14 +1,14 @@ <Properties> <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" /> - <MonoDevelop.Ide.Workbench ActiveDocument="TestApp/Main.cs"> + <MonoDevelop.Ide.Workbench ActiveDocument="NW4RTools/ColladaWriter.cs"> <Files> <File FileName="TestApp/Main.cs" Line="11" Column="27" /> <File FileName="NW4RTools/BrresReader.cs" Line="266" Column="1" /> <File FileName="NW4RTools/Enums.cs" Line="13" Column="1" /> <File FileName="NW4RTools/Models/Node.cs" Line="27" Column="1" /> <File FileName="NW4RTools/Models/Material.cs" Line="1" Column="1" /> - <File FileName="NW4RTools/ColladaWriter.cs" Line="376" Column="37" /> - <File FileName="NW4RTools/Texture.cs" Line="263" Column="102" /> + <File FileName="NW4RTools/ColladaWriter.cs" Line="144" Column="34" /> + <File FileName="NW4RTools/Texture.cs" Line="263" Column="8" /> </Files> </MonoDevelop.Ide.Workbench> <MonoDevelop.Ide.DebuggingService.Breakpoints> diff --git a/NW4RTools/BrresReader.cs b/NW4RTools/BrresReader.cs index 71dacc3..8b48ef3 100644 --- a/NW4RTools/BrresReader.cs +++ b/NW4RTools/BrresReader.cs @@ -427,14 +427,23 @@ namespace NW4RTools { n.ComponentCount = (VertexSettings.CompCount)ins.ReadUInt32(); n.ComponentType = (VertexSettings.CompType)ins.ReadUInt32(); - n.Fraction = ins.ReadByte(); - n.EntrySize = ins.ReadByte(); + + // ridiculous and hacky. thanks for requiring this, Nintendo + if (n is VertexClrData) { + n.EntrySize = ins.ReadByte(); + ins.Skip(1); + } else { + 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); + n.RawData = ins.ReadBytes(n.EntrySize * n.EntryCount); + n.Parse(); ins.Seek(structEndPos); } @@ -805,8 +814,8 @@ namespace NW4RTools { bTex.TexMapID = ins.ReadUInt32(); bTex.TlutID = ins.ReadUInt32(); - bTex.WrapS = ins.ReadUInt32(); - bTex.WrapT = ins.ReadUInt32(); + bTex.WrapS = (TextureWrapType)ins.ReadUInt32(); + bTex.WrapT = (TextureWrapType)ins.ReadUInt32(); bTex.MinFilt = ins.ReadUInt32(); bTex.MagFilt = ins.ReadUInt32(); bTex.LODBias = ins.ReadFloat(); diff --git a/NW4RTools/ColladaWriter.cs b/NW4RTools/ColladaWriter.cs index f0f5b19..2c57d7e 100644 --- a/NW4RTools/ColladaWriter.cs +++ b/NW4RTools/ColladaWriter.cs @@ -37,8 +37,8 @@ namespace NW4RTools { Collada.asset.contributor[0] = new assetContributor(); Collada.asset.contributor[0].authoring_tool = "NW4RTools Collada exporter by Treeki"; Collada.asset.contributor[0].source_data = "NW4R model: " + modelName; - Collada.asset.created = DateTime.Now; - Collada.asset.modified = DateTime.Now; + //Collada.asset.created = DateTime.Now; + //Collada.asset.modified = DateTime.Now; Collada.asset.unit = new assetUnit(); Collada.asset.unit.meter = 1.0; Collada.asset.up_axis = UpAxisType.Y_UP; @@ -344,16 +344,17 @@ namespace NW4RTools { eff.id = "Material-Effect-" + name; eff.name = eff.id; + + // HACK!! + if (mat.TextureInfos.Count == 0) + return eff; + // this is based off what colladamax outputs eff.Items = new effectFx_profile_abstractProfile_COMMON[1]; var profile = eff.Items[0] = new effectFx_profile_abstractProfile_COMMON(); // TODO: handle this correctly for multiple textures ETC and check how bb does it - // HACK!! - if (mat.TextureInfos.Count == 0) - return eff; - profile.Items = new object[2]; // create a surface newparam @@ -374,7 +375,10 @@ namespace NW4RTools { var samplerParam = new common_newparam_type(); var sampler2d = new fx_sampler2D_common(); + // add wrapping sampler2d.source = "Surface-" + mat.TextureInfos[0].TextureName; + sampler2d.wrap_s = mat.TextureInfos[0].WrapS.ToColladaSamplerWrap(); + sampler2d.wrap_t = mat.TextureInfos[0].WrapT.ToColladaSamplerWrap(); samplerParam.sid = "Sampler-" + mat.TextureInfos[0].TextureName; samplerParam.ItemElementName = ItemChoiceType.sampler2D; @@ -395,6 +399,28 @@ namespace NW4RTools { pShader.diffuse.Item = diffuseTex; + pShader.emission = new common_color_or_texture_type(); + var emissionClr = new common_color_or_texture_typeColor(); + emissionClr.Values = new double[] { 0, 0, 0, 1 }; + pShader.emission.Item = emissionClr; + + pShader.ambient = new common_color_or_texture_type(); + var ambientClr = new common_color_or_texture_typeColor(); + ambientClr.Values = new double[] { 0, 0, 0, 1 }; + pShader.ambient.Item = ambientClr; + + pShader.transparent = new common_transparent_type(); + pShader.transparent.opaque = fx_opaque_enum.A_ONE; + var transparentClr = new common_color_or_texture_typeColor(); + transparentClr.Values = new double[] { 1, 1, 1, 1 }; + pShader.transparent.Item = transparentClr; + pShader.transparency = new common_float_or_param_type(); + var bs = new common_float_or_param_typeFloat(); + bs.Value = 1; + pShader.transparency.Item = bs; + // we can reuse DiffuseTex! + pShader.transparent.Item = diffuseTex; + profile.technique.Item = pShader; return eff; @@ -537,7 +563,11 @@ namespace NW4RTools { for (int i = 0; i < tcData.EntryCount; i++) { float[] data = tcData.GetEntry(i); for (int j = 0; j < data.Length; j++) { - tcArray.Values[dest++] = data[j]; + // flip T (Y axis) coordinate + if (j == 1) + tcArray.Values[dest++] = 1.0 - data[j]; + else + tcArray.Values[dest++] = data[j]; } } diff --git a/NW4RTools/Enums.cs b/NW4RTools/Enums.cs index 0b3518b..a81da6c 100644 --- a/NW4RTools/Enums.cs +++ b/NW4RTools/Enums.cs @@ -25,4 +25,26 @@ namespace NW4RTools { C14X2 = 0xA, CMPR = 0xE } + + + public enum TextureWrapType { + CLAMP, + REPEAT, + MIRROR + } + + public static class TextureWrapTypeExtensionMethods { + public static Collada141.fx_sampler_wrap_common ToColladaSamplerWrap(this TextureWrapType t) { + if (t == TextureWrapType.CLAMP) + return Collada141.fx_sampler_wrap_common.CLAMP; + + if (t == TextureWrapType.REPEAT) + return Collada141.fx_sampler_wrap_common.WRAP; + + if (t == TextureWrapType.MIRROR) + return Collada141.fx_sampler_wrap_common.MIRROR; + + return Collada141.fx_sampler_wrap_common.WRAP; + } + } } diff --git a/NW4RTools/Models/OpenGL/GLDisplayList.cs b/NW4RTools/Models/OpenGL/GLDisplayList.cs new file mode 100644 index 0000000..180e89e --- /dev/null +++ b/NW4RTools/Models/OpenGL/GLDisplayList.cs @@ -0,0 +1,31 @@ +using System; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace NW4RTools.Models.OpenGL { + public class GLDisplayList : IDisposable { + public readonly int ListID; + + public GLDisplayList() { + ListID = GL.GenLists(1); + } + + void IDisposable.Dispose() { + GL.DeleteLists(ListID, 1); + } + + public void Begin() { + GL.NewList(ListID, ListMode.Compile); + } + + public void End() { + GL.EndList(); + } + + public void Execute() { + GL.CallList(ListID); + } + } +} + diff --git a/NW4RTools/Models/OpenGL/GLModel.cs b/NW4RTools/Models/OpenGL/GLModel.cs new file mode 100644 index 0000000..2e5779e --- /dev/null +++ b/NW4RTools/Models/OpenGL/GLModel.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using NW4RTools; +using NW4RTools.Models; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace NW4RTools.Models.OpenGL { + public class GLModel { + public ResFile SourceFile { + get; private set; + } + + public Model SourceModel { + get; private set; + } + + public GLModel(ResFile rf, string modelName) { + SourceFile = rf; + SourceModel = rf.GetGroup<Model>("3DModels(NW4R)")[modelName]; + + // cache some stuff + m_textureGroup = rf.GetGroup<Texture>("Textures(NW4R)"); + } + + + + + private ResDict<Texture> m_textureGroup; + private Dictionary<string, GLTexture> m_glTextures; + private Dictionary<Material, GLDisplayList> m_glMaterials; + private Dictionary<Shape, GLDisplayList> m_glShapes; + + public void Prepare(IGraphicsContext context) { + // convert every texture + m_glTextures = new Dictionary<string, GLTexture>(); + + foreach (var material in SourceModel.Materials) { + foreach (var texInfo in material.Value.TextureInfos) { + if (!m_glTextures.ContainsKey(texInfo.TextureName)) { + var newTex = new GLTexture(); + newTex.Load(m_textureGroup[texInfo.TextureName]); + m_glTextures.Add(texInfo.TextureName, newTex); + } + } + } + + // convert every material + m_glMaterials = new Dictionary<Material, GLDisplayList>(); + + foreach (var material in SourceModel.Materials.Values) { + m_glMaterials.Add(material, MakeMaterialDisplayList(material)); + } + + // convert every shape + m_glShapes = new Dictionary<Shape, GLDisplayList>(); + + foreach (var shape in SourceModel.Shapes.Values) { + m_glShapes.Add(shape, MakeShapeDisplayList(shape)); + } + } + + + + private static readonly TextureUnit[] TextureUnits = new TextureUnit[] { + TextureUnit.Texture0, TextureUnit.Texture1, TextureUnit.Texture2, TextureUnit.Texture3, + TextureUnit.Texture4, TextureUnit.Texture5, TextureUnit.Texture6, TextureUnit.Texture7, + TextureUnit.Texture8, TextureUnit.Texture9, TextureUnit.Texture10, TextureUnit.Texture11, + TextureUnit.Texture12, TextureUnit.Texture13, TextureUnit.Texture14, TextureUnit.Texture15 + }; + + private Material m_currentMaterial; + + private void ClearCache() { + m_currentMaterial = null; + } + + private void LoadMaterial(Material m) { + if (m == m_currentMaterial) + return; + + m_currentMaterial = m; + m_glMaterials[m].Execute(); + } + + private void DrawShape(ByteCode.DrawShapeInstruction insn) { + LoadMaterial(SourceModel.Materials[insn.MaterialID]); + + var shape = SourceModel.Shapes[insn.ShapeID]; + m_glShapes[shape].Execute(); + } + + public void Render(IGraphicsContext context) { + // This'll be fun. + + ClearCache(); + + foreach (var insn in SourceModel.Bytecode["DrawOpa"].Instructions) { + if (insn is ByteCode.DrawShapeInstruction) { + DrawShape(insn as ByteCode.DrawShapeInstruction); + } + } + + if (SourceModel.Bytecode.ContainsKey("DrawXlu")) { + foreach (var insn in SourceModel.Bytecode["DrawXlu"].Instructions) { + if (insn is ByteCode.DrawShapeInstruction) { + DrawShape(insn as ByteCode.DrawShapeInstruction); + } + } + } + } + + + + #region Display Lists + private GLDisplayList MakeMaterialDisplayList(Material m) { + var displayList = new GLDisplayList(); + 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; + } + + for (int i = 0; i < 8; i++) { + GL.ActiveTexture(TextureUnits[i]); + GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Decal); + + if (texInfoArray[i] == null) { + GL.BindTexture(TextureTarget.Texture2D, 0); + } else { + m_glTextures[texInfoArray[i].TextureName].Bind(TextureTarget.Texture2D); + } + } + + } else { + GL.Disable(EnableCap.Texture2D); + } + + displayList.End(); + return displayList; + } + + private GLDisplayList MakeShapeDisplayList(Shape shape) { + var displayList = new GLDisplayList(); + displayList.Begin(); + + 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); + + + InputStream dl = new InputStream(shape.DisplayList2); + + while (true) { + if (dl.AtEnd) + break; + + byte cmd = dl.ReadByte(); + if (cmd == 0) + break; + + PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7); + int vtxCount = dl.ReadUInt16(); + + // first, parse it into a list of vertices + GXIndexedVertex[] vtxs = new GXIndexedVertex[vtxCount]; + for (int i = 0; i < vtxCount; i++) { + vtxs[i].LoadFrom(dl, vs); + } + + switch (prim) { + case PrimitiveType.Quads: + GL.Begin(BeginMode.Quads); + break; + case PrimitiveType.Triangles: + GL.Begin(BeginMode.Triangles); + break; + case PrimitiveType.TriangleStrip: + GL.Begin(BeginMode.TriangleStrip); + break; + case PrimitiveType.TriangleFan: + GL.Begin(BeginMode.TriangleFan); + break; + case PrimitiveType.Lines: + GL.Begin(BeginMode.Lines); + break; + case PrimitiveType.LineStrip: + GL.Begin(BeginMode.LineStrip); + break; + case PrimitiveType.Points: + GL.Begin(BeginMode.Points); + break; + default: + Console.WriteLine("UNIMPLEMENTED PRIMITIVE TYPE {0}", prim); + throw new NotImplementedException(); + } + + for (int i = 0; i < vtxCount; i++) { + for (int j = 0; j < 8; j++) { + if (vs.TexCoordDesc[j] != VertexSettings.DescType.None) + GL.MultiTexCoord2(TextureUnits[j], shape.TexCoordData[j].Data[vtxs[i].TexCoords[j]]); + } + + GL.Vertex3(shape.PosData.Data[vtxs[i].Position]); + } + + GL.End(); + } + + displayList.End(); + return displayList; + } + + #endregion + } +} + diff --git a/NW4RTools/Models/OpenGL/GLTexture.cs b/NW4RTools/Models/OpenGL/GLTexture.cs new file mode 100644 index 0000000..c4cdee6 --- /dev/null +++ b/NW4RTools/Models/OpenGL/GLTexture.cs @@ -0,0 +1,46 @@ +using System; +using NW4RTools; +using NW4RTools.Models; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace NW4RTools.Models.OpenGL { + public class GLTexture : IDisposable { + public readonly int TextureID; + + public GLTexture() { + TextureID = GL.GenTexture(); + } + + void IDisposable.Dispose() { + GL.DeleteTexture(TextureID); + } + + public void Load(Texture tex) { + Bind(TextureTarget.Texture2D); + + // todo: check if this is configurable + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMagFilter.Linear); + + //byte[] pixelData = new byte[tex.BaseImage.Width * tex.BaseImage.Height * 4]; + + var lb = tex.BaseImage.LockBits( + new System.Drawing.Rectangle(0, 0, tex.BaseImage.Width, tex.BaseImage.Height), + System.Drawing.Imaging.ImageLockMode.ReadOnly, + System.Drawing.Imaging.PixelFormat.Format32bppArgb); + + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Four, + tex.BaseImage.Width, tex.BaseImage.Height, 0, + PixelFormat.Bgra, PixelType.UnsignedByte, lb.Scan0); + + tex.BaseImage.UnlockBits(lb); + } + + public void Bind(TextureTarget target) { + GL.BindTexture(target, TextureID); + } + } +} + diff --git a/NW4RTools/Models/TextureInfo.cs b/NW4RTools/Models/TextureInfo.cs index c8bc9a4..57a7169 100644 --- a/NW4RTools/Models/TextureInfo.cs +++ b/NW4RTools/Models/TextureInfo.cs @@ -3,7 +3,8 @@ using System; namespace NW4RTools.Models { public class TextureInfo { public string TextureName, PaletteName; - public UInt32 TexMapID, TlutID, WrapS, WrapT, MinFilt, MagFilt; + public UInt32 TexMapID, TlutID, MinFilt, MagFilt; + public TextureWrapType WrapS, WrapT; public float LODBias; public UInt32 MaxAniso; public bool BiasClamp, DoEdgeLOD; diff --git a/NW4RTools/Models/VertexData.cs b/NW4RTools/Models/VertexData.cs index 5b1a50a..187b9aa 100644 --- a/NW4RTools/Models/VertexData.cs +++ b/NW4RTools/Models/VertexData.cs @@ -10,23 +10,24 @@ namespace NW4RTools.Models { public UInt16 EntryCount; // Todo, decode data when reading - public byte[] Data; + public byte[] RawData; + public float[][] Data; public VertexDataBase() { } - public float[] GetEntry(int index) { + public virtual float[] GetEntry(int index) { float[] ret = new float[GetRealCount()]; float scale = 1.0f / (1 << Fraction); - //Console.WriteLine("Getting index {0}, count {1} size {2} length {3} offset {4}", index, EntryCount, EntrySize, Data.Length, index * EntrySize); - InputStream ins = new InputStream(Data); + InputStream ins = new InputStream(RawData); ins.Seek(index * EntrySize); for (int i = 0; i < ret.Length; i++) { switch (ComponentType) { case VertexSettings.CompType.UInt8: + ret[i] = (float)ins.ReadByte() * scale; break; case VertexSettings.CompType.Int8: ret[i] = (float)ins.ReadSByte() * scale; @@ -36,7 +37,6 @@ namespace NW4RTools.Models { break; 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 VertexSettings.CompType.Float32: ret[i] = ins.ReadFloat(); @@ -49,6 +49,18 @@ namespace NW4RTools.Models { return ret; } + public void Parse() { + if (Data != null) + return; + + Data = new float[EntryCount][]; + + for (int i = 0; i < EntryCount; i++) { + Data[i] = GetEntry(i); + } + } + + public abstract int GetRealCount(); } @@ -101,6 +113,79 @@ namespace NW4RTools.Models { return -1; } } + + public override float[] GetEntry(int index) { + float[] ret = new float[GetRealCount()]; + + InputStream ins = new InputStream(RawData); + ins.Seek(index * EntrySize); + + byte r, g, b, a; + + // todo: better solution instead of this cast + switch ((VertexSettings.CompClrType)ComponentType) { + case VertexSettings.CompClrType.RGB565: + ushort v565 = ins.ReadUInt16(); + r = (byte)((v565 & 0xF800) >> 8); + g = (byte)((v565 & 0x07E0) >> 3); + b = (byte)((v565 & 0x001F) << 3); + a = 255; + break; + + case VertexSettings.CompClrType.RGB8: + r = ins.ReadByte(); + g = ins.ReadByte(); + b = ins.ReadByte(); + a = 255; + break; + + case VertexSettings.CompClrType.RGBX8: + r = ins.ReadByte(); + g = ins.ReadByte(); + b = ins.ReadByte(); + a = 255; + ins.Skip(1); + break; + + case VertexSettings.CompClrType.RGBA4: + ushort vA4 = ins.ReadUInt16(); + r = (byte)((vA4 & 0xF000) >> 8); + g = (byte)((vA4 & 0x0F00) >> 4); + b = (byte)(vA4 & 0x00F0); + a = (byte)((vA4 & 0x000F) << 4); + break; + + case VertexSettings.CompClrType.RGBA6: + byte v1 = ins.ReadByte(); + byte v2 = ins.ReadByte(); + byte v3 = ins.ReadByte(); + r = (byte)(v1 & 0xF8); + g = (byte)(((v1 & 7) << 6) | ((v2 & 0xF0) >> 2)); + b = (byte)(((v2 & 0xF) << 4) | ((v3 & 0xC) >> 4)); + a = (byte)((v3 & 0x3F) << 2); + break; + + case VertexSettings.CompClrType.RGBA8: + r = ins.ReadByte(); + g = ins.ReadByte(); + b = ins.ReadByte(); + a = ins.ReadByte(); + break; + + default: + throw new NotImplementedException(String.Format("unimplemented type {0}", (int)ComponentType)); + } + + // this is the easiest way I can think of to handle this atm + // just use floats for EVERYTHING + ret[0] = r * (1.0f / 256); + ret[1] = g * (1.0f / 256); + ret[2] = b * (1.0f / 256); + if (ret.Length > 3) + ret[3] = a * (1.0f / 256); + + return ret; + } } diff --git a/NW4RTools/NW4RTools.csproj b/NW4RTools/NW4RTools.csproj index 0a462a3..e1da0e8 100644 --- a/NW4RTools/NW4RTools.csproj +++ b/NW4RTools/NW4RTools.csproj @@ -35,6 +35,11 @@ <Reference Include="System" /> <Reference Include="System.Xml" /> <Reference Include="System.Drawing" /> + <Reference Include="System.Core" /> + <Reference Include="OpenTK, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\CSharp\opentk\Binaries\OpenTK\Release\OpenTK.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="AssemblyInfo.cs" /> @@ -62,10 +67,19 @@ <Compile Include="ColladaWriter.cs" /> <Compile Include="Texture.cs" /> <Compile Include="Misc.cs" /> + <Compile Include="Models\OpenGL\GLModel.cs" /> + <Compile Include="Models\OpenGL\GLTexture.cs" /> + <Compile Include="Models\OpenGL\GLDisplayList.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> <Folder Include="Models\" /> <Folder Include="Util\" /> + <Folder Include="Models\OpenGL\" /> + </ItemGroup> + <ItemGroup> + <None Include="OpenTK.dll.config"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> </ItemGroup> </Project>
\ No newline at end of file diff --git a/NW4RTools/NW4RTools.pidb b/NW4RTools/NW4RTools.pidb Binary files differindex ff53d24..6c88349 100644 --- a/NW4RTools/NW4RTools.pidb +++ b/NW4RTools/NW4RTools.pidb diff --git a/NW4RTools/OpenTK.dll.config b/NW4RTools/OpenTK.dll.config new file mode 100644 index 0000000..99aef86 --- /dev/null +++ b/NW4RTools/OpenTK.dll.config @@ -0,0 +1,12 @@ +<configuration>
+ <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
+ <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
+ <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
+ <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
+ <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
+ <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+</configuration>
diff --git a/NW4RTools/Texture.cs b/NW4RTools/Texture.cs index 2de9ad8..7063056 100644 --- a/NW4RTools/Texture.cs +++ b/NW4RTools/Texture.cs @@ -274,8 +274,6 @@ namespace NW4RTools { image.UnlockBits(bits); - image.RotateFlip(RotateFlipType.RotateNoneFlipY); // TODO: remove this, and fix texcoords properly - BaseImage = image; Format = format; } diff --git a/NW4RTools/Util/IOrderedDictionary.cs b/NW4RTools/Util/IOrderedDictionary.cs index 6cf9b85..31a61eb 100644 --- a/NW4RTools/Util/IOrderedDictionary.cs +++ b/NW4RTools/Util/IOrderedDictionary.cs @@ -58,5 +58,7 @@ namespace NW4RTools.Util TKey GetKeyForIndex(int index);
+ TKey GetKeyForValue(TValue value);
+ int GetIndexForValue(TValue value);
}
}
diff --git a/NW4RTools/Util/OrderedDictionary.cs b/NW4RTools/Util/OrderedDictionary.cs index 98e523a..0463d33 100644 --- a/NW4RTools/Util/OrderedDictionary.cs +++ b/NW4RTools/Util/OrderedDictionary.cs @@ -171,6 +171,24 @@ namespace NW4RTools.Util return List[index].Key;
}
+ public TKey GetKeyForValue(TValue value) {
+ foreach (var kv in List) {
+ if (kv.Value.Equals(value))
+ return kv.Key;
+ }
+ throw new KeyNotFoundException();
+ }
+
+ public int GetIndexForValue(TValue value) {
+ int i = 0;
+ foreach (var kv in List) {
+ if (kv.Value.Equals(value))
+ return i;
+ i += 1;
+ }
+ throw new KeyNotFoundException();
+ }
+
/// <summary>
/// Inserts a new entry into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary<TKey,TValue></see> collection with the specified key and value at the specified index.
/// </summary>
diff --git a/NW4RTools/VertexSettings.cs b/NW4RTools/VertexSettings.cs index 5eac02a..b8a341f 100644 --- a/NW4RTools/VertexSettings.cs +++ b/NW4RTools/VertexSettings.cs @@ -129,6 +129,15 @@ namespace NW4RTools { Float32 = 4 } + public enum CompClrType { + RGB565 = 0, + RGB8 = 1, + RGBX8 = 2, + RGBA4 = 3, + RGBA6 = 4, + RGBA8 = 5 + } + public bool PNMatrixIndexExists; public bool[] TexCoordMatrixIndexExists; @@ -139,7 +148,8 @@ namespace NW4RTools { public CompCount[] ColorCount, TexCoordCount; public CompType PositionFormat, NormalFormat; - public CompType[] ColorFormat, TexCoordFormat; + public CompClrType[] ColorFormat; + public CompType[] TexCoordFormat; public byte PositionFrac; public byte[] TexCoordFrac; @@ -155,7 +165,7 @@ namespace NW4RTools { ColorCount = new CompCount[2]; TexCoordCount = new CompCount[8]; - ColorFormat = new CompType[2]; + ColorFormat = new CompClrType[2]; TexCoordFormat = new CompType[8]; TexCoordFrac = new byte[8]; @@ -189,10 +199,10 @@ namespace NW4RTools { NormalFormat = (CompType)((val1 & 0x1C00) >> 10); ColorCount[0] = (CompCount)((val1 & 0x2000) >> 13); - ColorFormat[0] = (CompType)((val1 & 0x1C000) >> 14); + ColorFormat[0] = (CompClrType)((val1 & 0x1C000) >> 14); ColorCount[1] = (CompCount)((val1 & 0x20000) >> 17); - ColorFormat[1] = (CompType)((val1 & 0x1C0000) >> 18); + ColorFormat[1] = (CompClrType)((val1 & 0x1C0000) >> 18); TexCoordCount[0] = (CompCount)((val1 & 0x200000) >> 21); TexCoordFormat[0] = (CompType)((val1 & 0x1C00000) >> 22); diff --git a/NW4RTools/bin/Debug/NW4RTools.dll b/NW4RTools/bin/Debug/NW4RTools.dll Binary files differindex 91a4b75..dbcb459 100755 --- a/NW4RTools/bin/Debug/NW4RTools.dll +++ b/NW4RTools/bin/Debug/NW4RTools.dll diff --git a/NW4RTools/bin/Debug/NW4RTools.dll.mdb b/NW4RTools/bin/Debug/NW4RTools.dll.mdb Binary files differindex 127ef0f..b67ce24 100644 --- a/NW4RTools/bin/Debug/NW4RTools.dll.mdb +++ b/NW4RTools/bin/Debug/NW4RTools.dll.mdb diff --git a/NW4RTools/bin/Debug/OpenTK.dll b/NW4RTools/bin/Debug/OpenTK.dll Binary files differnew file mode 100644 index 0000000..afff0dd --- /dev/null +++ b/NW4RTools/bin/Debug/OpenTK.dll diff --git a/NW4RTools/bin/Debug/OpenTK.dll.config b/NW4RTools/bin/Debug/OpenTK.dll.config new file mode 100644 index 0000000..99aef86 --- /dev/null +++ b/NW4RTools/bin/Debug/OpenTK.dll.config @@ -0,0 +1,12 @@ +<configuration>
+ <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
+ <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
+ <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
+ <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
+ <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
+ <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+</configuration>
diff --git a/TestApp/Main.cs b/TestApp/Main.cs index 3eb49a4..447f556 100644 --- a/TestApp/Main.cs +++ b/TestApp/Main.cs @@ -2,6 +2,9 @@ using System; using System.IO; using System.Collections.Generic; using NW4RTools; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; namespace TestApp { class MainClass { @@ -10,13 +13,22 @@ namespace TestApp { string mdlName = "CS_W1"; //string mdlName = "bgB_4502"; + //string mdlName = "cobKoopaCastle"; string whatever = (mdlName == "CS_W2" || mdlName == "CS_W3" || mdlName == "CS_W6") ? "a" : ""; byte[] file = File.ReadAllBytes(mdlPath + mdlName + ".brres"); ResFile rf = BrresReader.LoadFile(file); - var texs = rf.GetGroup<Texture>("Textures(NW4R)"); + using (var gw = new RenderWindow()) { + gw.Title = mdlName; + gw.SetModel(rf, mdlName); + gw.Run(1, 1); + } + + + + /*var texs = rf.GetGroup<Texture>("Textures(NW4R)"); // wtf C#?! foreach (var kv in (IEnumerable<KeyValuePair<string,Texture>>)texs) { kv.Value.BaseImage.Save(mdlPath + "images/" + kv.Key + ".png"); @@ -27,7 +39,7 @@ namespace TestApp { //var sw = new StreamWriter(objFile); //ObjWriter.WriteModel(sw, rf, mdlName); ColladaWriter.WriteModel(objFile, rf, mdlName + whatever); - objFile.Close(); + objFile.Close();*/ } } } diff --git a/TestApp/RenderWindow.cs b/TestApp/RenderWindow.cs new file mode 100644 index 0000000..2dfe1ec --- /dev/null +++ b/TestApp/RenderWindow.cs @@ -0,0 +1,57 @@ +using System; +using NW4RTools; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; +using OpenTK.Input; + +namespace TestApp { + public class RenderWindow : GameWindow { + public RenderWindow() : base(800, 600, GraphicsMode.Default, "Test Model") { + + } + + private NW4RTools.Models.OpenGL.GLModel m_glModel; + + public void SetModel(ResFile rf, string modelName) { + m_glModel = new NW4RTools.Models.OpenGL.GLModel(rf, modelName); + } + + + protected override void OnLoad(EventArgs e) { + base.OnLoad(e); + + GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f); + GL.Enable(EnableCap.DepthTest); + + m_glModel.Prepare(Context); + } + + protected override void OnResize(EventArgs e) { + base.OnResize(e); + + GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height); + + Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 2000.0f); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix(ref projection); + } + + protected override void OnUpdateFrame(FrameEventArgs e) { + base.OnUpdateFrame(e); + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + Matrix4 modelview = Matrix4.LookAt(new Vector3(0, 1200, 500), Vector3.UnitZ, Vector3.UnitY); + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadMatrix(ref modelview); + + m_glModel.Render(Context); + + SwapBuffers(); + } + + + } +} + diff --git a/TestApp/TestApp.csproj b/TestApp/TestApp.csproj index 5c96e3b..e979782 100644 --- a/TestApp/TestApp.csproj +++ b/TestApp/TestApp.csproj @@ -31,10 +31,15 @@ </PropertyGroup> <ItemGroup> <Reference Include="System" /> + <Reference Include="OpenTK, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\CSharp\opentk\Binaries\OpenTK\Release\OpenTK.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="Main.cs" /> <Compile Include="AssemblyInfo.cs" /> + <Compile Include="RenderWindow.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> diff --git a/TestApp/TestApp.pidb b/TestApp/TestApp.pidb Binary files differindex bf2fb29..4b3557d 100644 --- a/TestApp/TestApp.pidb +++ b/TestApp/TestApp.pidb diff --git a/TestApp/bin/Debug/NW4RTools.dll b/TestApp/bin/Debug/NW4RTools.dll Binary files differindex 91a4b75..dbcb459 100755 --- a/TestApp/bin/Debug/NW4RTools.dll +++ b/TestApp/bin/Debug/NW4RTools.dll diff --git a/TestApp/bin/Debug/NW4RTools.dll.mdb b/TestApp/bin/Debug/NW4RTools.dll.mdb Binary files differindex 127ef0f..b67ce24 100644 --- a/TestApp/bin/Debug/NW4RTools.dll.mdb +++ b/TestApp/bin/Debug/NW4RTools.dll.mdb diff --git a/TestApp/bin/Debug/OpenTK.dll b/TestApp/bin/Debug/OpenTK.dll Binary files differnew file mode 100644 index 0000000..afff0dd --- /dev/null +++ b/TestApp/bin/Debug/OpenTK.dll diff --git a/TestApp/bin/Debug/OpenTK.dll.config b/TestApp/bin/Debug/OpenTK.dll.config new file mode 100644 index 0000000..99aef86 --- /dev/null +++ b/TestApp/bin/Debug/OpenTK.dll.config @@ -0,0 +1,12 @@ +<configuration>
+ <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
+ <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
+ <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
+ <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
+ <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
+ <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
+ <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+</configuration>
diff --git a/TestApp/bin/Debug/TestApp.exe b/TestApp/bin/Debug/TestApp.exe Binary files differindex 1bce1bb..bafaf4c 100755 --- a/TestApp/bin/Debug/TestApp.exe +++ b/TestApp/bin/Debug/TestApp.exe diff --git a/TestApp/bin/Debug/TestApp.exe.mdb b/TestApp/bin/Debug/TestApp.exe.mdb Binary files differindex 00eab08..3f3b216 100644 --- a/TestApp/bin/Debug/TestApp.exe.mdb +++ b/TestApp/bin/Debug/TestApp.exe.mdb |