-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Loop3.cs
349 lines (318 loc) · 10.1 KB
/
Loop3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
using System;
using System.Text;
/// <summary>
/// Represents the edge loop of vertex indices that form the
/// face of a mesh.
/// </summary>
public class Loop3
{
/// <summary>
/// Array of compound vertex indices.
/// </summary>
protected Index3[] indices;
/// <summary>
/// Array of compound vertex indices.
/// </summary>
/// <value>indices</value>
public Index3[] Indices
{
get
{
return this.indices;
}
set
{
this.indices = value;
}
}
/// <summary>
/// The number of vertex indices in this loop.
/// </summary>
/// <value>length</value>
public int Length { get { return this.indices.Length; } }
/// <summary>
/// Gets or sets a mesh compound index at i. Wraps around, so
/// negative indices may be used.
/// </summary>
/// <value>mesh index</value>
public Index3 this[int i]
{
get
{
return this.indices[Utils.RemFloor(i, this.indices.Length)];
}
set
{
this.indices[Utils.RemFloor(i, this.indices.Length)] = value;
}
}
/// <summary>
/// Constructs a new loop with three indices, the minimum
/// number to form an enclosed face.
/// </summary>
public Loop3()
{
this.indices = new Index3[3];
}
/// <summary>
/// Constructs a loop with the given number of indices,
/// a minimum of three.
/// </summary>
/// <param name="length">index length</param>
public Loop3(in int length)
{
this.indices = new Index3[length < 3 ? 3 : length];
}
/// <summary>
/// Constructs a loop from an index array.
/// </summary>
/// <param name="indices">indices</param>
public Loop3(in Index3[] indices)
{
this.indices = indices;
}
/// <summary>
/// Constructs a loop from a list of indices.
/// </summary>
/// <param name="indices">indices</param>
public Loop3(params Index3[] indices)
{
this.indices = indices;
}
/// <summary>
/// Returns a string representation of this vector.
/// </summary>
/// <returns>string</returns>
public override string ToString()
{
return Loop3.ToString(this);
}
/// <summary>
/// Reverses the indices in this loop.
/// </summary>
/// <returns>this loop</returns>
public Loop3 Reverse()
{
Array.Reverse(this.indices);
return this;
}
/// <summary>
/// Promotes a 2D mesh loop to a 3D loop.
/// </summary>
/// <param name="source">2D loop</param>
/// <returns>the promotion</returns>
public static explicit operator Loop3(in Loop2 source)
{
int len = source.Length;
Loop3 result = new(new Index3[len]);
Index2[] srcIdcs = source.Indices;
Index3[] trgIdcs = result.Indices;
for (int i = 0; i < len; ++i)
{
trgIdcs[i] = (Index3)srcIdcs[i];
}
return result;
}
/// <summary>
/// Convenience method. Sets the target loop's indices to a new array
/// created from the arguments. Creates a quadrilateral.
/// </summary>
/// <param name="a">first vertex</param>
/// <param name="b">second vertex</param>
/// <param name="c">third vertex</param>
/// <param name="d">fourth vertex</param>
/// <param name="e">fifth vertex</param>
/// <param name="target">target loop</param>
/// <returns>pentagon loop</returns>
public static Loop3 Pentagon(
in Index3 a,
in Index3 b,
in Index3 c,
in Index3 d,
in Index3 e,
in Loop3 target)
{
target.indices = new Index3[] { a, b, c, d, e };
return target;
}
/// <summary>
/// Convenience method. Sets the target loop's indices to a new array
/// created from the arguments. Creates a quadrilateral.
/// </summary>
/// <param name="a">first vertex</param>
/// <param name="b">second vertex</param>
/// <param name="c">third vertex</param>
/// <param name="d">fourth vertex</param>
/// <param name="target">target loop</param>
/// <returns>quadrilateral loop</returns>
public static Loop3 Quad(
in Index3 a,
in Index3 b,
in Index3 c,
in Index3 d,
in Loop3 target)
{
target.indices = new Index3[] { a, b, c, d };
return target;
}
/// <summary>
/// Resizes an array of loops. If the size is less than one, returns an empty array.
/// If the input array is null, creates an array of new loops. Existing loops in the
/// old array are passed to the resized array by reference. There is an option to
/// resize the length of these existing loops to match the length of new loops.
/// </summary>
/// <param name="arr">array</param>
/// <param name="sz">size</param>
/// <param name="vertsPerLoop">vertices per loop</param>
/// <param name="resizeExisting">change existing loop length</param>
/// <returns>resized array</returns>
public static Loop3[] Resize(
in Loop3[] arr,
in int sz,
in int vertsPerLoop = 3,
in bool resizeExisting = false)
{
if (sz < 1) { return new Loop3[] { }; }
Loop3[] result = new Loop3[sz];
int vplVal = vertsPerLoop < 3 ? 3 : vertsPerLoop;
if (arr == null)
{
for (int i = 0; i < sz; ++i)
{
result[i] = new Loop3(vplVal);
}
return result;
}
int last = arr.Length - 1;
for (int i = 0; i < sz; ++i)
{
if (i > last || arr[i] == null)
{
result[i] = new Loop3(vplVal);
}
else
{
result[i] = arr[i];
if (resizeExisting)
{
result[i].indices = Index3.Resize(result[i].indices, vplVal);
}
}
}
return result;
}
/// <summary>
/// Splices an array of loops into the midst of another. For use by
/// subdivision functions. If the number of deletions exceeds the length of
/// the target array, then a copy of the insert array is returned.
/// </summary>
/// <param name="arr">array</param>
/// <param name="index">insertion point</param>
/// <param name="deletions">deletion count</param>
/// <param name="insert">insert</param>
/// <returns>spliced array</returns>
public static Loop3[] Splice(in Loop3[] arr, in int index, in int deletions, in Loop3[] insert)
{
int aLen = arr.Length;
if (deletions >= aLen)
{
Loop3[] result0 = new Loop3[insert.Length];
System.Array.Copy(insert, 0, result0, 0, insert.Length);
return result0;
}
int bLen = insert.Length;
int valIdx = Utils.RemFloor(index, aLen + 1);
if (deletions < 1)
{
Loop3[] result1 = new Loop3[aLen + bLen];
System.Array.Copy(arr, 0, result1, 0, valIdx);
System.Array.Copy(insert, 0, result1, valIdx, bLen);
System.Array.Copy(arr, valIdx, result1, valIdx + bLen, aLen - valIdx);
return result1;
}
int idxOff = valIdx + deletions;
Loop3[] result = new Loop3[aLen + bLen - deletions];
System.Array.Copy(arr, 0, result, 0, valIdx);
System.Array.Copy(insert, 0, result, valIdx, bLen);
System.Array.Copy(arr, idxOff, result, valIdx + bLen, aLen - idxOff);
return result;
}
/// <summary>
/// Returns a string representation of a loop.
/// </summary>
/// <param name="l">loop</param>
/// <param name="padding">padding</param>
/// <returns>string</returns>
public static string ToString(in Loop3 l, in int padding = 3)
{
return Loop3.ToString(new StringBuilder(1024), l, padding).ToString();
}
/// <summary>
/// Appends a string representation of a loop
/// to a string builder.
/// </summary>
/// <param name="sb">string builder</param>
/// <param name="l">loop</param>
/// <param name="padding">padding</param>
/// <returns>string builder</returns>
public static StringBuilder ToString(in StringBuilder sb, in Loop3 l, in int padding = 3)
{
sb.Append("{\"indices\":");
Index3.ToString(sb, l.indices, padding);
sb.Append('}');
return sb;
}
/// <summary>
/// Returns a string representation of an array of loops.
/// </summary>
/// <param name="arr">array</param>
/// <param name="padding">padding</param>
/// <returns>string</returns>
public static string ToString(in Loop3[] arr, in int padding = 3)
{
return Loop3.ToString(new StringBuilder(1024), arr, padding).ToString();
}
/// <summary>
/// Appends a string representation of an array of loops
/// to a string builder.
/// </summary>
/// <param name="sb">string builder</param>
/// <param name="arr">array</param>
/// <param name="padding">padding</param>
/// <returns>string builder</returns>
public static StringBuilder ToString(in StringBuilder sb, in Loop3[] arr, in int padding = 3)
{
sb.Append('[');
if (arr != null)
{
int len = arr.Length;
int last = len - 1;
for (int i = 0; i < last; ++i)
{
Loop3.ToString(sb, arr[i], padding);
sb.Append(',');
}
Loop3.ToString(sb, arr[last], padding);
}
sb.Append(']');
return sb;
}
/// <summary>
/// Convenience method. Sets the target loop's indices to a new array
/// created from the arguments. Creates a triangle.
/// </summary>
/// <param name="a">first vertex</param>
/// <param name="b">second vertex</param>
/// <param name="c">third vertex</param>
/// <param name="target">target loop</param>
/// <returns>triangle loop</returns>
public static Loop3 Tri(
in Index3 a,
in Index3 b,
in Index3 c,
in Loop3 target)
{
target.indices = new Index3[] { a, b, c };
return target;
}
}