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 | }
|
---|