public static void OptToObj(OptFile opt, string objPath, bool scale) { if (opt == null) { throw new ArgumentNullException("opt"); } string objDirectory = Path.GetDirectoryName(objPath); string objName = Path.GetFileNameWithoutExtension(objPath); var objMaterials = new ObjMaterialDictionary(); foreach (var texture in opt.Textures.Values) { var material = new ObjMaterial { Name = texture.Name, DiffuseMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}.png", texture.Name) }; texture.Save(Path.Combine(objDirectory, material.DiffuseMapFileName)); if (texture.HasAlpha) { material.AlphaMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}_alpha.png", texture.Name); texture.SaveAlphaMap(Path.Combine(objDirectory, material.AlphaMapFileName)); } objMaterials.Add(texture.Name, material); } objMaterials.Save(Path.ChangeExtension(objPath, "mtl")); var distances = opt.Meshes .SelectMany(t => t.Lods) .Select(t => t.Distance) .Distinct() .OrderByDescending(t => t) .ToArray(); for (int distance = 0; distance < distances.Length; distance++) { var obj = new ObjFile(); int objectsIndex = 0; int verticesIndex = 0; int verticesTexIndex = 0; int verticesNormalIndex = 0; foreach (var mesh in opt.Meshes) { var lod = mesh.Lods.FirstOrDefault(t => t.Distance <= distances[distance]); if (lod == null) { continue; } var objMesh = new ObjMesh(string.Format(CultureInfo.InvariantCulture, "{0}.{1:D3}", mesh.Descriptor.MeshType, objectsIndex)); obj.Meshes.Add(objMesh); objectsIndex++; if (scale) { foreach (var v in mesh.Vertices) { obj.Vertices.Add(new ObjVector3(v.X * OptFile.ScaleFactor, v.Z * OptFile.ScaleFactor, v.Y * OptFile.ScaleFactor)); } } else { foreach (var v in mesh.Vertices) { obj.Vertices.Add(new ObjVector3(v.X, v.Z, v.Y)); } } foreach (var v in mesh.TextureCoordinates) { obj.VertexTexCoords.Add(new ObjVector2(v.U, -v.V)); } foreach (var v in mesh.VertexNormals) { obj.VertexNormals.Add(new ObjVector3(v.X, v.Z, v.Y)); } foreach (var faceGroup in lod.FaceGroups) { var objFaceGroup = new ObjFaceGroup(); if (faceGroup.Textures.Count > 0) { objFaceGroup.MaterialName = faceGroup.Textures[0]; } objMesh.FaceGroups.Add(objFaceGroup); foreach (var face in faceGroup.Faces) { if (face.VerticesIndex.D < 0) { objFaceGroup.Faces.Add(new ObjFace() { VerticesIndex = new ObjIndex( verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C ), VertexTexCoordsIndex = new ObjIndex( verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C), VertexNormalsIndex = new ObjIndex( verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C) }); } else { objFaceGroup.Faces.Add(new ObjFace() { VerticesIndex = new ObjIndex( verticesIndex + face.VerticesIndex.A, verticesIndex + face.VerticesIndex.B, verticesIndex + face.VerticesIndex.C, verticesIndex + face.VerticesIndex.D ), VertexTexCoordsIndex = new ObjIndex( verticesTexIndex + face.TextureCoordinatesIndex.A, verticesTexIndex + face.TextureCoordinatesIndex.B, verticesTexIndex + face.TextureCoordinatesIndex.C, verticesTexIndex + face.TextureCoordinatesIndex.D), VertexNormalsIndex = new ObjIndex( verticesNormalIndex + face.VertexNormalsIndex.A, verticesNormalIndex + face.VertexNormalsIndex.B, verticesNormalIndex + face.VertexNormalsIndex.C, verticesNormalIndex + face.VertexNormalsIndex.D) }); } } } verticesIndex += mesh.Vertices.Count; verticesTexIndex += mesh.TextureCoordinates.Count; verticesNormalIndex += mesh.VertexNormals.Count; } obj.Save(Path.Combine(objDirectory, string.Format(CultureInfo.InvariantCulture, "{0}_{1}.obj", objName, distance)), objName); } }