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}