summaryrefslogtreecommitdiff
path: root/NW4RTools/ColladaWriter.cs
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2011-03-10 03:00:09 +0100
committerTreeki <treeki@gmail.com>2011-03-10 03:00:09 +0100
commit5926616de2bd346f1a1c69c93ff2aaa3c453a2b3 (patch)
treef282b05ae5616a05fb4db167fad20ec242775c27 /NW4RTools/ColladaWriter.cs
parent7d391e33a0b3d9793c95fce832abb2c6d9002186 (diff)
downloadnw4rtools-5926616de2bd346f1a1c69c93ff2aaa3c453a2b3.tar.gz
nw4rtools-5926616de2bd346f1a1c69c93ff2aaa3c453a2b3.zip
kinda hackish, but mostly working NSMBW lightmap support
Diffstat (limited to '')
-rw-r--r--NW4RTools/ColladaWriter.cs732
1 files changed, 0 insertions, 732 deletions
diff --git a/NW4RTools/ColladaWriter.cs b/NW4RTools/ColladaWriter.cs
deleted file mode 100644
index 2c57d7e..0000000
--- a/NW4RTools/ColladaWriter.cs
+++ /dev/null
@@ -1,732 +0,0 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Text;
-using NW4RTools.Models;
-using Collada141;
-
-namespace NW4RTools {
- public class ColladaWriter {
- public static void WriteModel(Stream outputStream, ResFile file, string modelName) {
- new ColladaWriter(file).SaveModel(outputStream, modelName);
- }
-
-
-
- ResFile CurrentFile;
- Models.Model CurrentModel;
- COLLADA Collada;
-
- library_geometries LibGeometries;
- library_visual_scenes LibVisualScenes;
- library_images LibImages;
- library_materials LibMaterials;
- library_effects LibEffects;
-
- private ColladaWriter(ResFile file) {
- CurrentFile = file;
- }
-
- public void SaveModel(Stream outputStream, string modelName) {
- CurrentModel = CurrentFile.GetGroup<Model>("3DModels(NW4R)")[modelName];
- Collada = new COLLADA();
-
- Collada.asset = new asset();
-
- Collada.asset.contributor = new assetContributor[1];
- 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.unit = new assetUnit();
- Collada.asset.unit.meter = 1.0;
- Collada.asset.up_axis = UpAxisType.Y_UP;
-
- var ColladaItems = new List<object>();
-
- // First up, before anything else: images and materials
- // Compile a list of every texture we use in the model
- var usedTextures = new List<string>();
-
- foreach (var kv in CurrentModel.Materials) {
- foreach (var texInfo in kv.Value.TextureInfos) {
- if (!usedTextures.Contains(texInfo.TextureName))
- usedTextures.Add(texInfo.TextureName);
- }
- }
-
- // Create a Collada image for these
- LibImages = new library_images();
- ColladaItems.Add(LibImages);
-
- var ImageList = new List<image>();
- var TexGroup = CurrentFile.GetGroup<Texture>("Textures(NW4R)");
-
- foreach (var texName in usedTextures) {
- var img = new image();
- var tex = TexGroup[texName];
-
- img.name = "Texture-" + texName;
- img.id = img.name;
- img.Item = "./images/" + texName + ".png";
-
- ImageList.Add(img);
- }
-
- LibImages.image = ImageList.ToArray();
-
- // Make a quick reference material for each one
- LibMaterials = new library_materials();
- ColladaItems.Add(LibMaterials);
-
- var MaterialList = new List<material>();
-
- foreach (var kv in CurrentModel.Materials) {
- var mat = new material();
-
- mat.name = "Material-" + kv.Key;
- mat.id = mat.name;
- mat.instance_effect = new instance_effect();
- mat.instance_effect.url = "#Material-Effect-" + kv.Key;
-
- MaterialList.Add(mat);
- }
-
- LibMaterials.material = MaterialList.ToArray();
-
- // Now create an effect for each material (this is where all the real work is done!)
- LibEffects = new library_effects();
- ColladaItems.Add(LibEffects);
-
- var EffectList = new List<effect>();
- foreach (var kv in CurrentModel.Materials) {
- EffectList.Add(CreateEffectFromMaterial(kv.Key, kv.Value));
- }
-
- LibEffects.effect = EffectList.ToArray();
-
- // Now shapes
- LibGeometries = new library_geometries();
- ColladaItems.Add(LibGeometries);
-
- var GeometryList = new List<geometry>();
- foreach (var kv in CurrentModel.Shapes) {
- GeometryList.Add(CreateGeometryFromShape(kv.Key, kv.Value));
- }
-
- LibGeometries.geometry = GeometryList.ToArray();
-
- // SHAPES ARE DONE.
- // Next up: Visual Scenes (I will just create one atm)
-
- LibVisualScenes = new library_visual_scenes();
- ColladaItems.Add(LibVisualScenes);
-
- LibVisualScenes.visual_scene = new visual_scene[1];
- var mainScene = LibVisualScenes.visual_scene[0] = new visual_scene();
-
- // TODO: Change this so it doesn't have the possibility of name collisions with shapes
- mainScene.id = "RootNode";
- mainScene.name = "RootNode";
- var mainSceneNodeList = new List<node>();
-
- // OK, so here's what's up: first off, we must create a definition for every node
- var NodeDefs = new Dictionary<Node, node>();
-
- foreach (var kv in CurrentModel.Nodes) {
- string nodeName = kv.Key;
- Node origNode = kv.Value;
- var cNode = new node();
-
- cNode.id = nodeName;
- cNode.name = nodeName;
- //cNode.type = NodeType.JOINT;
- cNode.node1 = new node[0];
-
- double cosX = Math.Cos(origNode.Rotation.x / 180 * Math.PI);
- double cosY = Math.Cos(origNode.Rotation.y / 180 * Math.PI);
- double cosZ = Math.Cos(origNode.Rotation.z / 180 * Math.PI);
- double sinX = Math.Sin(origNode.Rotation.x / 180 * Math.PI);
- double sinY = Math.Sin(origNode.Rotation.y / 180 * Math.PI);
- double sinZ = Math.Sin(origNode.Rotation.z / 180 * Math.PI);
-
- var nodeMatrix = new matrix();
- nodeMatrix.Values = new double[] {
- origNode.Scale.x * cosY * cosZ,
- origNode.Scale.y * (sinX * cosZ * sinY - cosX * sinZ),
- origNode.Scale.z * (sinX * sinZ + cosX * cosZ * sinY),
- origNode.Translation.x,
- origNode.Scale.x * sinZ * cosY,
- origNode.Scale.y * (sinX * sinZ * sinY + cosZ * cosX),
- origNode.Scale.z * (cosX * sinZ * sinY - sinX * cosZ),
- origNode.Translation.y,
- -origNode.Scale.x * sinY,
- origNode.Scale.y * sinX * cosY,
- origNode.Scale.z * cosX * cosY,
- origNode.Translation.z,
- 0, 0, 0, 1
- };
-
- cNode.Items = new object[] { nodeMatrix };
- cNode.ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.matrix };
-
- NodeDefs[origNode] = cNode;
- }
-
- // Now add them to the hierarchy
- foreach (var kv in NodeDefs) {
- Node origNode = kv.Key;
- node cNode = kv.Value;
-
- if (origNode.Parent == null) {
- mainSceneNodeList.Add(cNode);
- } else {
- var parentNode = NodeDefs[origNode.Parent];
-
- // this is stupid, thanks C#
- node[] nodeArrayCopy = parentNode.node1;
- Array.Resize<node>(ref nodeArrayCopy, nodeArrayCopy.Length + 1);
- nodeArrayCopy[nodeArrayCopy.Length - 1] = cNode;
- parentNode.node1 = nodeArrayCopy;
- }
- }
-
- // Apply shapes to nodes
- /*foreach (var kv in CurrentModel.Shapes) {
- Shape shape = kv.Value;
- Node origNode = CurrentModel.Nodes[CurrentModel.MatrixIDtoNodeID[shape.MatrixID]];
- node cNode = NodeDefs[origNode];
-
- var newGeoEntry = new instance_geometry();
- newGeoEntry.name = kv.Key;
- newGeoEntry.url = String.Format("#{0}-lib", kv.Key);
-
- instance_geometry[] geoArrayCopy = cNode.instance_geometry;
- if (geoArrayCopy == null)
- geoArrayCopy = new instance_geometry[1];
- else
- Array.Resize<instance_geometry>(ref geoArrayCopy, geoArrayCopy.Length + 1);
- geoArrayCopy[geoArrayCopy.Length - 1] = newGeoEntry;
- cNode.instance_geometry = geoArrayCopy;
-
- // TODO: Add material handling, I'll probably have to parse DrawOpa/DrawXlu for this...
- }*/
-
- // WARNING: THIS NEEDS REFACTORING
-
- int drawID = 0;
-
- foreach (var insn in CurrentModel.Bytecode["DrawOpa"].Instructions) {
- if (insn is ByteCode.DrawShapeInstruction) {
- var dsInsn = insn as ByteCode.DrawShapeInstruction;
-
- Shape shape = CurrentModel.Shapes[dsInsn.ShapeID];
- string shapeName = CurrentModel.Shapes.GetKeyForIndex(dsInsn.ShapeID);
-
- Node origNode = CurrentModel.Nodes[dsInsn.NodeID];
- node cNode = NodeDefs[origNode];
-
- Material mat = CurrentModel.Materials[dsInsn.MaterialID];
- string matName = CurrentModel.Materials.GetKeyForIndex(dsInsn.MaterialID);
-
- var newGeoEntry = new instance_geometry();
- newGeoEntry.name = String.Format("DrawOpa{0}-{1}", drawID, shapeName);
- newGeoEntry.url = String.Format("#{0}-lib", shapeName);
-
- // now add the material
- var bindMaterial = newGeoEntry.bind_material = new bind_material();
- bindMaterial.technique_common = new instance_material[1];
- var matTechnique = bindMaterial.technique_common[0] = new instance_material();
-
- // constant marker so that I don't have to set a unique material name in each primitive
- // it doesn't matter, since each geometry instance only uses one material anyway
- matTechnique.symbol = "NW4R_MATERIAL";
- matTechnique.target = "#Material-" + matName;
-
- matTechnique.bind_vertex_input = new instance_materialBind_vertex_input[1];
- matTechnique.bind_vertex_input[0] = new instance_materialBind_vertex_input();
- matTechnique.bind_vertex_input[0].semantic = "CHANNEL1";
- matTechnique.bind_vertex_input[0].input_semantic = "TEXCOORD";
- matTechnique.bind_vertex_input[0].input_set = 0;
-
- // ok, now add the instance_geometry into the node
- instance_geometry[] geoArrayCopy = cNode.instance_geometry;
- if (geoArrayCopy == null)
- geoArrayCopy = new instance_geometry[1];
- else
- Array.Resize<instance_geometry>(ref geoArrayCopy, geoArrayCopy.Length + 1);
- geoArrayCopy[geoArrayCopy.Length - 1] = newGeoEntry;
- cNode.instance_geometry = geoArrayCopy;
-
- drawID++;
- }
- }
-
- drawID = 0;
-
- foreach (var insn in CurrentModel.Bytecode["DrawXlu"].Instructions) {
- if (insn is ByteCode.DrawShapeInstruction) {
- var dsInsn = insn as ByteCode.DrawShapeInstruction;
-
- Shape shape = CurrentModel.Shapes[dsInsn.ShapeID];
- string shapeName = CurrentModel.Shapes.GetKeyForIndex(dsInsn.ShapeID);
-
- Node origNode = CurrentModel.Nodes[dsInsn.NodeID];
- node cNode = NodeDefs[origNode];
-
- Material mat = CurrentModel.Materials[dsInsn.MaterialID];
- string matName = CurrentModel.Materials.GetKeyForIndex(dsInsn.MaterialID);
-
- var newGeoEntry = new instance_geometry();
- newGeoEntry.name = String.Format("DrawXlu{0}-{1}", drawID, shapeName);
- newGeoEntry.url = String.Format("#{0}-lib", shapeName);
-
- // now add the material
- var bindMaterial = newGeoEntry.bind_material = new bind_material();
- bindMaterial.technique_common = new instance_material[1];
- var matTechnique = bindMaterial.technique_common[0] = new instance_material();
-
- // constant marker so that I don't have to set a unique material name in each primitive
- // it doesn't matter, since each geometry instance only uses one material anyway
- matTechnique.symbol = "NW4R_MATERIAL";
- matTechnique.target = "#Material-" + matName;
-
- matTechnique.bind_vertex_input = new instance_materialBind_vertex_input[1];
- matTechnique.bind_vertex_input[0] = new instance_materialBind_vertex_input();
- matTechnique.bind_vertex_input[0].semantic = "CHANNEL1";
- matTechnique.bind_vertex_input[0].input_semantic = "TEXCOORD";
- matTechnique.bind_vertex_input[0].input_set = 0;
-
- // ok, now add the instance_geometry into the node
- instance_geometry[] geoArrayCopy = cNode.instance_geometry;
- if (geoArrayCopy == null)
- geoArrayCopy = new instance_geometry[1];
- else
- Array.Resize<instance_geometry>(ref geoArrayCopy, geoArrayCopy.Length + 1);
- geoArrayCopy[geoArrayCopy.Length - 1] = newGeoEntry;
- cNode.instance_geometry = geoArrayCopy;
-
- drawID++;
- }
- }
-
-
- /*foreach (var kv in CurrentModel.Shapes) {
- var thisNode = new node();
-
- thisNode.id = kv.Key;
- thisNode.name = kv.Key;
- thisNode.instance_geometry = new instance_geometry[1];
- thisNode.instance_geometry[0] = new instance_geometry();
- thisNode.instance_geometry[0].url = String.Format("#{0}-lib", kv.Key);
-
- mainSceneNodeList.Add(thisNode);
- }*/
-
- mainScene.node = mainSceneNodeList.ToArray();
-
-
- // Finally, create a scene
- Collada.scene = new COLLADAScene();
- Collada.scene.instance_visual_scene = new InstanceWithExtra();
- Collada.scene.instance_visual_scene.url = "#RootNode";
-
- Collada.Items = ColladaItems.ToArray();
- Collada.Save(outputStream);
- }
-
-
-
- private effect CreateEffectFromMaterial(string name, Material mat) {
- var eff = new effect();
-
- 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
-
- profile.Items = new object[2];
-
- // create a surface newparam
- var surfaceParam = new common_newparam_type();
- var surface = new fx_surface_common();
-
- surface.type = fx_surface_type_enum.Item2D;
- surface.init_from = new fx_surface_init_from_common[1];
- surface.init_from[0] = new fx_surface_init_from_common();
- surface.init_from[0].Value = "Texture-" + mat.TextureInfos[0].TextureName;
-
- surfaceParam.sid = "Surface-" + mat.TextureInfos[0].TextureName;
- surfaceParam.ItemElementName = ItemChoiceType.surface;
- surfaceParam.Item = surface;
- profile.Items[0] = surfaceParam;
-
- // now create a sampler newparam
- 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;
- samplerParam.Item = sampler2d;
- profile.Items[1] = samplerParam;
-
- // now make a technique
- // should I really use blinn...?
- profile.technique = new effectFx_profile_abstractProfile_COMMONTechnique();
- profile.technique.sid = "common";
-
- var pShader = new effectFx_profile_abstractProfile_COMMONTechniquePhong();
- pShader.diffuse = new common_color_or_texture_type();
-
- var diffuseTex = new common_color_or_texture_typeTexture();
- diffuseTex.texture = "Sampler-" + mat.TextureInfos[0].TextureName;
- diffuseTex.texcoord = "CHANNEL1";
-
- 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;
- }
-
-
-
- private geometry CreateGeometryFromShape(string name, Shape shape) {
- var geo = new geometry();
-
- geo.id = name + "-lib";
- geo.name = name + "Mesh";
-
- var m = new mesh();
- geo.Item = m;
-
- // Vertex settings
- 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);
-
- // Figure out how many elements we need in the Source array
- // Position data ALWAYS exists
- int sourceCount = 1;
- sourceCount += (shape.NrmData != null) ? 1 : 0;
- for (int i = 0; i < 8; i++)
- sourceCount += (shape.TexCoordData[i] != null) ? 1 : 0;
-
- m.source = new source[sourceCount];
- int currentSource = 0;
-
- // TODO: Refactor this messy code!
-
- int dest;
-
- // Write position data
- var posData = shape.PosData;
- var posSource = new source();
- posSource.id = name + "-lib-Position";
- m.source[currentSource++] = posSource;
-
- var posArray = new float_array();
- posArray.id = name + "-lib-Position-array";
- posArray.count = (ulong)(posData.GetRealCount() * posData.EntryCount);
- posArray.Values = new double[posArray.count];
-
- dest = 0;
- for (int i = 0; i < posData.EntryCount; i++) {
- float[] data = posData.GetEntry(i);
- for (int j = 0; j < data.Length; j++) {
- posArray.Values[dest++] = data[j];
- }
- }
-
- posSource.Item = posArray;
-
- // Write position technique
- posSource.technique_common = new sourceTechnique_common();
- var posAcc = posSource.technique_common.accessor = new accessor();
- posAcc.source = String.Format("#{0}-lib-Position-array", name);
- posAcc.count = posData.EntryCount;
- posAcc.stride = (ulong)posData.GetRealCount();
-
- posAcc.param = new param[posData.GetRealCount()];
- string[] posParamNames = new string[] { "X", "Y", "Z" };
-
- for (int i = 0; i < posAcc.param.Length; i++) {
- posAcc.param[i] = new param();
- posAcc.param[i].name = posParamNames[i];
- posAcc.param[i].type = "float";
- }
-
-
- // Write normal data
- if (shape.NrmData != null) {
- var nrmData = shape.NrmData;
- var nrmSource = new source();
- nrmSource.id = name + "-lib-Normal";
- m.source[currentSource++] = nrmSource;
-
- var nrmArray = new float_array();
- nrmArray.id = name + "-lib-Normal-array";
- nrmArray.count = (ulong)(nrmData.GetRealCount() * nrmData.EntryCount);
- nrmArray.Values = new double[nrmArray.count];
-
- dest = 0;
- for (int i = 0; i < nrmData.EntryCount; i++) {
- float[] data = nrmData.GetEntry(i);
- for (int j = 0; j < data.Length; j++) {
- nrmArray.Values[dest++] = data[j];
- }
- }
-
- nrmSource.Item = nrmArray;
-
- // Write normal technique
- nrmSource.technique_common = new sourceTechnique_common();
- var nrmAcc = nrmSource.technique_common.accessor = new accessor();
- nrmAcc.source = String.Format("#{0}-lib-Normal-array", name);
- nrmAcc.count = nrmData.EntryCount;
- nrmAcc.stride = (ulong)nrmData.GetRealCount();
-
- nrmAcc.param = new param[nrmData.GetRealCount()];
- string[] nrmParamNames = new string[] { "X", "Y", "Z" };
-
- for (int i = 0; i < nrmAcc.param.Length; i++) {
- nrmAcc.param[i] = new param();
- nrmAcc.param[i].name = nrmParamNames[i];
- nrmAcc.param[i].type = "float";
- }
- }
-
-
- // Write TexCoord data
- for (int tcIndex = 0; tcIndex < 8; tcIndex++) {
- if (shape.TexCoordData[tcIndex] != null) {
- var tcData = shape.TexCoordData[tcIndex];
- var tcSource = new source();
- tcSource.id = String.Format("{0}-lib-TexCoord{1}", name, tcIndex);
- m.source[currentSource++] = tcSource;
-
- var tcArray = new float_array();
- tcArray.id = String.Format("{0}-lib-TexCoord{1}-array", name, tcIndex);
- tcArray.count = (ulong)(tcData.GetRealCount() * tcData.EntryCount);
- tcArray.Values = new double[tcArray.count];
-
- dest = 0;
- for (int i = 0; i < tcData.EntryCount; i++) {
- float[] data = tcData.GetEntry(i);
- for (int j = 0; j < data.Length; j++) {
- // flip T (Y axis) coordinate
- if (j == 1)
- tcArray.Values[dest++] = 1.0 - data[j];
- else
- tcArray.Values[dest++] = data[j];
- }
- }
-
- tcSource.Item = tcArray;
-
- // Write texcoord technique
- tcSource.technique_common = new sourceTechnique_common();
- var tcAcc = tcSource.technique_common.accessor = new accessor();
- tcAcc.source = String.Format("#{0}-lib-TexCoord{1}-array", name, tcIndex);
- tcAcc.count = tcData.EntryCount;
- tcAcc.stride = (ulong)tcData.GetRealCount();
-
- tcAcc.param = new param[tcData.GetRealCount()];
- string[] tcParamNames = new string[] { "S", "T" };
-
- for (int i = 0; i < tcAcc.param.Length; i++) {
- tcAcc.param[i] = new param();
- tcAcc.param[i].name = tcParamNames[i];
- tcAcc.param[i].type = "float";
- }
- }
- }
-
-
-
- // Ok, we've written all the raw float data, now set up vertices
- // TODO: Vertex colours
- m.vertices = new vertices();
- m.vertices.id = String.Format("{0}-lib-Vertex", name);
- m.vertices.input = new InputLocal[1];
- m.vertices.input[0] = new InputLocal();
- m.vertices.input[0].semantic = "POSITION";
- m.vertices.input[0].source = String.Format("#{0}-lib-Position", name);
-
- // And before we finish, write the polygon data of course
- var dl = new InputStream(shape.DisplayList2);
-
- List<object> meshItems = new List<object>();
-
- // create the Input array -- we can reuse sourceCount!
- var inputArray = new InputLocalOffset[sourceCount];
- currentSource = 0;
-
- var posInput = inputArray[currentSource] = new InputLocalOffset();
- posInput.semantic = "VERTEX";
- posInput.offset = (ulong)currentSource;
- posInput.source = String.Format("#{0}-lib-Vertex", name);
- currentSource++;
-
- if (shape.NrmData != null) {
- var nrmInput = inputArray[currentSource] = new InputLocalOffset();
- nrmInput.semantic = "NORMAL";
- nrmInput.offset = (ulong)currentSource;
- nrmInput.source = String.Format("#{0}-lib-Normal", name);
- currentSource++;
- }
-
- for (int i = 0; i < 8; i++) {
- if (shape.TexCoordData[i] != null) {
- var tcInput = inputArray[currentSource] = new InputLocalOffset();
- tcInput.semantic = "TEXCOORD";
- tcInput.offset = (ulong)currentSource;
- tcInput.@set = (ulong)i;
- tcInput.source = String.Format("#{0}-lib-TexCoord{1}", name, i);
- currentSource++;
- }
- }
-
-
- // Create a list for tristrips beforehand, because they're THE most common
- List<string> triStrips = new List<string>();
-
-
- // Now go through the display list
- 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];
- string[] pVtxs = new string[vtxCount];
-
- for (int i = 0; i < vtxCount; i++) {
- vtxs[i].LoadFrom(dl, vs);
-
- pVtxs[i] = vtxs[i].Position.ToString();
-
- if (vs.NormalDesc != VertexSettings.DescType.None)
- pVtxs[i] += " " + vtxs[i].Normal.ToString();
-
- for (int j = 0; j < 8; j++) {
- if (vs.TexCoordDesc[j] != VertexSettings.DescType.None) {
- pVtxs[i] += " " + vtxs[i].TexCoords[j].ToString();
- }
- }
- }
-
- switch (prim) {
- case PrimitiveType.Triangles:
- var pTri = new triangles();
- pTri.material = "NW4R_MATERIAL";
- pTri.count = (ulong)(vtxCount / 3);
- // should be 1? dunno
- pTri.input = inputArray;
-
- StringBuilder pTriData = new StringBuilder();
-
- for (int i = 0; i < vtxCount; i++) {
- pTriData.AppendFormat("{0} ", pVtxs[i]);
- }
-
-
- pTri.p = pTriData.ToString();
-
- meshItems.Add(pTri);
- break;
-
- case PrimitiveType.TriangleStrip:
- StringBuilder pTriStripData = new StringBuilder();
-
- for (int i = 0; i < vtxCount; i++) {
- pTriStripData.AppendFormat("{0} ", pVtxs[i]);
- }
-
-
- triStrips.Add(pTriStripData.ToString());
- break;
- default:
-
-
- Console.WriteLine("UNIMPLEMENTED PRIMITIVE TYPE");
- return geo;
- }
- }
-
-
- // If any tristrips were found, add them!
- if (triStrips.Count > 0) {
- var pTriStrips = new tristrips();
- pTriStrips.material = "NW4R_MATERIAL";
- pTriStrips.input = inputArray;
- pTriStrips.count = (ulong)triStrips.Count;
- pTriStrips.p = triStrips.ToArray();
- meshItems.Add(pTriStrips);
- }
-
-
- m.Items = meshItems.ToArray();
-
- // FINALLY DONE!
- return geo;
- }
- }
-}
-