summaryrefslogtreecommitdiff
path: root/NW4RTools/Models/OpenGL/GLModel.cs
diff options
context:
space:
mode:
Diffstat (limited to 'NW4RTools/Models/OpenGL/GLModel.cs')
-rw-r--r--NW4RTools/Models/OpenGL/GLModel.cs243
1 files changed, 174 insertions, 69 deletions
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
}
}