source: OniSplit/Akira/Polygon.cs@ 1138

Last change on this file since 1138 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: 8.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using Oni.Imaging;
4
5namespace Oni.Akira
6{
7 internal class Polygon
8 {
9 #region Private data
10 private PolygonMesh mesh;
11 private GunkFlags flags;
12 private int[] pointIndices;
13 private int[] texCoordIndices;
14 private int[] normalIndices;
15 private Color[] colors;
16 private Material material;
17 private Plane plane;
18 private int objectType = -1;
19 private int objectId = -1;
20 private int scriptId;
21 private string fileName;
22 private string objectName;
23 private PolygonEdge[] edges;
24 private BoundingBox bbox;
25 #endregion
26
27 public Polygon(PolygonMesh mesh, int[] pointIndices)
28 {
29 this.mesh = mesh;
30 this.pointIndices = pointIndices;
31 this.plane = GetPlane();
32 this.bbox = GetBoundingBox();
33
34 BuildFlags();
35 }
36
37 public Polygon(PolygonMesh mesh, int[] pointIndices, GunkFlags flags)
38 : this(mesh, pointIndices)
39 {
40 this.flags |= flags;
41 }
42
43 public Polygon(PolygonMesh mesh, int[] pointIndices, Plane plane)
44 {
45 this.mesh = mesh;
46 this.pointIndices = pointIndices;
47 this.plane = plane;
48
49 BuildFlags();
50 }
51
52 public PolygonMesh Mesh => mesh;
53
54 public GunkFlags Flags
55 {
56 get
57 {
58 if (material == null)
59 return flags;
60
61 return flags | material.Flags;
62 }
63 set
64 {
65 flags = value;
66 }
67 }
68
69 public bool IsTransparent => (Flags & GunkFlags.Transparent) != 0;
70 public bool IsStairs=>(Flags & GunkFlags.Stairs) != 0;
71
72 public Material Material
73 {
74 get { return material; }
75 set { material = value; }
76 }
77
78 public int VertexCount => pointIndices.Length;
79
80 public int[] PointIndices => pointIndices;
81
82 public IEnumerable<Vector3> Points
83 {
84 get
85 {
86 foreach (int i in pointIndices)
87 yield return mesh.Points[i];
88 }
89 }
90
91 public int[] TexCoordIndices
92 {
93 get { return texCoordIndices; }
94 set { texCoordIndices = value; }
95 }
96
97 public int[] NormalIndices
98 {
99 get { return normalIndices; }
100 set { normalIndices = value; }
101 }
102
103 public Color[] Colors
104 {
105 get { return colors; }
106 set { colors = value; }
107 }
108
109 public Plane Plane => plane;
110
111 public int ObjectType
112 {
113 get { return objectType; }
114 set { objectType = value; }
115 }
116
117 public int ObjectId
118 {
119 get { return objectId; }
120 set { objectId = value; }
121 }
122
123 public int ScriptId
124 {
125 get { return scriptId; }
126 set { scriptId = value; }
127 }
128
129 public string FileName
130 {
131 get { return fileName; }
132 set { fileName = value; }
133 }
134
135 public string ObjectName
136 {
137 get { return objectName; }
138 set { objectName = value; }
139 }
140
141 private Plane GetPlane()
142 {
143 var plane = new Plane(
144 mesh.Points[pointIndices[0]],
145 mesh.Points[pointIndices[1]],
146 mesh.Points[pointIndices[2]]);
147
148 var bbox = GetBoundingBox();
149 var bboxSize = bbox.Max - bbox.Min;
150
151 if (Math.Abs(bboxSize.X) < 0.0001f)
152 {
153 if (plane.Normal.X < 0.0f)
154 plane = new Plane(Vector3.Left, bbox.Min.X);
155 else
156 plane = new Plane(Vector3.Right, -bbox.Max.X);
157 }
158 else if (Math.Abs(bboxSize.Y) < 0.0001f)
159 {
160 if (plane.Normal.Y < 0.0f)
161 plane = new Plane(Vector3.Down, bbox.Min.Y);
162 else
163 plane = new Plane(Vector3.Up, -bbox.Max.Y);
164 }
165 else if (Math.Abs(bboxSize.Z) < 0.0001f)
166 {
167 if (plane.Normal.Z < 0.0f)
168 plane = new Plane(Vector3.Forward, bbox.Min.Z);
169 else
170 plane = new Plane(Vector3.Backward, -bbox.Max.Z);
171 }
172 else
173 {
174 plane.Normal.X = FMath.Round(plane.Normal.X, 4);
175 plane.Normal.Y = FMath.Round(plane.Normal.Y, 4);
176 plane.Normal.Z = FMath.Round(plane.Normal.Z, 4);
177 }
178
179 return plane;
180 }
181
182 public BoundingBox BoundingBox => bbox;
183
184 private BoundingBox GetBoundingBox()
185 {
186 var point = mesh.Points[pointIndices[0]];
187 var bbox = new BoundingBox(point, point);
188
189 for (int i = 1; i < pointIndices.Length; i++)
190 {
191 point = mesh.Points[pointIndices[i]];
192
193 Vector3.Min(ref bbox.Min, ref point, out bbox.Min);
194 Vector3.Max(ref bbox.Max, ref point, out bbox.Max);
195 }
196
197 return bbox;
198 }
199
200 private void BuildFlags()
201 {
202 SetProjectionPlane();
203 SetHorizontalVertical();
204 }
205
206 private void SetHorizontalVertical()
207 {
208 if (Math.Abs(Vector3.Dot(plane.Normal, Vector3.UnitY)) < 0.3420201f)
209 flags |= GunkFlags.Vertical;
210 else
211 flags |= GunkFlags.Horizontal;
212 }
213
214 private void SetProjectionPlane()
215 {
216 var points = new Vector3[pointIndices.Length];
217
218 for (int i = 0; i < pointIndices.Length; i++)
219 points[i] = mesh.Points[pointIndices[i]];
220
221 float xyArea = MathHelper.Area(Project(points, PolygonProjectionPlane.XY));
222 float yzArea = MathHelper.Area(Project(points, PolygonProjectionPlane.YZ));
223 float xzArea = MathHelper.Area(Project(points, PolygonProjectionPlane.XZ));
224
225 var plane = PolygonProjectionPlane.None;
226
227 if (xyArea > yzArea)
228 {
229 if (xyArea > xzArea)
230 plane = PolygonProjectionPlane.XY;
231 else
232 plane = PolygonProjectionPlane.XZ;
233 }
234 else
235 {
236 if (yzArea > xzArea)
237 plane = PolygonProjectionPlane.YZ;
238 else
239 plane = PolygonProjectionPlane.XZ;
240 }
241
242 flags |= (GunkFlags)((int)plane << 25);
243 }
244
245 private static Vector2[] Project(Vector3[] points, PolygonProjectionPlane plane)
246 {
247 var result = new Vector2[points.Length];
248
249 switch (plane)
250 {
251 case PolygonProjectionPlane.XY:
252 for (int i = 0; i < points.Length; i++)
253 {
254 result[i].X = points[i].X;
255 result[i].Y = points[i].Y;
256 }
257 break;
258 case PolygonProjectionPlane.XZ:
259 for (int i = 0; i < points.Length; i++)
260 {
261 result[i].X = points[i].X;
262 result[i].Y = points[i].Z;
263 }
264 break;
265 case PolygonProjectionPlane.YZ:
266 for (int i = 0; i < points.Length; i++)
267 {
268 result[i].X = points[i].Z;
269 result[i].Y = points[i].Y;
270 }
271 break;
272 }
273
274 return result;
275 }
276
277 public PolygonEdge[] Edges
278 {
279 get
280 {
281 if (edges == null)
282 {
283 edges = new PolygonEdge[pointIndices.Length];
284
285 for (int i = 0; i < edges.Length; i++)
286 edges[i] = new PolygonEdge(this, i);
287 }
288
289 return edges;
290 }
291 }
292 }
293}
Note: See TracBrowser for help on using the repository browser.