using System; using System.Collections.Generic; using System.IO; namespace Oni.Akira { internal class RoomExtractor { private readonly IEnumerable fromFiles; private readonly string outputFilePath; private PolygonMesh mesh; private List positions; private Stack nodeTransformStack; private Matrix nodeTransform; private string nodeName; public RoomExtractor(IEnumerable fromFiles, string outputFilePath) { this.fromFiles = fromFiles; this.outputFilePath = outputFilePath; } public void Extract() { mesh = new PolygonMesh(new MaterialLibrary()); positions = mesh.Points; nodeTransformStack = new Stack(); nodeTransform = Matrix.Identity; foreach (var filePath in fromFiles) ReadScene(Dae.Reader.ReadFile(filePath)); var q = new PolygonQuadrangulate(mesh); q.Execute(); RoomDaeWriter.Write(mesh, outputFilePath); } private void ReadScene(Dae.Scene scene) { foreach (var node in scene.Nodes) ReadNode(node); } private void ReadNode(Dae.Node node) { nodeTransformStack.Push(nodeTransform); foreach (var transform in node.Transforms) nodeTransform = transform.ToMatrix() * nodeTransform; nodeName = node.Name; foreach (var geometryInstance in node.GeometryInstances) ReadGeometryInstance(geometryInstance); foreach (var child in node.Nodes) ReadNode(child); nodeTransform = nodeTransformStack.Pop(); } private void ReadGeometryInstance(Dae.GeometryInstance instance) { foreach (var primitives in instance.Target.Primitives) { if (primitives.PrimitiveType != Dae.MeshPrimitiveType.Polygons) { Console.Error.WriteLine("Unsupported primitive type '{0}' found in geometry '{1}', ignoring.", primitives.PrimitiveType, instance.Name); continue; } ReadPolygonPrimitives(primitives, instance.Materials.Find(m => m.Symbol == primitives.MaterialSymbol)); } } private void ReadPolygonPrimitives(Dae.MeshPrimitives primitives, Dae.MaterialInstance materialInstance) { int[] positionIndices = null; foreach (var input in primitives.Inputs) { switch (input.Semantic) { case Dae.Semantic.Position: positionIndices = ReadInputIndexed(input, positions, Dae.Source.ReadVector3); break; } } foreach (int i in positionIndices) positions[i] = Vector3.Transform(positions[i], ref nodeTransform); int startIndex = 0; foreach (int vertexCount in primitives.VertexCounts) { var polygonPointIndices = new int[vertexCount]; Array.Copy(positionIndices, startIndex, polygonPointIndices, 0, vertexCount); var polygon = new Polygon(mesh, polygonPointIndices); if (Vector3.Dot(polygon.Plane.Normal, Vector3.UnitY) >= 0.3420201f) mesh.Polygons.Add(polygon); startIndex += vertexCount; } } private static int[] ReadInputIndexed(Dae.IndexedInput input, List list, Func elementReader) where T : struct { var indices = new int[input.Indices.Count]; for (int i = 0; i < input.Indices.Count; i++) { var v = elementReader(input.Source, input.Indices[i]); indices[i] = list.Count; list.Add(v); } return indices; } } }