public void ExportOBJ(string filename) { MDLBlock mdl;// = (Blocks[BlockHeader.MAGIC_MODEL3] ?? Blocks[BlockHeader.MAGIC_MODEL2]) as MDLBlock; if (Blocks.ContainsKey(BlockHeader.MAGIC_MODEL2)) { mdl = Blocks[BlockHeader.MAGIC_MODEL2] as MDLBlock; } else if (Blocks.ContainsKey(BlockHeader.MAGIC_MODEL3)) { mdl = Blocks[BlockHeader.MAGIC_MODEL3] as MDLBlock; } else { throw new Exception("No supported MDL block found."); } GeometryBlock geo;// = Blocks[BlockHeader.MAGIC_GEOMETRY2] as GeometryBlock; if (Blocks.ContainsKey(BlockHeader.MAGIC_GEOMETRY1)) { geo = Blocks[BlockHeader.MAGIC_GEOMETRY1] as GeometryBlock; } else if (Blocks.ContainsKey(BlockHeader.MAGIC_GEOMETRY2)) { geo = Blocks[BlockHeader.MAGIC_GEOMETRY2] as GeometryBlock; } else { throw new Exception("No supported GEO block found."); } using (StreamWriter matwriter = new StreamWriter(Path.ChangeExtension(filename, ".mtl"))) using (StreamWriter writer = new StreamWriter(filename)) { writer.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl"); int m = 0; int vertexOffset = 0; foreach (GeometryBlock.LOD lod in geo.LODs) { writer.WriteLine("g LOD" + lod.Type.ToString()); foreach (RenderGroup group in lod.RenderGroups) { // Write a new material MaterialProps mat = mdl.Materials[group.Material]; matwriter.WriteLine("newmtl " + Path.GetFileNameWithoutExtension(filename) + "_" + m); matwriter.WriteLine("Ka " + (mat.Ambient.X + mat.Emissive.X) + " " + (mat.Ambient.Y + mat.Emissive.Y) + " " + (mat.Ambient.Z + mat.Emissive.Z)); matwriter.WriteLine("Kd " + mat.Diffuse.X + " " + mat.Diffuse.Y + " " + mat.Diffuse.Z); matwriter.WriteLine("Ks " + mat.Specular.X + " " + mat.Specular.Y + " " + mat.Specular.Z); matwriter.WriteLine("Ns " + mat.Shininess); matwriter.WriteLine("d " + (1.0f - mat.Transparency)); foreach (TextureBlend blend in group.TextureBlends) { if (blend.Effect == Texture.MapType.Base) { matwriter.WriteLine("map_Kd " + Path.GetFileName(mdl.TextureReferences[blend.TextureIndex].MapName)); // Write Texture if (Program.Filesystem != null) { using (MemoryStream ms = new MemoryStream(Program.Filesystem.GetFileData(Program.Filesystem.GetFileEntry(mdl.TextureReferences[blend.TextureIndex].MapName.Replace(".tga", ".PC TEXTURE"))))) using (BinaryReader texReader = new BinaryReader(ms)) { Texture tex = new Texture(texReader); tex.DumpTGA(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(mdl.TextureReferences[blend.TextureIndex].MapName)) + ".tga"); } } } } writer.WriteLine("usemtl " + Path.GetFileNameWithoutExtension(filename) + "_" + m); writer.WriteLine("o LOD" + lod.Type.ToString() + "_group" + lod.RenderGroups.IndexOf(group)); // Write vertices for (int v = 0; v < group.VertexCount; v++) { writer.WriteLine("v " + (Context.Current.Game == Context.NextGenGame.LegoRacers2 ? -1.0f : 1.0f) * ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.PositionOffset) + " " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.PositionOffset + 4) + " " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.PositionOffset + 8)); writer.WriteLine("vn " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.NormalOffset) + " " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.NormalOffset + 4) + " " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.NormalOffset + 8)); writer.WriteLine("vt " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.UVOffset) + " " + ParseFloat(group.VertexBuffer.VertexData, v * (int)group.VertexBuffer.VertexSize + (int)group.VertexBuffer.UVOffset + 4)); } for (int i = 0; i < group.IndexBuffer.IndexCount; i += 3) { int i1 = BitConverter.ToUInt16(group.IndexBuffer.IndexData, i * 2) + vertexOffset + 1; int i2 = BitConverter.ToUInt16(group.IndexBuffer.IndexData, i * 2 + 2) + vertexOffset + 1; int i3 = BitConverter.ToUInt16(group.IndexBuffer.IndexData, i * 2 + 4) + vertexOffset + 1; /*if (Context.Current.Game == Context.NextGenGame.LegoRacers2) * { * // Flip the order of the indices * int temp = i1; * i1 = i2; * i2 = i3; * i3 = temp; * }*/ writer.WriteLine("f " + i1 + "/" + i1 + "/" + i1 + " " + i2 + "/" + i2 + "/" + i2 + " " + i3 + "/" + i3 + "/" + i3); } vertexOffset += group.VertexCount; m++; } } } }
public void ExportOBJ(string filename) { using (System.IO.StreamWriter objWriter = new StreamWriter(filename, false)) using (System.IO.StreamWriter mtlWriter = new StreamWriter(Path.ChangeExtension(filename, ".mtl"), false)) { objWriter.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl"); HashSet <string> writtenMaterials = new HashSet <string>(); int vertexOffset = 0; foreach (RenderGroup rg in this.RenderGroups) { TextureBlend baseTexture = rg.TextureBlends.First(tb => tb.Effect == Texture.MapType.Base); string texturePath = BitmapIndices[baseTexture.TextureIndex].MapName; string materialName = Path.GetFileNameWithoutExtension(texturePath); // Create the material if it's the first time it's being used if (!writtenMaterials.Contains(materialName)) { mtlWriter.WriteLine("newmtl " + materialName); MaterialProps mat = this.MaterialIndices[rg.Material]; mtlWriter.WriteLine("Ka " + (mat.Ambient.X + mat.Emissive.X) + " " + (mat.Ambient.Y + mat.Emissive.Y) + " " + (mat.Ambient.Z + mat.Emissive.Z)); mtlWriter.WriteLine("Kd " + mat.Diffuse.X + " " + mat.Diffuse.Y + " " + mat.Diffuse.Z); mtlWriter.WriteLine("Ks " + mat.Specular.X + " " + mat.Specular.Y + " " + mat.Specular.Z); mtlWriter.WriteLine("Ns " + mat.Shininess); mtlWriter.WriteLine("d " + (1.0f - mat.Transparency)); // Write Texture if (Program.Filesystem != null) { if (texturePath.EndsWith(".tga")) { mtlWriter.WriteLine("map_Kd " + Path.GetFileName(texturePath)); using (MemoryStream ms = new MemoryStream(Program.Filesystem.GetFileData(Program.Filesystem.GetFileEntry(texturePath.Replace(".tga", "." + Context.Current.Platform.ToString() + " TEXTURE"))))) using (BinaryReader texReader = new BinaryReader(ms)) { Texture tex = new Texture(texReader); tex.DumpTGA(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(texturePath)) + ".tga"); } } else if (texturePath.EndsWith(".ifl")) { using (MemoryStream iflMs = new MemoryStream(Program.Filesystem.GetFileData(Program.Filesystem.GetFileEntry(texturePath)))) { IFLFile ifl = new IFLFile(iflMs, texturePath); mtlWriter.WriteLine("map_Kd " + Path.GetFileName(ifl.Frames[0].TextureFilename)); using (MemoryStream ms = new MemoryStream(Program.Filesystem.GetFileData(Program.Filesystem.GetFileEntry(Path.Combine(Path.GetDirectoryName(texturePath), ifl.Frames[0].TextureFilename.Replace(".tga", "." + Context.Current.Platform.ToString() + " TEXTURE")))))) using (BinaryReader texReader = new BinaryReader(ms)) { Texture tex = new Texture(texReader); tex.DumpTGA(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(ifl.Frames[0].TextureFilename)) + ".tga"); } } } } } objWriter.WriteLine("usemtl " + materialName); // Write vertices for (int v = 0; v < rg.VertexCount; v++) { objWriter.WriteLine("v " + (Context.Current.Game == Context.NextGenGame.LegoRacers2 ? -1.0f : -1.0f) * ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.PositionOffset) + " " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.PositionOffset + 4) + " " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.PositionOffset + 8)); objWriter.WriteLine("vn " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.NormalOffset) + " " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.NormalOffset + 4) + " " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.NormalOffset + 8)); objWriter.WriteLine("vt " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.UVOffset) + " " + ParseFloat(rg.VertexBuffer.VertexData, v * (int)rg.VertexBuffer.VertexSize + (int)rg.VertexBuffer.UVOffset + 4)); } for (int i = 0; i < rg.IndexBuffer.IndexCount; i += 3) { int i1 = BitConverter.ToUInt16(rg.IndexBuffer.IndexData, i * 2) + vertexOffset + 1; int i2 = BitConverter.ToUInt16(rg.IndexBuffer.IndexData, i * 2 + 2) + vertexOffset + 1; int i3 = BitConverter.ToUInt16(rg.IndexBuffer.IndexData, i * 2 + 4) + vertexOffset + 1; /*if (Context.Current.Game == Context.NextGenGame.LegoRacers2) * { * // Flip the order of the indices * int temp = i1; * i1 = i2; * i2 = i3; * i3 = temp; * }*/ objWriter.WriteLine("f " + i1 + "/" + i1 + "/" + i1 + " " + i2 + "/" + i2 + "/" + i2 + " " + i3 + "/" + i3 + "/" + i3); } vertexOffset += rg.VertexCount; } } }