diff options
author | Treeki <treeki@gmail.com> | 2011-03-10 03:00:09 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2011-03-10 03:00:09 +0100 |
commit | 5926616de2bd346f1a1c69c93ff2aaa3c453a2b3 (patch) | |
tree | f282b05ae5616a05fb4db167fad20ec242775c27 /NW4RTools | |
parent | 7d391e33a0b3d9793c95fce832abb2c6d9002186 (diff) | |
download | nw4rtools-5926616de2bd346f1a1c69c93ff2aaa3c453a2b3.tar.gz nw4rtools-5926616de2bd346f1a1c69c93ff2aaa3c453a2b3.zip |
kinda hackish, but mostly working NSMBW lightmap support
Diffstat (limited to 'NW4RTools')
-rw-r--r-- | NW4RTools/ColladaExporter.cs | 72 | ||||
-rw-r--r-- | NW4RTools/ColladaWriter.cs | 732 | ||||
-rw-r--r-- | NW4RTools/Models/OpenGL/GLModel.cs | 2 | ||||
-rw-r--r-- | NW4RTools/NW4RTools.pidb | bin | 579951 -> 582467 bytes | |||
-rwxr-xr-x | NW4RTools/ObjImporter.cs | 309 | ||||
-rw-r--r-- | NW4RTools/ObjWriter.cs | 187 | ||||
-rwxr-xr-x | NW4RTools/bin/Debug/NW4RTools.dll | bin | 235008 -> 235008 bytes | |||
-rw-r--r-- | NW4RTools/bin/Debug/NW4RTools.dll.mdb | bin | 113704 -> 113949 bytes |
8 files changed, 256 insertions, 1046 deletions
diff --git a/NW4RTools/ColladaExporter.cs b/NW4RTools/ColladaExporter.cs index f18bfed..cd5aaf1 100644 --- a/NW4RTools/ColladaExporter.cs +++ b/NW4RTools/ColladaExporter.cs @@ -264,50 +264,52 @@ namespace NW4RTools { } drawID = 0; - - foreach (var insn in CurrentModel.Bytecode["DrawXlu"].Instructions) { - if (insn is ByteCode.DrawShapeInstruction) { - var dsInsn = insn as ByteCode.DrawShapeInstruction; + + if (CurrentModel.Bytecode.ContainsKey("DrawXlu")) { + 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); + Shape shape = CurrentModel.Shapes[dsInsn.ShapeID]; + string shapeName = CurrentModel.Shapes.GetKeyForIndex(dsInsn.ShapeID); - Node origNode = CurrentModel.Nodes[dsInsn.NodeID]; - node cNode = NodeDefs[origNode]; + Node origNode = CurrentModel.Nodes[dsInsn.NodeID]; + node cNode = NodeDefs[origNode]; - Material mat = CurrentModel.Materials[dsInsn.MaterialID]; - string matName = CurrentModel.Materials.GetKeyForIndex(dsInsn.MaterialID); + 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); + 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(); + // 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; + // 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; + 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; + // 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++; + } } } 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; - } - } -} - diff --git a/NW4RTools/Models/OpenGL/GLModel.cs b/NW4RTools/Models/OpenGL/GLModel.cs index 18e5f6f..7de560e 100644 --- a/NW4RTools/Models/OpenGL/GLModel.cs +++ b/NW4RTools/Models/OpenGL/GLModel.cs @@ -215,7 +215,7 @@ namespace NW4RTools.Models.OpenGL { GL.BindTexture(TextureTarget.Texture2D, 0); } else { BindTextureInfo(texInfoArray[i]); - GL.Enable(EnableCap.Texture2D); + //GL.Enable(EnableCap.Texture2D); } } diff --git a/NW4RTools/NW4RTools.pidb b/NW4RTools/NW4RTools.pidb Binary files differindex e7aef3c..6bd6989 100644 --- a/NW4RTools/NW4RTools.pidb +++ b/NW4RTools/NW4RTools.pidb diff --git a/NW4RTools/ObjImporter.cs b/NW4RTools/ObjImporter.cs index 81fcf81..1606028 100755 --- a/NW4RTools/ObjImporter.cs +++ b/NW4RTools/ObjImporter.cs @@ -239,86 +239,165 @@ namespace NW4RTools { // Create a new material and initialise everything
// Default settings taken from Test_Lift material
currentMaterial = new Material();
-
- currentMaterial.TexCoordGenCount = 1;
- currentMaterial.ChanCount = 1;
- currentMaterial.TevStageCount = 2;
- currentMaterial.IndStageCount = 0;
-
- // This might need changing
- currentMaterial.CullMode = 2;
-
- currentMaterial.SRTSettings[0] = new SRTSettingInfo();
-
- currentMaterial.ChanCtrls[0] = new ChanCtrl();
- currentMaterial.ChanCtrls[0].Flags = 0x3F;
- currentMaterial.ChanCtrls[0].MatColor.Rgba = 0xFFFFFFFF;
- currentMaterial.ChanCtrls[0].AmbColor.Rgba = 0xFFFFFFFF;
- currentMaterial.ChanCtrls[0].FlagC = 0x702;
- currentMaterial.ChanCtrls[0].FlagA = 0x700;
-
- currentMaterial.ChanCtrls[1] = new ChanCtrl();
- currentMaterial.ChanCtrls[1].Flags = 0xF;
- currentMaterial.ChanCtrls[1].MatColor.Rgba = 0x000000FF;
- currentMaterial.ChanCtrls[1].AmbColor.Rgba = 0x00000000;
- currentMaterial.ChanCtrls[1].FlagC = 0;
+ + currentMaterial.ChanCtrls[0] = new ChanCtrl(); + currentMaterial.ChanCtrls[0].Flags = 0x3F; + currentMaterial.ChanCtrls[0].MatColor.Rgba = 0xFFFFFFFF; + currentMaterial.ChanCtrls[0].AmbColor.Rgba = 0xFFFFFFFF; + currentMaterial.ChanCtrls[0].FlagC = Lightmaps ? (uint)0x701 : (uint)0x702; + currentMaterial.ChanCtrls[0].FlagA = 0x700; + + currentMaterial.ChanCtrls[1] = new ChanCtrl(); + currentMaterial.ChanCtrls[1].Flags = 0xF; + currentMaterial.ChanCtrls[1].MatColor.Rgba = 0x000000FF; + currentMaterial.ChanCtrls[1].AmbColor.Rgba = 0x00000000; + currentMaterial.ChanCtrls[1].FlagC = 0; currentMaterial.ChanCtrls[1].FlagA = 0; - currentMaterial.LightSetID = 1;
+ if (!Lightmaps) {
+ currentMaterial.TexCoordGenCount = 1;
+ currentMaterial.ChanCount = 1;
+ currentMaterial.TevStageCount = 2;
+ currentMaterial.IndStageCount = 0;
+
+ // This might need changing
+ currentMaterial.CullMode = 2;
+ + currentMaterial.LightSetID = 1; + + currentMaterial.SRTSettings[0] = new SRTSettingInfo();
- // Default display lists, taken from test_lift
- var pixDL = new DisplayListWriter(); - pixDL.LoadBPReg(0xF31EFF80); - pixDL.LoadBPReg(0x40000017); - pixDL.LoadBPReg(0xFE00FFE3); - pixDL.LoadBPReg(0x410034A0); - pixDL.LoadBPReg(0x42000000); - pixDL.End(); - - currentMaterial.PixDL = pixDL.GetBuffer(); - - var tevColorDL = new DisplayListWriter(); - tevColorDL.LoadBPReg(0xE20000FF); - tevColorDL.LoadBPReg(0xE30FF0FF); - tevColorDL.LoadBPReg(0xE30FF0FF); - tevColorDL.LoadBPReg(0xE30FF0FF); - tevColorDL.LoadBPReg(0xE4000000); - tevColorDL.LoadBPReg(0xE5000000); - tevColorDL.LoadBPReg(0xE5000000); - tevColorDL.LoadBPReg(0xE5000000); - tevColorDL.LoadBPReg(0xE6000000); - tevColorDL.LoadBPReg(0xE7000000); - tevColorDL.LoadBPReg(0xE7000000); - tevColorDL.LoadBPReg(0xE7000000); - tevColorDL.AddPadding(4); - tevColorDL.LoadBPReg(0xE0800000); - tevColorDL.LoadBPReg(0xE1800000); - tevColorDL.LoadBPReg(0xE2800000); - tevColorDL.LoadBPReg(0xE3800000); - tevColorDL.LoadBPReg(0xE4800000); - tevColorDL.LoadBPReg(0xE5800000); - tevColorDL.LoadBPReg(0xE6800000); - tevColorDL.LoadBPReg(0xE7800000); - tevColorDL.AddPadding(24); - tevColorDL.End(); - - currentMaterial.TevColorDL = tevColorDL.GetBuffer(); - - var indMtxAndScaleDL = new DisplayListWriter(); - indMtxAndScaleDL.LoadBPReg(0x25000000); - indMtxAndScaleDL.LoadBPReg(0x26000000); - indMtxAndScaleDL.AddPadding(54); - indMtxAndScaleDL.End(); - - currentMaterial.IndMtxAndScaleDL = indMtxAndScaleDL.GetBuffer(); - - var texCoordGenDL = new DisplayListWriter(); - texCoordGenDL.LoadXFReg(0x1040, new byte[] { 0x00, 0x00, 0x52, 0x80 }); - texCoordGenDL.LoadXFReg(0x1050, new byte[] { 0x00, 0x00, 0x00, 0x00 }); - texCoordGenDL.AddPadding(110); - texCoordGenDL.End(); - - currentMaterial.TexCoordGenDL = texCoordGenDL.GetBuffer(); + // Default display lists, taken from test_lift
+ var pixDL = new DisplayListWriter(); + pixDL.LoadBPReg(0xF31EFF80); + pixDL.LoadBPReg(0x40000017); + pixDL.LoadBPReg(0xFE00FFE3); + pixDL.LoadBPReg(0x410034A0); + pixDL.LoadBPReg(0x42000000); + pixDL.End(); + + currentMaterial.PixDL = pixDL.GetBuffer(); + + var tevColorDL = new DisplayListWriter(); + tevColorDL.LoadBPReg(0xE20000FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE30FF0FF); + tevColorDL.LoadBPReg(0xE4000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE6000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.AddPadding(4); + tevColorDL.LoadBPReg(0xE0800000); + tevColorDL.LoadBPReg(0xE1800000); + tevColorDL.LoadBPReg(0xE2800000); + tevColorDL.LoadBPReg(0xE3800000); + tevColorDL.LoadBPReg(0xE4800000); + tevColorDL.LoadBPReg(0xE5800000); + tevColorDL.LoadBPReg(0xE6800000); + tevColorDL.LoadBPReg(0xE7800000); + tevColorDL.AddPadding(24); + tevColorDL.End(); + + currentMaterial.TevColorDL = tevColorDL.GetBuffer(); + + var indMtxAndScaleDL = new DisplayListWriter(); + indMtxAndScaleDL.LoadBPReg(0x25000000); + indMtxAndScaleDL.LoadBPReg(0x26000000); + indMtxAndScaleDL.AddPadding(54); + indMtxAndScaleDL.End(); + + currentMaterial.IndMtxAndScaleDL = indMtxAndScaleDL.GetBuffer(); + + var texCoordGenDL = new DisplayListWriter(); + texCoordGenDL.LoadXFReg(0x1040, new byte[] { 0x00, 0x00, 0x52, 0x80 }); + texCoordGenDL.LoadXFReg(0x1050, new byte[] { 0x00, 0x00, 0x00, 0x00 }); + texCoordGenDL.AddPadding(110); + texCoordGenDL.End(); + + currentMaterial.TexCoordGenDL = texCoordGenDL.GetBuffer(); + + } else { + // These are taken from mtSand on CS_W1 + currentMaterial.TexCoordGenCount = 3; + currentMaterial.ChanCount = 1; + currentMaterial.TevStageCount = 3; + currentMaterial.IndStageCount = 0; + + currentMaterial.CullMode = 2; + + currentMaterial.ZCompLoc = 1; + currentMaterial.LightSetID = 0xFF; + currentMaterial.FogID = 1; + + currentMaterial.SRTSettings[0] = new SRTSettingInfo(); + currentMaterial.SRTSettings[1] = new SRTSettingInfo(); + currentMaterial.SRTSettings[2] = new SRTSettingInfo(); + + currentMaterial.SRTSettings[1].MapType = 1; + currentMaterial.SRTSettings[2].MapType = 1; + + var pixDL = new DisplayListWriter(); + pixDL.LoadBPReg(0xF33F0000); + pixDL.LoadBPReg(0x40000017); + pixDL.LoadBPReg(0xFE00FFE3); + pixDL.LoadBPReg(0x410034A0); + pixDL.LoadBPReg(0x42000000); + pixDL.End(); + + currentMaterial.PixDL = pixDL.GetBuffer(); + + var tevColorDL = new DisplayListWriter(); + tevColorDL.LoadBPReg(0xE2000000); + tevColorDL.LoadBPReg(0xE3000000); + tevColorDL.LoadBPReg(0xE3000000); + tevColorDL.LoadBPReg(0xE3000000); + tevColorDL.LoadBPReg(0xE4000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE5000000); + tevColorDL.LoadBPReg(0xE6000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.LoadBPReg(0xE7000000); + tevColorDL.AddPadding(4); + tevColorDL.LoadBPReg(0xE0800000); + tevColorDL.LoadBPReg(0xE1800000); + tevColorDL.LoadBPReg(0xE2800000); + tevColorDL.LoadBPReg(0xE3800000); + tevColorDL.LoadBPReg(0xE4800000); + tevColorDL.LoadBPReg(0xE5800000); + tevColorDL.LoadBPReg(0xE68FF000); + tevColorDL.LoadBPReg(0xE7800000); + tevColorDL.AddPadding(24); + tevColorDL.End(); + + currentMaterial.TevColorDL = tevColorDL.GetBuffer(); + + var indMtxAndScaleDL = new DisplayListWriter(); + indMtxAndScaleDL.LoadBPReg(0x25000000); + indMtxAndScaleDL.LoadBPReg(0x26000000); + indMtxAndScaleDL.AddPadding(54); + indMtxAndScaleDL.End(); + + currentMaterial.IndMtxAndScaleDL = indMtxAndScaleDL.GetBuffer(); + + var texCoordGenDL = new DisplayListWriter(); + texCoordGenDL.LoadXFReg(0x1040, new byte[] { 0x00, 0x00, 0x52, 0x80 }); + texCoordGenDL.LoadXFReg(0x1050, new byte[] { 0x00, 0x00, 0x00, 0x00 }); + texCoordGenDL.LoadXFReg(0x1041, new byte[] { 0x00, 0x00, 0x50, 0x86 }); + texCoordGenDL.LoadXFReg(0x1051, new byte[] { 0x00, 0x00, 0x01, 0x03 }); + texCoordGenDL.LoadXFReg(0x1042, new byte[] { 0x00, 0x00, 0x50, 0x86 }); + texCoordGenDL.LoadXFReg(0x1052, new byte[] { 0x00, 0x00, 0x01, 0x06 }); + texCoordGenDL.PadToSize(0xA0); + texCoordGenDL.End(); + + currentMaterial.TexCoordGenDL = texCoordGenDL.GetBuffer(); + } CurrentModel.Materials.Add(parsed[1], currentMaterial); @@ -348,6 +427,26 @@ namespace NW4RTools { texInfo.MagFilt = 1; currentMaterial.TextureInfos.Add(texInfo); + + // Now add the lm_01m and lm_02m + var lm01m = new TextureInfo(); + lm01m.TextureName = "lm_01m"; + lm01m.TexMapID = 1; + lm01m.TlutID = 1; + + lm01m.MinFilt = 1; + lm01m.MagFilt = 1; + + var lm02m = new TextureInfo(); + lm02m.TextureName = "lm_02m"; + lm02m.TexMapID = 2; + lm02m.TlutID = 2; + + lm02m.MinFilt = 1; + lm02m.MagFilt = 1; + + currentMaterial.TextureInfos.Add(lm01m); + currentMaterial.TextureInfos.Add(lm02m); break;
@@ -373,12 +472,8 @@ namespace NW4RTools { private Shader CreateShader() { var shader = new Shader(); - - shader.TevStageCount = 2; - shader.Unk1 = 0x00FFFFFF; - shader.Unk2 = 0xFFFFFFFF; - var dl = new DisplayListWriter(); + dl.LoadBPReg(0xFE00000F); dl.LoadBPReg(0xF6000004); dl.LoadBPReg(0xFE00000F); @@ -397,15 +492,47 @@ namespace NW4RTools { dl.LoadBPReg(0xFD00000E); dl.LoadBPReg(0x27FFFFFF); dl.AddPadding(11); - dl.LoadBPReg(0xFEFFFFF0); - dl.LoadBPReg(0xF6E338C0); - dl.LoadBPReg(0x2803F040); - dl.LoadBPReg(0xC008F8AF); - dl.LoadBPReg(0xC208F20F); - dl.LoadBPReg(0xC108F2F0); - dl.LoadBPReg(0xC3081FF0); - dl.LoadBPReg(0x10000000); - dl.LoadBPReg(0x11000000); + + if (!Lightmaps) { + shader.TevStageCount = 2; + shader.Unk1 = 0x00FFFFFF; + shader.Unk2 = 0xFFFFFFFF; + + dl.LoadBPReg(0xFEFFFFF0); + dl.LoadBPReg(0xF6E338C0); + dl.LoadBPReg(0x2803F040); + dl.LoadBPReg(0xC008F8AF); + dl.LoadBPReg(0xC208F20F); + dl.LoadBPReg(0xC108F2F0); + dl.LoadBPReg(0xC3081FF0); + dl.LoadBPReg(0x10000000); + dl.LoadBPReg(0x11000000); + + } else { + shader.TevStageCount = 3; + shader.Unk1 = 0x000102FF; + shader.Unk2 = 0xFFFFFFFF; + + dl.LoadBPReg(0xFEFFFFF0); + dl.LoadBPReg(0xF6E338C0); + dl.LoadBPReg(0x283C0049); + dl.LoadBPReg(0xC008F8AF); + dl.LoadBPReg(0xC208F80F); + dl.LoadBPReg(0xC108FFD0); + dl.LoadBPReg(0xC308E270); + dl.LoadBPReg(0x10000000); + dl.LoadBPReg(0x11000000); + dl.AddPadding(3); + dl.LoadBPReg(0xFEFFFFF0); + dl.LoadBPReg(0xF7003EF0); + dl.LoadBPReg(0x293BF052); + dl.LoadBPReg(0xC4080A8E); + dl.AddPadding(5); + dl.LoadBPReg(0xC508E370); + dl.AddPadding(5); + dl.LoadBPReg(0x12000000); + } + dl.PadToSize(0x1E0); dl.End(); diff --git a/NW4RTools/ObjWriter.cs b/NW4RTools/ObjWriter.cs deleted file mode 100644 index 592347b..0000000 --- a/NW4RTools/ObjWriter.cs +++ /dev/null @@ -1,187 +0,0 @@ -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) { - // first, parse the first DisplayList to get the attr info - // for now we'll hardcode the offsets. must be fixed later - - 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); - - // get the Matrix to use - // todo: how to apply this?! - Matrix m = CurrentModel.Nodes[CurrentModel.MatrixIDtoNodeID[shape.MatrixID]].NodeMatrix; - - // now parse the second 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(); - if (cmd == 0) - break; - - PrimitiveType prim = (PrimitiveType)((cmd >> 3) & 7); - int vtxCount = dl.ReadUInt16(); - Output.WriteLine("# Primitive: {0} ({1} vertices)", prim, vtxCount); - - // 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); - - string tc = (vtxs[i].TexCoords[0] == -1) ? "" : (tcOffset + vtxs[i].TexCoords[0]).ToString(); - string n = (vtxs[i].Normal == -1) ? "" : (nrmOffset + vtxs[i].Normal).ToString(); - pVtxs[i] = String.Format(" {0}/{1}/{2}", posOffset + vtxs[i].Position, tc, n); - } - - switch (prim) { - case PrimitiveType.Triangles: - for (int i = 0; i < vtxCount; i += 3) { - Output.WriteLine("f {0} {1} {2}", pVtxs[i], pVtxs[i + 1], pVtxs[i + 2]); - } - - break; - - case PrimitiveType.TriangleStrip: - // De-stripify it! - for (int i = 2; i < vtxCount; i++) { - Output.Write("f"); - if ((i & 1) == 0) { - // Even number - Output.Write(pVtxs[i - 2]); - Output.Write(pVtxs[i - 1]); - Output.Write(pVtxs[i]); - } else { - // Odd number - Output.Write(pVtxs[i - 1]); - Output.Write(pVtxs[i - 2]); - Output.Write(pVtxs[i]); - } - Output.WriteLine(); - } - - break; - - default: - Output.WriteLine("# UNIMPLEMENTED"); - return; - } - } - } - } -} - diff --git a/NW4RTools/bin/Debug/NW4RTools.dll b/NW4RTools/bin/Debug/NW4RTools.dll Binary files differindex 497cebb..d8f19a2 100755 --- a/NW4RTools/bin/Debug/NW4RTools.dll +++ b/NW4RTools/bin/Debug/NW4RTools.dll diff --git a/NW4RTools/bin/Debug/NW4RTools.dll.mdb b/NW4RTools/bin/Debug/NW4RTools.dll.mdb Binary files differindex e36c23e..330c38e 100644 --- a/NW4RTools/bin/Debug/NW4RTools.dll.mdb +++ b/NW4RTools/bin/Debug/NW4RTools.dll.mdb |