summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NW4RTools.userprefs6
-rw-r--r--NW4RTools/BrresReader.cs19
-rw-r--r--NW4RTools/ColladaWriter.cs44
-rw-r--r--NW4RTools/Enums.cs22
-rw-r--r--NW4RTools/Models/OpenGL/GLDisplayList.cs31
-rw-r--r--NW4RTools/Models/OpenGL/GLModel.cs235
-rw-r--r--NW4RTools/Models/OpenGL/GLTexture.cs46
-rw-r--r--NW4RTools/Models/TextureInfo.cs3
-rw-r--r--NW4RTools/Models/VertexData.cs95
-rw-r--r--NW4RTools/NW4RTools.csproj14
-rw-r--r--NW4RTools/NW4RTools.pidbbin531637 -> 532733 bytes
-rw-r--r--NW4RTools/OpenTK.dll.config12
-rw-r--r--NW4RTools/Texture.cs2
-rw-r--r--NW4RTools/Util/IOrderedDictionary.cs2
-rw-r--r--NW4RTools/Util/OrderedDictionary.cs18
-rw-r--r--NW4RTools/VertexSettings.cs18
-rwxr-xr-xNW4RTools/bin/Debug/NW4RTools.dllbin166400 -> 173568 bytes
-rw-r--r--NW4RTools/bin/Debug/NW4RTools.dll.mdbbin90788 -> 93825 bytes
-rw-r--r--NW4RTools/bin/Debug/OpenTK.dllbin0 -> 2719744 bytes
-rw-r--r--NW4RTools/bin/Debug/OpenTK.dll.config12
-rw-r--r--TestApp/Main.cs16
-rw-r--r--TestApp/RenderWindow.cs57
-rw-r--r--TestApp/TestApp.csproj5
-rw-r--r--TestApp/TestApp.pidbbin2991 -> 3039 bytes
-rwxr-xr-xTestApp/bin/Debug/NW4RTools.dllbin166400 -> 173568 bytes
-rw-r--r--TestApp/bin/Debug/NW4RTools.dll.mdbbin90788 -> 93825 bytes
-rw-r--r--TestApp/bin/Debug/OpenTK.dllbin0 -> 2719744 bytes
-rw-r--r--TestApp/bin/Debug/OpenTK.dll.config12
-rwxr-xr-xTestApp/bin/Debug/TestApp.exebin4608 -> 5632 bytes
-rw-r--r--TestApp/bin/Debug/TestApp.exe.mdbbin548 -> 992 bytes
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
index ff53d24..6c88349 100644
--- a/NW4RTools/NW4RTools.pidb
+++ b/NW4RTools/NW4RTools.pidb
Binary files differ
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&lt;TKey,TValue&gt;</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
index 91a4b75..dbcb459 100755
--- a/NW4RTools/bin/Debug/NW4RTools.dll
+++ b/NW4RTools/bin/Debug/NW4RTools.dll
Binary files differ
diff --git a/NW4RTools/bin/Debug/NW4RTools.dll.mdb b/NW4RTools/bin/Debug/NW4RTools.dll.mdb
index 127ef0f..b67ce24 100644
--- a/NW4RTools/bin/Debug/NW4RTools.dll.mdb
+++ b/NW4RTools/bin/Debug/NW4RTools.dll.mdb
Binary files differ
diff --git a/NW4RTools/bin/Debug/OpenTK.dll b/NW4RTools/bin/Debug/OpenTK.dll
new file mode 100644
index 0000000..afff0dd
--- /dev/null
+++ b/NW4RTools/bin/Debug/OpenTK.dll
Binary files differ
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
index bf2fb29..4b3557d 100644
--- a/TestApp/TestApp.pidb
+++ b/TestApp/TestApp.pidb
Binary files differ
diff --git a/TestApp/bin/Debug/NW4RTools.dll b/TestApp/bin/Debug/NW4RTools.dll
index 91a4b75..dbcb459 100755
--- a/TestApp/bin/Debug/NW4RTools.dll
+++ b/TestApp/bin/Debug/NW4RTools.dll
Binary files differ
diff --git a/TestApp/bin/Debug/NW4RTools.dll.mdb b/TestApp/bin/Debug/NW4RTools.dll.mdb
index 127ef0f..b67ce24 100644
--- a/TestApp/bin/Debug/NW4RTools.dll.mdb
+++ b/TestApp/bin/Debug/NW4RTools.dll.mdb
Binary files differ
diff --git a/TestApp/bin/Debug/OpenTK.dll b/TestApp/bin/Debug/OpenTK.dll
new file mode 100644
index 0000000..afff0dd
--- /dev/null
+++ b/TestApp/bin/Debug/OpenTK.dll
Binary files differ
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
index 1bce1bb..bafaf4c 100755
--- a/TestApp/bin/Debug/TestApp.exe
+++ b/TestApp/bin/Debug/TestApp.exe
Binary files differ
diff --git a/TestApp/bin/Debug/TestApp.exe.mdb b/TestApp/bin/Debug/TestApp.exe.mdb
index 00eab08..3f3b216 100644
--- a/TestApp/bin/Debug/TestApp.exe.mdb
+++ b/TestApp/bin/Debug/TestApp.exe.mdb
Binary files differ