summaryrefslogtreecommitdiff
path: root/NW4RTools/ObjWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'NW4RTools/ObjWriter.cs')
-rw-r--r--NW4RTools/ObjWriter.cs130
1 files changed, 130 insertions, 0 deletions
diff --git a/NW4RTools/ObjWriter.cs b/NW4RTools/ObjWriter.cs
new file mode 100644
index 0000000..72a134c
--- /dev/null
+++ b/NW4RTools/ObjWriter.cs
@@ -0,0 +1,130 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using NW4RTools.Models;
+
+namespace NW4RTools {
+ public class ObjWriter {
+ public static void WriteModel(TextWriter tw, ResFile file, string modelName) {
+ new ObjWriter(file).SaveModel(tw, modelName);
+ }
+
+
+
+ ResFile CurrentFile;
+ Models.Model CurrentModel;
+ TextWriter Output;
+
+ private ObjWriter(ResFile file) {
+ CurrentFile = file;
+ }
+
+ Dictionary<Models.VertexPosData, int> VtxPosOffsets;
+ Dictionary<Models.VertexNrmData, int> VtxNrmOffsets;
+ Dictionary<Models.VertexTexCoordData, int> VtxTexCoordOffsets;
+
+ public void SaveModel(TextWriter tw, string modelName) {
+ Output = tw;
+ CurrentModel = CurrentFile.GetGroup<Model>("3DModels(NW4R)")[modelName];
+
+ Output.WriteLine("# {0} exported by Treeki's NW4RTools", modelName);
+ Output.WriteLine("# {0}", DateTime.Now);
+ Output.WriteLine();
+
+ // Write vertex data pool
+ int Offset;
+
+ VtxPosOffsets = new Dictionary<VertexPosData, int>();
+ Offset = 1;
+ foreach (var kv in CurrentModel.VtxPosData) {
+ VtxPosOffsets[kv.Value] = Offset;
+ Output.WriteLine("# Vertex Positions: {0} [offset {1}]", kv.Key, Offset);
+
+ for (int i = 0; i < kv.Value.EntryCount; i++) {
+ float[] v = kv.Value.GetEntry(i);
+ Output.WriteLine("v {0} {1} {2}", v[0], v[1], v[2]);
+ }
+
+ Offset += kv.Value.EntryCount;
+ }
+
+ VtxNrmOffsets = new Dictionary<VertexNrmData, int>();
+ Offset = 1;
+ foreach (var kv in CurrentModel.VtxNrmData) {
+ VtxNrmOffsets[kv.Value] = Offset;
+ Output.WriteLine("# Vertex Normals: {0} [offset {1}]", kv.Key, Offset);
+
+ for (int i = 0; i < kv.Value.EntryCount; i++) {
+ float[] v = kv.Value.GetEntry(i);
+ Output.WriteLine("vn {0} {1} {2}", v[0], v[1], v[2]);
+ }
+
+ Offset += kv.Value.EntryCount;
+ }
+
+ VtxTexCoordOffsets = new Dictionary<VertexTexCoordData, int>();
+ Offset = 1;
+ foreach (var kv in CurrentModel.VtxTexCoordData) {
+ VtxTexCoordOffsets[kv.Value] = Offset;
+ Output.WriteLine("# Vertex TexCoords: {0} [offset {1}]", kv.Key, Offset);
+
+ for (int i = 0; i < kv.Value.EntryCount; i++) {
+ float[] v = kv.Value.GetEntry(i);
+ Output.WriteLine("vt {0} {1}", v[0], v[1]);
+ }
+
+ Offset += kv.Value.EntryCount;
+ }
+
+ Output.WriteLine();
+
+ // Write shapes
+ // TODO: replace with something using the Bytecode
+ foreach (var kv in CurrentModel.Shapes) {
+ Output.WriteLine("g {0}", kv.Key);
+
+ WriteShape(kv.Value);
+
+ Output.WriteLine();
+ }
+
+ Output.Flush();
+ }
+
+
+ private void WriteShape(Models.Shape shape) {
+ // parse the DisplayList
+
+ int posOffset = VtxPosOffsets[shape.PosData];
+ int nrmOffset = shape.NrmData == null ? -1 : VtxNrmOffsets[shape.NrmData];
+ int tcOffset = shape.TexCoordData[0] == null ? -1 : VtxTexCoordOffsets[shape.TexCoordData[0]];
+ // TODO: Better DisplayList parsing, in a similar fashion to ByteCode
+ var dl = new InputStream(shape.DisplayList2);
+
+ while (true) {
+ if (dl.AtEnd)
+ break;
+
+ byte cmd = dl.ReadByte();
+ PrimitiveType prim = (PrimitiveType)cmd;
+ int vtxCount = dl.ReadUInt16();
+ Output.WriteLine("# Primitive: {0} ({1} vertices)", prim, vtxCount);
+
+ // I wonder if INDEX8 is ever used here?
+ // Going with INDEX16 for now.
+
+ switch (prim) {
+ case PrimitiveType.TriangleStrip:
+ // De-stripify it!
+
+
+ break;
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+ }
+ }
+}
+