No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BatchedDrawing.cs 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System.Collections.Generic;
  2. using Unity.Burst;
  3. using Unity.Collections;
  4. using Unity.Collections.LowLevel.Unsafe;
  5. using Unity.Mathematics;
  6. using UnityEditor.U2D.Common;
  7. using UnityEngine;
  8. using UnityEngine.U2D.Animation;
  9. namespace UnityEditor.U2D.Animation
  10. {
  11. [BurstCompile]
  12. internal static class BatchedDrawing
  13. {
  14. class Batch
  15. {
  16. public UnsafeList<float3> vertices;
  17. public UnsafeList<Color> vertexColors;
  18. public UnsafeList<int> indices;
  19. public Batch()
  20. {
  21. vertices = new UnsafeList<float3>(1, Allocator.Persistent);
  22. indices = new UnsafeList<int>(1, Allocator.Persistent);
  23. vertexColors = new UnsafeList<Color>(1, Allocator.Persistent);
  24. }
  25. ~Batch()
  26. {
  27. vertices.Dispose();
  28. indices.Dispose();
  29. vertexColors.Dispose();
  30. }
  31. public void Clear()
  32. {
  33. vertices.Clear();
  34. indices.Clear();
  35. vertexColors.Clear();
  36. }
  37. }
  38. // Unity's max index limit for meshes.
  39. const int k_MaxIndexLimit = 65535;
  40. static readonly int s_HandleSize = Shader.PropertyToID("_HandleSize");
  41. static readonly List<Batch> s_Batches = new List<Batch>(1) { new Batch() };
  42. static Mesh s_Mesh;
  43. static NativeArray<float3> s_VertexTmpCache = default;
  44. public static unsafe void RegisterLine(float3 p1, float3 p2, float3 normal, float widthP1, float widthP2, Color color)
  45. {
  46. var up = math.cross(normal, p2 - p1);
  47. up = math.normalize(up);
  48. const int dataToAdd = 6;
  49. var batch = GetBatch(dataToAdd);
  50. var startIndex = batch.vertices.Length;
  51. batch.indices.Resize(startIndex + dataToAdd);
  52. batch.vertexColors.Resize(startIndex + dataToAdd);
  53. batch.vertices.Resize(startIndex + dataToAdd);
  54. var vertexPtr = batch.vertices.Ptr;
  55. vertexPtr[startIndex] = p1 + up * (widthP1 * 0.5f);
  56. vertexPtr[startIndex + 1] = p1 - up * (widthP1 * 0.5f);
  57. vertexPtr[startIndex + 2] = p2 - up * (widthP2 * 0.5f);
  58. vertexPtr[startIndex + 3] = p1 + up * (widthP1 * 0.5f);
  59. vertexPtr[startIndex + 4] = p2 - up * (widthP2 * 0.5f);
  60. vertexPtr[startIndex + 5] = p2 + up * (widthP2 * 0.5f);
  61. for (var i = 0; i < dataToAdd; ++i)
  62. {
  63. batch.indices.Ptr[startIndex + i] = startIndex + i;
  64. batch.vertexColors.Ptr[startIndex + i] = color;
  65. }
  66. }
  67. public static void RegisterSolidDisc(float3 center, float3 normal, float radius, Color color)
  68. {
  69. var from = math.cross(normal, math.up());
  70. if (math.lengthsq(from) < 1.0 / 1000.0)
  71. from = math.cross(normal, math.right());
  72. RegisterSolidArc(center, normal, from, 360f, radius, color);
  73. }
  74. public static unsafe void RegisterSolidArc(float3 center, float3 normal, float3 from, float angle, float radius, Color color, int numSamples = 60)
  75. {
  76. numSamples = math.clamp(numSamples, 3, 60);
  77. if (s_VertexTmpCache == default)
  78. s_VertexTmpCache = new NativeArray<float3>(60, Allocator.Persistent);
  79. SetDiscSectionPoints(ref s_VertexTmpCache, numSamples, in normal, in from, angle);
  80. var dataToAdd = (numSamples - 1) * 3;
  81. var batch = GetBatch(dataToAdd);
  82. var startIndex = batch.vertices.Length;
  83. batch.indices.Resize(startIndex + dataToAdd);
  84. batch.vertexColors.Resize(startIndex + dataToAdd);
  85. batch.vertices.Resize(startIndex + dataToAdd);
  86. CreateSolidArcVertices(ref batch.vertices, startIndex, in s_VertexTmpCache, in center, numSamples, radius);
  87. for (var i = 0; i < dataToAdd; ++i)
  88. {
  89. batch.indices.Ptr[startIndex + i] = startIndex + i;
  90. batch.vertexColors.Ptr[startIndex + i] = color;
  91. }
  92. }
  93. [BurstCompile]
  94. static void CreateSolidArcVertices(
  95. ref UnsafeList<float3> vertexPtr,
  96. int startIndex,
  97. in NativeArray<float3> vertexCache,
  98. in float3 center,
  99. int numSamples,
  100. float radius)
  101. {
  102. var count = 0;
  103. for (var i = 1; i < numSamples; i++, count += 3)
  104. {
  105. var index = startIndex + count;
  106. vertexPtr[index] = center;
  107. vertexPtr[index + 1] = center + vertexCache[i - 1] * radius;
  108. vertexPtr[index + 2] = center + vertexCache[i] * radius;
  109. }
  110. }
  111. public static unsafe void RegisterSolidArcWithOutline(float3 center, float3 normal, float3 from, float angle,
  112. float radius, float outlineScale, Color color, int numSamples = 60)
  113. {
  114. numSamples = Mathf.Clamp(numSamples, 3, 60);
  115. if (s_VertexTmpCache == default)
  116. s_VertexTmpCache = new NativeArray<float3>(60, Allocator.Persistent);
  117. SetDiscSectionPoints(ref s_VertexTmpCache, numSamples, in normal, in from, angle);
  118. var dataToAdd = (numSamples - 1) * 6;
  119. var batch = GetBatch(dataToAdd);
  120. var startIndex = batch.vertices.Length;
  121. batch.indices.Resize(startIndex + dataToAdd);
  122. batch.vertexColors.Resize(startIndex + dataToAdd);
  123. batch.vertices.Resize(startIndex + dataToAdd);
  124. // var vertexPtr = batch.vertices.Ptr + startIndex;
  125. CreateSolidArcWithOutlineVertices(ref batch.vertices, startIndex, in s_VertexTmpCache, in center, numSamples, outlineScale, radius);
  126. for (var i = 0; i < dataToAdd; ++i)
  127. {
  128. batch.indices.Ptr[startIndex + i] = startIndex + i;
  129. batch.vertexColors.Ptr[startIndex + i] = color;
  130. }
  131. }
  132. [BurstCompile]
  133. static void CreateSolidArcWithOutlineVertices(
  134. ref UnsafeList<float3> vertexPtr,
  135. int startIndex,
  136. in NativeArray<float3> vertexCache,
  137. in float3 center,
  138. int numSamples,
  139. float outlineScale,
  140. float radius)
  141. {
  142. var count = 0;
  143. for (var i = 1; i < numSamples; i++, count += 6)
  144. {
  145. var index = startIndex + count;
  146. vertexPtr[index] = center + vertexCache[i - 1] * (radius * outlineScale);
  147. vertexPtr[index + 1] = center + vertexCache[i - 1] * radius;
  148. vertexPtr[index + 2] = center + vertexCache[i] * radius;
  149. vertexPtr[index + 3] = center + vertexCache[i - 1] * (radius * outlineScale);
  150. vertexPtr[index + 4] = center + vertexCache[i] * radius;
  151. vertexPtr[index + 5] = center + vertexCache[i] * (radius * outlineScale);
  152. }
  153. }
  154. [BurstCompile]
  155. static void SetDiscSectionPoints(ref NativeArray<float3> dest, int count, in float3 normal, in float3 from, float angle)
  156. {
  157. var angleInRadians = math.degrees(angle / (float) (count - 1));
  158. var rotation = quaternion.AxisAngle(normal, angleInRadians);
  159. var vector = math.normalize(from);
  160. for (var i = 0; i < count; i++)
  161. {
  162. dest[i] = vector;
  163. vector = math.mul(rotation, vector);
  164. }
  165. }
  166. static Batch GetBatch(int dataToAdd)
  167. {
  168. for (var i = 0; i < s_Batches.Count; ++i)
  169. {
  170. if ((s_Batches[i].indices.Length + dataToAdd) < k_MaxIndexLimit)
  171. return s_Batches[i];
  172. }
  173. var newBatch = new Batch();
  174. s_Batches.Add(newBatch);
  175. return newBatch;
  176. }
  177. public static void Draw()
  178. {
  179. if (s_Batches[0].indices.Length == 0)
  180. return;
  181. if (Event.current.type != EventType.Repaint)
  182. return;
  183. Shader.SetGlobalFloat(s_HandleSize, 1);
  184. InternalEditorBridge.ApplyWireMaterial();
  185. for (var i = 0; i < s_Batches.Count; ++i)
  186. {
  187. DrawBatch(s_Batches[i]);
  188. s_Batches[i].Clear();
  189. }
  190. s_VertexTmpCache.DisposeIfCreated();
  191. s_VertexTmpCache = default;
  192. }
  193. static unsafe void DrawBatch(Batch batch)
  194. {
  195. var vertexPtr = batch.vertices.Ptr;
  196. var indexPtr = batch.indices.Ptr;
  197. var vertexColorPtr = batch.vertexColors.Ptr;
  198. var vertexCount = batch.vertices.Length;
  199. var vertexArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector3>(vertexPtr, vertexCount, batch.vertices.Allocator.ToAllocator);
  200. var indexArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<int>(indexPtr, vertexCount, batch.indices.Allocator.ToAllocator);
  201. var colorArr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Color>(vertexColorPtr, vertexCount, batch.vertexColors.Allocator.ToAllocator);
  202. NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref vertexArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle());
  203. NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref indexArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle());
  204. NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref colorArr, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle());
  205. if (s_Mesh == null)
  206. s_Mesh = new Mesh();
  207. else
  208. s_Mesh.Clear();
  209. s_Mesh.SetVertices(vertexArr);
  210. s_Mesh.SetIndices(indexArr, MeshTopology.Triangles, 0);
  211. s_Mesh.SetColors(colorArr);
  212. Graphics.DrawMeshNow(s_Mesh, Handles.matrix);
  213. }
  214. }
  215. }