A game about forced loneliness, made by TACStudios
1namespace UnityEngine.Rendering
2{
3 /// <summary>Debug class containing several debug shapes for debugging</summary>
4 public partial class DebugShapes
5 {
6 // Singleton
7 static DebugShapes s_Instance = null;
8
9 /// <summary>Singleton instance</summary>
10 static public DebugShapes instance
11 {
12 get
13 {
14 if (s_Instance == null)
15 {
16 s_Instance = new DebugShapes();
17 }
18
19 return s_Instance;
20 }
21 }
22
23 Mesh m_sphereMesh = null;
24 Mesh m_boxMesh = null;
25 Mesh m_coneMesh = null;
26 Mesh m_pyramidMesh = null;
27
28 // This code has been grabbed from http://wiki.unity3d.com/index.php/ProceduralPrimitives
29 void BuildSphere(ref Mesh outputMesh, float radius, uint longSubdiv, uint latSubdiv)
30 {
31 // Make sure it is empty before pushing anything to it
32 outputMesh.Clear();
33
34 // Build the vertices array
35 Vector3[] vertices = new Vector3[(longSubdiv + 1) * latSubdiv + 2];
36 float _pi = Mathf.PI;
37 float _2pi = _pi * 2f;
38
39 vertices[0] = Vector3.up * radius;
40 for (int lat = 0; lat < latSubdiv; lat++)
41 {
42 float a1 = _pi * (float)(lat + 1) / (latSubdiv + 1);
43 float sin1 = Mathf.Sin(a1);
44 float cos1 = Mathf.Cos(a1);
45
46 for (int lon = 0; lon <= longSubdiv; lon++)
47 {
48 float a2 = _2pi * (float)(lon == longSubdiv ? 0 : lon) / longSubdiv;
49 float sin2 = Mathf.Sin(a2);
50 float cos2 = Mathf.Cos(a2);
51
52 vertices[lon + lat * (longSubdiv + 1) + 1] = new Vector3(sin1 * cos2, cos1, sin1 * sin2) * radius;
53 }
54 }
55 vertices[vertices.Length - 1] = Vector3.up * -radius;
56
57 // Build the normals array
58 Vector3[] normals = new Vector3[vertices.Length];
59 for (int n = 0; n < vertices.Length; n++)
60 {
61 normals[n] = vertices[n].normalized;
62 }
63
64 // Build the UV array
65 Vector2[] uvs = new Vector2[vertices.Length];
66 uvs[0] = Vector2.up;
67 uvs[uvs.Length - 1] = Vector2.zero;
68 for (int lat = 0; lat < latSubdiv; lat++)
69 {
70 for (int lon = 0; lon <= longSubdiv; lon++)
71 {
72 uvs[lon + lat * (longSubdiv + 1) + 1] = new Vector2((float)lon / longSubdiv, 1f - (float)(lat + 1) / (latSubdiv + 1));
73 }
74 }
75
76 // Build the index array
77 uint nbTriangles = longSubdiv * 2 + // Top and bottom cap
78 (latSubdiv - 1) * longSubdiv * 2; // Middle part
79 uint nbIndexes = nbTriangles * 3;
80 int[] triangles = new int[nbIndexes];
81
82 // Top Cap
83 int i = 0;
84 for (int lon = 0; lon < longSubdiv; lon++)
85 {
86 triangles[i++] = lon + 2;
87 triangles[i++] = lon + 1;
88 triangles[i++] = 0;
89 }
90
91 //Middle
92 for (uint lat = 0; lat < latSubdiv - 1; lat++)
93 {
94 for (uint lon = 0; lon < longSubdiv; lon++)
95 {
96 uint current = lon + lat * (longSubdiv + 1) + 1;
97 uint next = current + longSubdiv + 1;
98
99 triangles[i++] = (int)current;
100 triangles[i++] = (int)current + 1;
101 triangles[i++] = (int)next + 1;
102
103 triangles[i++] = (int)current;
104 triangles[i++] = (int)next + 1;
105 triangles[i++] = (int)next;
106 }
107 }
108
109 // Bottom Cap
110 for (int lon = 0; lon < longSubdiv; lon++)
111 {
112 triangles[i++] = vertices.Length - 1;
113 triangles[i++] = vertices.Length - (lon + 2) - 1;
114 triangles[i++] = vertices.Length - (lon + 1) - 1;
115 }
116
117 // Assign them to
118 outputMesh.vertices = vertices;
119 outputMesh.normals = normals;
120 outputMesh.uv = uvs;
121 outputMesh.triangles = triangles;
122
123 outputMesh.RecalculateBounds();
124 }
125
126 void BuildBox(ref Mesh outputMesh, float length, float width, float height)
127 {
128 outputMesh.Clear();
129
130 Vector3 p0 = new Vector3(-length * .5f, -width * .5f, height * .5f);
131 Vector3 p1 = new Vector3(length * .5f, -width * .5f, height * .5f);
132 Vector3 p2 = new Vector3(length * .5f, -width * .5f, -height * .5f);
133 Vector3 p3 = new Vector3(-length * .5f, -width * .5f, -height * .5f);
134
135 Vector3 p4 = new Vector3(-length * .5f, width * .5f, height * .5f);
136 Vector3 p5 = new Vector3(length * .5f, width * .5f, height * .5f);
137 Vector3 p6 = new Vector3(length * .5f, width * .5f, -height * .5f);
138 Vector3 p7 = new Vector3(-length * .5f, width * .5f, -height * .5f);
139
140 Vector3[] vertices = new Vector3[]
141 {
142 // Bottom
143 p0, p1, p2, p3,
144 // Left
145 p7, p4, p0, p3,
146 // Front
147 p4, p5, p1, p0,
148 // Back
149 p6, p7, p3, p2,
150 // Right
151 p5, p6, p2, p1,
152 // Top
153 p7, p6, p5, p4
154 };
155
156 Vector3 up = Vector3.up;
157 Vector3 down = Vector3.down;
158 Vector3 front = Vector3.forward;
159 Vector3 back = Vector3.back;
160 Vector3 left = Vector3.left;
161 Vector3 right = Vector3.right;
162
163 Vector3[] normales = new Vector3[]
164 {
165 // Bottom
166 down, down, down, down,
167 // Left
168 left, left, left, left,
169 // Front
170 front, front, front, front,
171 // Back
172 back, back, back, back,
173 // Right
174 right, right, right, right,
175 // Top
176 up, up, up, up
177 };
178
179 Vector2 _00 = new Vector2(0f, 0f);
180 Vector2 _10 = new Vector2(1f, 0f);
181 Vector2 _01 = new Vector2(0f, 1f);
182 Vector2 _11 = new Vector2(1f, 1f);
183
184 Vector2[] uvs = new Vector2[]
185 {
186 // Bottom
187 _11, _01, _00, _10,
188 // Left
189 _11, _01, _00, _10,
190 // Front
191 _11, _01, _00, _10,
192 // Back
193 _11, _01, _00, _10,
194 // Right
195 _11, _01, _00, _10,
196 // Top
197 _11, _01, _00, _10,
198 };
199
200 int[] triangles = new int[]
201 {
202 // Bottom
203 3, 1, 0,
204 3, 2, 1,
205 // Left
206 3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1,
207 3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,
208 // Front
209 3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2,
210 3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,
211 // Back
212 3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3,
213 3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,
214 // Right
215 3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4,
216 3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,
217 // Top
218 3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5,
219 3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5,
220 };
221
222 outputMesh.vertices = vertices;
223 outputMesh.normals = normales;
224 outputMesh.uv = uvs;
225 outputMesh.triangles = triangles;
226
227 outputMesh.RecalculateBounds();
228 }
229
230 void BuildCone(ref Mesh outputMesh, float height, float topRadius, float bottomRadius, int nbSides)
231 {
232 outputMesh.Clear();
233
234 int nbVerticesCap = nbSides + 1;
235
236 // bottom + top + sides
237 Vector3[] vertices = new Vector3[nbVerticesCap + nbVerticesCap + nbSides * 2 + 2];
238 int vert = 0;
239 float _2pi = Mathf.PI * 2f;
240
241 // Bottom cap
242 vertices[vert++] = new Vector3(0f, 0f, 0f);
243 while (vert <= nbSides)
244 {
245 float rad = (float)vert / nbSides * _2pi;
246 vertices[vert] = new Vector3(Mathf.Sin(rad) * bottomRadius, Mathf.Cos(rad) * bottomRadius, 0f);
247 vert++;
248 }
249
250 // Top cap
251 vertices[vert++] = new Vector3(0f, 0f, height);
252 while (vert <= nbSides * 2 + 1)
253 {
254 float rad = (float)(vert - nbSides - 1) / nbSides * _2pi;
255 vertices[vert] = new Vector3(Mathf.Sin(rad) * topRadius, Mathf.Cos(rad) * topRadius, height);
256 vert++;
257 }
258
259 // Sides
260 int v = 0;
261 while (vert <= vertices.Length - 4)
262 {
263 float rad = (float)v / nbSides * _2pi;
264 vertices[vert] = new Vector3(Mathf.Sin(rad) * topRadius, Mathf.Cos(rad) * topRadius, height);
265 vertices[vert + 1] = new Vector3(Mathf.Sin(rad) * bottomRadius, Mathf.Cos(rad) * bottomRadius, 0);
266 vert += 2;
267 v++;
268 }
269 vertices[vert] = vertices[nbSides * 2 + 2];
270 vertices[vert + 1] = vertices[nbSides * 2 + 3];
271
272 // bottom + top + sides
273 Vector3[] normales = new Vector3[vertices.Length];
274 vert = 0;
275
276 // Bottom cap
277 while (vert <= nbSides)
278 {
279 normales[vert++] = new Vector3(0, 0, -1);
280 }
281
282 // Top cap
283 while (vert <= nbSides * 2 + 1)
284 {
285 normales[vert++] = new Vector3(0, 0, 1);
286 }
287
288 // Sides
289 v = 0;
290 while (vert <= vertices.Length - 4)
291 {
292 float rad = (float)v / nbSides * _2pi;
293 float cos = Mathf.Cos(rad);
294 float sin = Mathf.Sin(rad);
295
296 normales[vert] = new Vector3(sin, cos, 0f);
297 normales[vert + 1] = normales[vert];
298
299 vert += 2;
300 v++;
301 }
302 normales[vert] = normales[nbSides * 2 + 2];
303 normales[vert + 1] = normales[nbSides * 2 + 3];
304
305 Vector2[] uvs = new Vector2[vertices.Length];
306
307 // Bottom cap
308 int u = 0;
309 uvs[u++] = new Vector2(0.5f, 0.5f);
310 while (u <= nbSides)
311 {
312 float rad = (float)u / nbSides * _2pi;
313 uvs[u] = new Vector2(Mathf.Cos(rad) * .5f + .5f, Mathf.Sin(rad) * .5f + .5f);
314 u++;
315 }
316
317 // Top cap
318 uvs[u++] = new Vector2(0.5f, 0.5f);
319 while (u <= nbSides * 2 + 1)
320 {
321 float rad = (float)u / nbSides * _2pi;
322 uvs[u] = new Vector2(Mathf.Cos(rad) * .5f + .5f, Mathf.Sin(rad) * .5f + .5f);
323 u++;
324 }
325
326 // Sides
327 int u_sides = 0;
328 while (u <= uvs.Length - 4)
329 {
330 float t = (float)u_sides / nbSides;
331 uvs[u] = new Vector3(t, 1f);
332 uvs[u + 1] = new Vector3(t, 0f);
333 u += 2;
334 u_sides++;
335 }
336 uvs[u] = new Vector2(1f, 1f);
337 uvs[u + 1] = new Vector2(1f, 0f);
338
339 int nbTriangles = nbSides + nbSides + nbSides * 2;
340 int[] triangles = new int[nbTriangles * 3 + 3];
341
342 // Bottom cap
343 int tri = 0;
344 int i = 0;
345 while (tri < nbSides - 1)
346 {
347 triangles[i] = 0;
348 triangles[i + 1] = tri + 1;
349 triangles[i + 2] = tri + 2;
350 tri++;
351 i += 3;
352 }
353 triangles[i] = 0;
354 triangles[i + 1] = tri + 1;
355 triangles[i + 2] = 1;
356 tri++;
357 i += 3;
358
359 // Top cap
360 //tri++;
361 while (tri < nbSides * 2)
362 {
363 triangles[i] = tri + 2;
364 triangles[i + 1] = tri + 1;
365 triangles[i + 2] = nbVerticesCap;
366 tri++;
367 i += 3;
368 }
369
370 triangles[i] = nbVerticesCap + 1;
371 triangles[i + 1] = tri + 1;
372 triangles[i + 2] = nbVerticesCap;
373 tri++;
374 i += 3;
375 tri++;
376
377 // Sides
378 while (tri <= nbTriangles)
379 {
380 triangles[i] = tri + 2;
381 triangles[i + 1] = tri + 1;
382 triangles[i + 2] = tri + 0;
383 tri++;
384 i += 3;
385
386 triangles[i] = tri + 1;
387 triangles[i + 1] = tri + 2;
388 triangles[i + 2] = tri + 0;
389 tri++;
390 i += 3;
391 }
392
393 outputMesh.vertices = vertices;
394 outputMesh.normals = normales;
395 outputMesh.uv = uvs;
396 outputMesh.triangles = triangles;
397
398 outputMesh.RecalculateBounds();
399 }
400
401 void BuildPyramid(ref Mesh outputMesh, float width, float height, float depth)
402 {
403 outputMesh.Clear();
404
405 // Allocate the buffer
406 Vector3[] vertices = new Vector3[16];
407
408 // Top Face
409 vertices[0] = new Vector3(0f, 0f, 0f);
410 vertices[1] = new Vector3(-width / 2.0f, height / 2.0f, depth);
411 vertices[2] = new Vector3(width / 2.0f, height / 2.0f, depth);
412
413 // Left Face
414 vertices[3] = new Vector3(0f, 0f, 0f);
415 vertices[4] = new Vector3(width / 2.0f, height / 2.0f, depth);
416 vertices[5] = new Vector3(width / 2.0f, -height / 2.0f, depth);
417
418 // Bottom Face
419 vertices[6] = new Vector3(0f, 0f, 0f);
420 vertices[7] = new Vector3(width / 2.0f, -height / 2.0f, depth);
421 vertices[8] = new Vector3(-width / 2.0f, -height / 2.0f, depth);
422
423 // Right Face
424 vertices[9] = new Vector3(0f, 0f, 0f);
425 vertices[10] = new Vector3(-width / 2.0f, -height / 2.0f, depth);
426 vertices[11] = new Vector3(-width / 2.0f, height / 2.0f, depth);
427
428 // Cap
429 vertices[12] = new Vector3(-width / 2.0f, height / 2.0f, depth);
430 vertices[13] = new Vector3(-width / 2.0f, -height / 2.0f, depth);
431 vertices[14] = new Vector3(width / 2.0f, -height / 2.0f, depth);
432 vertices[15] = new Vector3(width / 2.0f, height / 2.0f, depth);
433
434 // TODO: support the uv/normals
435 Vector3[] normals = new Vector3[vertices.Length];
436 Vector2[] uvs = new Vector2[vertices.Length];
437
438 // The indexes for the side part is simple
439 int[] triangles = new int[18];
440 for (int idx = 0; idx < 12; ++idx)
441 {
442 triangles[idx] = idx;
443 }
444
445 // Cap indexes
446 triangles[12] = 12;
447 triangles[13] = 13;
448 triangles[14] = 14;
449 triangles[15] = 12;
450 triangles[16] = 14;
451 triangles[17] = 15;
452
453 outputMesh.vertices = vertices;
454 outputMesh.normals = normals;
455 outputMesh.uv = uvs;
456 outputMesh.triangles = triangles;
457
458 outputMesh.RecalculateBounds();
459 }
460
461 void BuildShapes()
462 {
463 m_sphereMesh = new Mesh();
464 BuildSphere(ref m_sphereMesh, 1.0f, 24, 16);
465
466 m_boxMesh = new Mesh();
467 BuildBox(ref m_boxMesh, 1.0f, 1.0f, 1.0f);
468
469 m_coneMesh = new Mesh();
470 BuildCone(ref m_coneMesh, 1.0f, 1.0f, 0.0f, 16);
471
472 m_pyramidMesh = new Mesh();
473 BuildPyramid(ref m_pyramidMesh, 1.0f, 1.0f, 1.0f);
474 }
475
476 void RebuildResources()
477 {
478 if (m_sphereMesh == null || m_boxMesh == null || m_coneMesh == null || m_pyramidMesh == null)
479 {
480 BuildShapes();
481 }
482 }
483
484 /// <summary>Get a Sphere Mesh</summary>
485 /// <returns>A Sphere Mesh</returns>
486 public Mesh RequestSphereMesh()
487 {
488 RebuildResources();
489 return m_sphereMesh;
490 }
491
492 /// <summary>Builds a custom Sphere Mesh</summary>
493 /// <param name="radius">The radius of the generated sphere.</param>
494 /// <param name="longSubdiv">The number of subdivisions along the equator of the sphere. Must be at least 3 to give a relevant shape.</param>
495 /// <param name="latSubdiv">The number of subdivisions from north to south. Must be at least 1 to give a relevant shape.</param>
496 /// <returns>A Sphere Mesh</returns>
497 /// <example>
498 /// <code>
499 /// <![CDATA[
500 /// Mesh lowPolyDebugMesh = DebugShapes.instance.BuildCustomSphereMesh(0.5f, 9, 8); // Generates a 82 vert sphere
501 /// ]]>
502 ///</code>
503 /// </example>
504 public Mesh BuildCustomSphereMesh(float radius, uint longSubdiv, uint latSubdiv)
505 {
506 Mesh sphereMesh = new Mesh();
507 BuildSphere(ref sphereMesh, radius, longSubdiv, latSubdiv);
508 return sphereMesh;
509 }
510
511 /// <summary>Get a Box Mesh</summary>
512 /// <returns>A Box Mesh</returns>
513 public Mesh RequestBoxMesh()
514 {
515 RebuildResources();
516 return m_boxMesh;
517 }
518
519 /// <summary>Get a Cone Mesh</summary>
520 /// <returns>A Cone Mesh</returns>
521 public Mesh RequestConeMesh()
522 {
523 RebuildResources();
524 return m_coneMesh;
525 }
526
527 /// <summary>Get a Pyramid Mesh</summary>
528 /// <returns>A Pyramid Mesh</returns>
529 public Mesh RequestPyramidMesh()
530 {
531 RebuildResources();
532 return m_pyramidMesh;
533 }
534 }
535}