diff options
author | Treeki <treeki@gmail.com> | 2011-02-11 01:10:44 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2011-02-11 01:10:44 +0100 |
commit | 0d017deb24e7f6f8e049616a71691f1401c50b6a (patch) | |
tree | 8b107dcb3d51163831ffcce96010367f3779585e /NW4RTools/ObjWriter.cs | |
parent | 58dead7b909861732011325f5d4844eae21a9bc2 (diff) | |
download | nw4rtools-0d017deb24e7f6f8e049616a71691f1401c50b6a.tar.gz nw4rtools-0d017deb24e7f6f8e049616a71691f1401c50b6a.zip |
tons of stuff: more work on shapes, unfinished OBJ exporter, ...
Diffstat (limited to '')
-rw-r--r-- | NW4RTools/ObjWriter.cs | 130 |
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(); + } + } + } + } +} + |