summaryrefslogtreecommitdiff
path: root/NW4RTools
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NW4RTools.userprefs19
-rw-r--r--NW4RTools/Enums.cs10
-rw-r--r--NW4RTools/Models/ByteCode.cs2
-rw-r--r--NW4RTools/Models/OpenGL/GLModel.cs243
-rw-r--r--NW4RTools/NW4RTools.pidbbin532733 -> 541003 bytes
-rw-r--r--NW4RTools/VertexSettings.cs17
-rwxr-xr-xNW4RTools/bin/Debug/NW4RTools.dllbin173568 -> 175616 bytes
-rw-r--r--NW4RTools/bin/Debug/NW4RTools.dll.mdbbin93825 -> 94193 bytes
8 files changed, 212 insertions, 79 deletions
diff --git a/NW4RTools.userprefs b/NW4RTools.userprefs
index b0eba72..facc6fe 100644
--- a/NW4RTools.userprefs
+++ b/NW4RTools.userprefs
@@ -1,14 +1,23 @@
<Properties>
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
- <MonoDevelop.Ide.Workbench ActiveDocument="NW4RTools/ColladaWriter.cs">
+ <MonoDevelop.Ide.Workbench ActiveDocument="NW4RTools/Models/OpenGL/GLModel.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="TestApp/Main.cs" Line="14" Column="6" />
+ <File FileName="NW4RTools/BrresReader.cs" Line="163" Column="17" />
+ <File FileName="NW4RTools/Enums.cs" Line="20" Column="29" />
+ <File FileName="NW4RTools/ColladaWriter.cs" Line="147" 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="144" Column="34" />
<File FileName="NW4RTools/Texture.cs" Line="263" Column="8" />
+ <File FileName="NW4RTools/Models/VertexData.cs" Line="121" Column="32" />
+ <File FileName="TestApp/RenderWindow.cs" Line="48" Column="82" />
+ <File FileName="NW4RTools/Models/OpenGL/GLModel.cs" Line="310" Column="83" />
+ <File FileName="NW4RTools/VertexSettings.cs" Line="187" Column="1" />
+ <File FileName="NW4RTools/Util/OrderedDictionary.cs" Line="176" Column="24" />
+ <File FileName="NW4RTools/Util/IOrderedDictionary.cs" Line="62" Column="38" />
+ <File FileName="NW4RTools/Models/OpenGL/GLTexture.cs" Line="15" Column="1" />
+ <File FileName="NW4RTools/Models/ByteCode.cs" Line="40" Column="18" />
+ <File FileName="NW4RTools/Models/TextureInfo.cs" Line="1" Column="1" />
</Files>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints>
diff --git a/NW4RTools/Enums.cs b/NW4RTools/Enums.cs
index a81da6c..734eb9b 100644
--- a/NW4RTools/Enums.cs
+++ b/NW4RTools/Enums.cs
@@ -12,6 +12,16 @@ namespace NW4RTools {
}
+ public enum GXCommand {
+ // Missing many!!
+ LoadPosMtxFromArray = 0x20,
+ LoadNrmMtxFromArray = 0x28,
+ LoadTexCoordMtxFromArray = 0x30,
+ LoadLightFromArray = 0x38,
+ DrawPrimitiveMask = 0x80
+ }
+
+
public enum TextureFormat {
I4,
I8,
diff --git a/NW4RTools/Models/ByteCode.cs b/NW4RTools/Models/ByteCode.cs
index 438c009..6df6dee 100644
--- a/NW4RTools/Models/ByteCode.cs
+++ b/NW4RTools/Models/ByteCode.cs
@@ -28,6 +28,7 @@ namespace NW4RTools.Models {
public UInt16 ParentMatrixID;
}
+ // According to BrawlLib: in NodeMix, this is for "weighted influences"
public class BlendMatricesInstruction : Instruction {
public override OpType GetOp() {
return OpType.BlendMatrices;
@@ -52,6 +53,7 @@ namespace NW4RTools.Models {
public UInt16 NodeID;
}
+ // According to BrawlLib: in NodeMix, this is for "primary influences"
public class AssignMtxToNodeInstruction : Instruction {
public override OpType GetOp() {
return OpType.AssignMtxToNode;
diff --git a/NW4RTools/Models/OpenGL/GLModel.cs b/NW4RTools/Models/OpenGL/GLModel.cs
index 2e5779e..315415e 100644
--- a/NW4RTools/Models/OpenGL/GLModel.cs
+++ b/NW4RTools/Models/OpenGL/GLModel.cs
@@ -8,34 +8,42 @@ using OpenTK.Graphics.OpenGL;
namespace NW4RTools.Models.OpenGL {
public class GLModel {
- public ResFile SourceFile {
- get; private set;
- }
+ public ResFile SourceFile { get; private set; }
- public Model SourceModel {
- 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 class MyNode {
+ Node RealNode;
+ MyNode Parent;
+ List<MyNode> Children;
+ }
+
+
private ResDict<Texture> m_textureGroup;
private Dictionary<string, GLTexture> m_glTextures;
private Dictionary<Material, GLDisplayList> m_glMaterials;
private Dictionary<Shape, GLDisplayList> m_glShapes;
+ private Matrix4[] m_matrices;
+ private MyNode[] m_nodesByMtxID;
+ private MyNode[] m_nodes;
+
+ #region Initialisation
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)) {
@@ -45,30 +53,45 @@ namespace NW4RTools.Models.OpenGL {
}
}
}
-
+
// 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));
}
+
+ // allocate stuff for nodes
+ m_matrices = new Matrix4[SourceModel.MatrixIDtoNodeID.Length];
+
+ // build the hierarchy
+ BuildNodeHierarchy();
+ }
+
+ private void BuildNodeHierarchy() {
+ var nodeTree = SourceModel.Bytecode["NodeTree"];
+
+ foreach (var insn in nodeTree.Instructions) {
+ if (insn.GetOp() == ByteCode.OpType.AssignNodeToParentMtx) {
+ MyNode n = new MyNode();
+ }
+ }
}
+ #endregion
+ 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 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
- };
+ // GX_CLAMP, GX_REPEAT, GX_MIRROR
+ private static readonly TextureWrapMode[] GXtoGLTextureWrapModes = new TextureWrapMode[] { TextureWrapMode.ClampToEdge, TextureWrapMode.Repeat, TextureWrapMode.MirroredRepeat };
private Material m_currentMaterial;
@@ -79,29 +102,72 @@ namespace NW4RTools.Models.OpenGL {
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]);
-
+
+ // HACKY TEST !!
+ GL.MatrixMode(MatrixMode.Modelview);
+ var node = SourceModel.Nodes[insn.NodeID];
+ var m = node.NodeMatrix;
+ /*double cosX = Math.Cos(node.Rotation.x / 180 * Math.PI);
+ double cosY = Math.Cos(node.Rotation.y / 180 * Math.PI);
+ double cosZ = Math.Cos(node.Rotation.z / 180 * Math.PI);
+ double sinX = Math.Sin(node.Rotation.x / 180 * Math.PI);
+ double sinY = Math.Sin(node.Rotation.y / 180 * Math.PI);
+ double sinZ = Math.Sin(node.Rotation.z / 180 * Math.PI);
+
+ var nodeMatrix = new Matrix4d();
+ nodeMatrix.M11 = node.Scale.x * cosY * cosZ;
+ nodeMatrix.M12 = node.Scale.y * (sinX * cosZ * sinY - cosX * sinZ);
+ nodeMatrix.M13 = node.Scale.z * (sinX * sinZ + cosX * cosZ * sinY);
+ nodeMatrix.M14 = node.Translation.x;
+ nodeMatrix.M21 = node.Scale.x * sinZ * cosY;
+ nodeMatrix.M22 = node.Scale.y * (sinX * sinZ * sinY + cosZ * cosX);
+ nodeMatrix.M23 = node.Scale.z * (cosX * sinZ * sinY - sinX * cosZ);
+ nodeMatrix.M24 = node.Translation.y;
+ nodeMatrix.M31 = -node.Scale.x * sinY;
+ nodeMatrix.M32 = node.Scale.y * sinX * cosY;
+ nodeMatrix.M33 = node.Scale.z * cosX * cosY;
+ nodeMatrix.M34 = node.Translation.z;
+ nodeMatrix.M41 = 0;
+ nodeMatrix.M42 = 0;
+ nodeMatrix.M43 = 0;
+ nodeMatrix.M44 = 1;
+
+ GL.PushMatrix();
+ GL.MultTransposeMatrix(ref nodeMatrix);
+ //*/
+
+ GL.PushMatrix();
+ GL.MultTransposeMatrix(new float[] { m.v00, m.v01, m.v02, m.v03, m.v10, m.v11, m.v12, m.v13, m.v20, m.v21,
+ m.v22, m.v23, 0, 0, 0, 1 });
+
+ //GL.Translate(node.Translation.x, node.Translation.y, node.Translation.z);
+
var shape = SourceModel.Shapes[insn.ShapeID];
m_glShapes[shape].Execute();
+
+ GL.PopMatrix();
}
public void Render(IGraphicsContext context) {
// This'll be fun.
-
+
ClearCache();
+ //CalculateNodes();
+
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) {
@@ -112,6 +178,14 @@ namespace NW4RTools.Models.OpenGL {
}
+ private void BindTextureInfo(TextureInfo info) {
+ m_glTextures[info.TextureName].Bind(TextureTarget.Texture2D);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)GXtoGLTextureWrapModes[(int)info.WrapS]);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)GXtoGLTextureWrapModes[(int)info.WrapT]);
+ }
+
+
#region Display Lists
private GLDisplayList MakeMaterialDisplayList(Material m) {
@@ -129,12 +203,12 @@ namespace NW4RTools.Models.OpenGL {
for (int i = 0; i < 8; i++) {
GL.ActiveTexture(TextureUnits[i]);
- GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Decal);
+ GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate);
if (texInfoArray[i] == null) {
GL.BindTexture(TextureTarget.Texture2D, 0);
} else {
- m_glTextures[texInfoArray[i].TextureName].Bind(TextureTarget.Texture2D);
+ BindTextureInfo(texInfoArray[i]);
}
}
@@ -166,7 +240,6 @@ namespace NW4RTools.Models.OpenGL {
vs.SetDesc(vtxDesc1, vtxDesc2);
vs.SetAttrFmt(vtxAttr1, vtxAttr2, vtxAttr3);
-
InputStream dl = new InputStream(shape.DisplayList2);
while (true) {
@@ -177,58 +250,90 @@ namespace NW4RTools.Models.OpenGL {
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]]);
+ if ((cmd & (int)GXCommand.DrawPrimitiveMask) != 0) {
+ PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7);
+ int vtxCount = dl.ReadUInt16();
+
+ if ((cmd & 7) != 0)
+ Console.WriteLine("WARNING!! Not using vertex attribute table 0");
+
+ // 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]]);
+ }
+ }
+
+ // TODO: normals
+
+ GL.Vertex3(shape.PosData.Data[vtxs[i].Position]);
}
- GL.Vertex3(shape.PosData.Data[vtxs[i].Position]);
+ GL.End();
+ } else {
+ // some other command
+ switch ((GXCommand)cmd) {
+ case GXCommand.LoadPosMtxFromArray:
+ int targetID = dl.ReadUInt16();
+ int sourceID = (dl.ReadUInt16() & 0xFFF) / 12;
+ Console.WriteLine("Load PosMtx from array: {0} => {1}", targetID, sourceID);
+ break;
+ case GXCommand.LoadNrmMtxFromArray:
+ dl.Skip(4);
+ Console.WriteLine("UNIMPLEMENTED: Load NrmMtx from array");
+ break;
+ case GXCommand.LoadTexCoordMtxFromArray:
+ dl.Skip(4);
+ Console.WriteLine("UNIMPLEMENTED: Load TexCoordMtx from array");
+ break;
+ case GXCommand.LoadLightFromArray:
+ dl.Skip(4);
+ Console.WriteLine("UNIMPLEMENTED: Load Light from array");
+ break;
+ default:
+ Console.WriteLine("UNKNOWN DL COMMAND");
+ break;
+ }
}
-
- GL.End();
}
displayList.End();
return displayList;
}
-
+
#endregion
}
}
diff --git a/NW4RTools/NW4RTools.pidb b/NW4RTools/NW4RTools.pidb
index 6c88349..d805eec 100644
--- a/NW4RTools/NW4RTools.pidb
+++ b/NW4RTools/NW4RTools.pidb
Binary files differ
diff --git a/NW4RTools/VertexSettings.cs b/NW4RTools/VertexSettings.cs
index b8a341f..2a0d3ac 100644
--- a/NW4RTools/VertexSettings.cs
+++ b/NW4RTools/VertexSettings.cs
@@ -8,14 +8,21 @@ namespace NW4RTools {
public int[] Colors;
public int[] TexCoords;
+ public byte PosMtxIndex;
+ public byte[] TexCoordMtxIndex;
public void LoadFrom(InputStream ins, VertexSettings vs) {
if (vs.PNMatrixIndexExists)
- throw new NotImplementedException();
- if (vs.TexCoordMatrixIndexExists[0])
- throw new NotImplementedException();
- // won't bother with the rest
+ PosMtxIndex = ins.ReadByte();
+
+ for (int i = 0; i < 8; i++) {
+ if (vs.TexCoordMatrixIndexExists[i]) {
+ if (TexCoordMtxIndex == null)
+ TexCoordMtxIndex = new byte[8];
+ TexCoordMtxIndex[i] = ins.ReadByte();
+ }
+ }
switch (vs.PositionDesc) {
case VertexSettings.DescType.Direct:
@@ -34,7 +41,7 @@ namespace NW4RTools {
break;
}
- // not sure how to detect NBT3 yet
+ // not sure how to detect NBT3 yet -- or if it's even relevant?
switch (vs.NormalDesc) {
case VertexSettings.DescType.Direct:
throw new NotImplementedException();
diff --git a/NW4RTools/bin/Debug/NW4RTools.dll b/NW4RTools/bin/Debug/NW4RTools.dll
index dbcb459..0fe74f3 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 b67ce24..f7eb0df 100644
--- a/NW4RTools/bin/Debug/NW4RTools.dll.mdb
+++ b/NW4RTools/bin/Debug/NW4RTools.dll.mdb
Binary files differ