DebugShapes.cs 17 KB

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