source: OniSplit/Akira/RoomExtractor.cs@ 1148

Last change on this file since 1148 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 4.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4
5namespace 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}
Note: See TracBrowser for help on using the repository browser.