[1114] | 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 | }
|
---|