1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
|
4 |
namespace Oni.Motoko |
5 |
{ |
6 |
internal static class GeometryDatReader |
7 |
{ |
8 |
public static Geometry Read(InstanceDescriptor m3gm) |
9 |
{ |
10 |
if (m3gm.Template.Tag != TemplateTag.M3GM) |
11 |
throw new ArgumentException(string.Format("Invalid instance type {0}", m3gm.Template.Tag), "m3gm"); |
12 |
|
13 |
InstanceDescriptor pnta; |
14 |
InstanceDescriptor vcra1; |
15 |
InstanceDescriptor vcra2; |
16 |
InstanceDescriptor txca; |
17 |
InstanceDescriptor idxa1; |
18 |
InstanceDescriptor idxa2; |
19 |
InstanceDescriptor txmp; |
20 |
|
21 |
using (var reader = m3gm.OpenRead(4)) |
22 |
{ |
23 |
pnta = reader.ReadInstance(); |
24 |
vcra1 = reader.ReadInstance(); |
25 |
vcra2 = reader.ReadInstance(); |
26 |
txca = reader.ReadInstance(); |
27 |
idxa1 = reader.ReadInstance(); |
28 |
idxa2 = reader.ReadInstance(); |
29 |
txmp = reader.ReadInstance(); |
30 |
} |
31 |
|
32 |
var geometry = new Geometry { |
33 |
Name = m3gm.FullName, |
34 |
Texture = txmp |
35 |
}; |
36 |
|
37 |
Vector3[] faceNormals; |
38 |
int[] faceIndices; |
39 |
int[] vertexIndices; |
40 |
|
41 |
using (var reader = pnta.OpenRead(52)) |
42 |
geometry.Points = reader.ReadVector3Array(reader.ReadInt32()); |
43 |
|
44 |
using (var reader = vcra1.OpenRead(20)) |
45 |
geometry.Normals = reader.ReadVector3Array(reader.ReadInt32()); |
46 |
|
47 |
using (var reader = vcra2.OpenRead(20)) |
48 |
faceNormals = reader.ReadVector3Array(reader.ReadInt32()); |
49 |
|
50 |
using (var reader = txca.OpenRead(20)) |
51 |
geometry.TexCoords = reader.ReadVector2Array(reader.ReadInt32()); |
52 |
|
53 |
using (var reader = idxa1.OpenRead(20)) |
54 |
vertexIndices = reader.ReadInt32Array(reader.ReadInt32()); |
55 |
|
56 |
using (var reader = idxa2.OpenRead(20)) |
57 |
faceIndices = reader.ReadInt32Array(reader.ReadInt32()); |
58 |
|
59 |
geometry.Triangles = ConvertTriangleStripToTriangleList(geometry.Points, vertexIndices, faceNormals, faceIndices); |
60 |
|
61 |
return geometry; |
62 |
} |
63 |
|
64 |
private static int[] ConvertTriangleStripToTriangleList(Vector3[] points, int[] vIndices, Vector3[] fNormals, int[] fIndices) |
65 |
{ |
66 |
var triangles = new List<int>(vIndices.Length * 2); |
67 |
|
68 |
var face = new int[3]; |
69 |
int faceIndex = 0; |
70 |
int order = 0; |
71 |
|
72 |
for (int i = 0; i < vIndices.Length; i++) |
73 |
{ |
74 |
if (vIndices[i] < 0) |
75 |
{ |
76 |
face[0] = vIndices[i++] & int.MaxValue; |
77 |
face[1] = vIndices[i++]; |
78 |
order = 0; |
79 |
} |
80 |
else |
81 |
{ |
82 |
face[order] = face[2]; |
83 |
order ^= 1; |
84 |
} |
85 |
|
86 |
face[2] = vIndices[i]; |
87 |
|
88 |
var v1 = points[face[0]]; |
89 |
var v2 = points[face[1]]; |
90 |
var v3 = points[face[2]]; |
91 |
|
92 |
var faceNormal1 = Vector3.Normalize(fNormals[fIndices[faceIndex]]); |
93 |
var faceNormal2 = Vector3.Normalize(Vector3.Cross(v2 - v1, v3 - v1)); |
94 |
|
95 |
if (Vector3.Dot(faceNormal1, faceNormal2) < 0.0f) |
96 |
{ |
97 |
triangles.Add(face[2]); |
98 |
triangles.Add(face[1]); |
99 |
triangles.Add(face[0]); |
100 |
} |
101 |
else |
102 |
{ |
103 |
triangles.Add(face[0]); |
104 |
triangles.Add(face[1]); |
105 |
triangles.Add(face[2]); |
106 |
} |
107 |
|
108 |
faceIndex++; |
109 |
} |
110 |
|
111 |
return triangles.ToArray(); |
112 |
} |
113 |
} |
114 |
} |