| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 |  | 
 
 
 
 
 | 5 | namespace Oni.Akira | 
 
 
 
 
 | 6 | { | 
 
 
 
 
 | 7 | internal class RoomExtractor | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | private readonly IEnumerable<string> fromFiles; | 
 
 
 
 
 | 10 | private readonly string outputFilePath; | 
 
 
 
 
 | 11 |  | 
 
 
 
 
 | 12 | private PolygonMesh mesh; | 
 
 
 
 
 | 13 | private List<Vector3> positions; | 
 
 
 
 
 | 14 | private Stack<Matrix> nodeTransformStack; | 
 
 
 
 
 | 15 | private Matrix nodeTransform; | 
 
 
 
 
 | 16 | private string nodeName; | 
 
 
 
 
 | 17 |  | 
 
 
 
 
 | 18 | public RoomExtractor(IEnumerable<string> fromFiles, string outputFilePath) | 
 
 
 
 
 | 19 | { | 
 
 
 
 
 | 20 | this.fromFiles = fromFiles; | 
 
 
 
 
 | 21 | this.outputFilePath = outputFilePath; | 
 
 
 
 
 | 22 | } | 
 
 
 
 
 | 23 |  | 
 
 
 
 
 | 24 | public void Extract() | 
 
 
 
 
 | 25 | { | 
 
 
 
 
 | 26 | mesh = new PolygonMesh(new MaterialLibrary()); | 
 
 
 
 
 | 27 |  | 
 
 
 
 
 | 28 | positions = mesh.Points; | 
 
 
 
 
 | 29 |  | 
 
 
 
 
 | 30 | nodeTransformStack = new Stack<Matrix>(); | 
 
 
 
 
 | 31 | nodeTransform = Matrix.Identity; | 
 
 
 
 
 | 32 |  | 
 
 
 
 
 | 33 | foreach (var filePath in fromFiles) | 
 
 
 
 
 | 34 | ReadScene(Dae.Reader.ReadFile(filePath)); | 
 
 
 
 
 | 35 |  | 
 
 
 
 
 | 36 | var q = new PolygonQuadrangulate(mesh); | 
 
 
 
 
 | 37 | q.Execute(); | 
 
 
 
 
 | 38 |  | 
 
 
 
 
 | 39 | RoomDaeWriter.Write(mesh, outputFilePath); | 
 
 
 
 
 | 40 | } | 
 
 
 
 
 | 41 |  | 
 
 
 
 
 | 42 | private void ReadScene(Dae.Scene scene) | 
 
 
 
 
 | 43 | { | 
 
 
 
 
 | 44 | foreach (var node in scene.Nodes) | 
 
 
 
 
 | 45 | ReadNode(node); | 
 
 
 
 
 | 46 | } | 
 
 
 
 
 | 47 |  | 
 
 
 
 
 | 48 | private void ReadNode(Dae.Node node) | 
 
 
 
 
 | 49 | { | 
 
 
 
 
 | 50 | nodeTransformStack.Push(nodeTransform); | 
 
 
 
 
 | 51 |  | 
 
 
 
 
 | 52 | foreach (var transform in node.Transforms) | 
 
 
 
 
 | 53 | nodeTransform = transform.ToMatrix() * nodeTransform; | 
 
 
 
 
 | 54 |  | 
 
 
 
 
 | 55 | nodeName = node.Name; | 
 
 
 
 
 | 56 |  | 
 
 
 
 
 | 57 | foreach (var geometryInstance in node.GeometryInstances) | 
 
 
 
 
 | 58 | ReadGeometryInstance(geometryInstance); | 
 
 
 
 
 | 59 |  | 
 
 
 
 
 | 60 | foreach (var child in node.Nodes) | 
 
 
 
 
 | 61 | ReadNode(child); | 
 
 
 
 
 | 62 |  | 
 
 
 
 
 | 63 | nodeTransform = nodeTransformStack.Pop(); | 
 
 
 
 
 | 64 | } | 
 
 
 
 
 | 65 |  | 
 
 
 
 
 | 66 | private void ReadGeometryInstance(Dae.GeometryInstance instance) | 
 
 
 
 
 | 67 | { | 
 
 
 
 
 | 68 | foreach (var primitives in instance.Target.Primitives) | 
 
 
 
 
 | 69 | { | 
 
 
 
 
 | 70 | if (primitives.PrimitiveType != Dae.MeshPrimitiveType.Polygons) | 
 
 
 
 
 | 71 | { | 
 
 
 
 
 | 72 | Console.Error.WriteLine("Unsupported primitive type '{0}' found in geometry '{1}', ignoring.", primitives.PrimitiveType, instance.Name); | 
 
 
 
 
 | 73 | continue; | 
 
 
 
 
 | 74 | } | 
 
 
 
 
 | 75 |  | 
 
 
 
 
 | 76 | ReadPolygonPrimitives(primitives, instance.Materials.Find(m => m.Symbol == primitives.MaterialSymbol)); | 
 
 
 
 
 | 77 | } | 
 
 
 
 
 | 78 | } | 
 
 
 
 
 | 79 |  | 
 
 
 
 
 | 80 | private void ReadPolygonPrimitives(Dae.MeshPrimitives primitives, Dae.MaterialInstance materialInstance) | 
 
 
 
 
 | 81 | { | 
 
 
 
 
 | 82 | int[] positionIndices = null; | 
 
 
 
 
 | 83 |  | 
 
 
 
 
 | 84 | foreach (var input in primitives.Inputs) | 
 
 
 
 
 | 85 | { | 
 
 
 
 
 | 86 | switch (input.Semantic) | 
 
 
 
 
 | 87 | { | 
 
 
 
 
 | 88 | case Dae.Semantic.Position: | 
 
 
 
 
 | 89 | positionIndices = ReadInputIndexed(input, positions, Dae.Source.ReadVector3); | 
 
 
 
 
 | 90 | break; | 
 
 
 
 
 | 91 | } | 
 
 
 
 
 | 92 | } | 
 
 
 
 
 | 93 |  | 
 
 
 
 
 | 94 | foreach (int i in positionIndices) | 
 
 
 
 
 | 95 | positions[i] = Vector3.Transform(positions[i], ref nodeTransform); | 
 
 
 
 
 | 96 |  | 
 
 
 
 
 | 97 | int startIndex = 0; | 
 
 
 
 
 | 98 |  | 
 
 
 
 
 | 99 | foreach (int vertexCount in primitives.VertexCounts) | 
 
 
 
 
 | 100 | { | 
 
 
 
 
 | 101 | var polygonPointIndices = new int[vertexCount]; | 
 
 
 
 
 | 102 | Array.Copy(positionIndices, startIndex, polygonPointIndices, 0, vertexCount); | 
 
 
 
 
 | 103 |  | 
 
 
 
 
 | 104 | var polygon = new Polygon(mesh, polygonPointIndices); | 
 
 
 
 
 | 105 |  | 
 
 
 
 
 | 106 | if (Vector3.Dot(polygon.Plane.Normal, Vector3.UnitY) >= 0.3420201f) | 
 
 
 
 
 | 107 | mesh.Polygons.Add(polygon); | 
 
 
 
 
 | 108 |  | 
 
 
 
 
 | 109 | startIndex += vertexCount; | 
 
 
 
 
 | 110 | } | 
 
 
 
 
 | 111 | } | 
 
 
 
 
 | 112 |  | 
 
 
 
 
 | 113 | private static int[] ReadInputIndexed<T>(Dae.IndexedInput input, List<T> list, Func<Dae.Source, int, T> elementReader) | 
 
 
 
 
 | 114 | where T : struct | 
 
 
 
 
 | 115 | { | 
 
 
 
 
 | 116 | var indices = new int[input.Indices.Count]; | 
 
 
 
 
 | 117 |  | 
 
 
 
 
 | 118 | for (int i = 0; i < input.Indices.Count; i++) | 
 
 
 
 
 | 119 | { | 
 
 
 
 
 | 120 | var v = elementReader(input.Source, input.Indices[i]); | 
 
 
 
 
 | 121 | indices[i] = list.Count; | 
 
 
 
 
 | 122 | list.Add(v); | 
 
 
 
 
 | 123 | } | 
 
 
 
 
 | 124 |  | 
 
 
 
 
 | 125 | return indices; | 
 
 
 
 
 | 126 | } | 
 
 
 
 
 | 127 | } | 
 
 
 
 
 | 128 | } |