MeshPreviewCache.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. using UnityEngine;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace UnityEditor.U2D.Animation
  5. {
  6. internal class MeshPreviewCache : SkinningObject
  7. {
  8. private const int kNiceColorCount = 6;
  9. [SerializeField]
  10. private SpriteCache m_Sprite;
  11. [SerializeField]
  12. private Mesh m_Mesh;
  13. [SerializeField]
  14. private Mesh m_DefaultMesh;
  15. private List<Vector3> m_SkinnedVertices = new List<Vector3>();
  16. private List<Vector3> m_Vertices = new List<Vector3>();
  17. private List<BoneWeight> m_Weights = new List<BoneWeight>();
  18. private List<Vector2> m_TexCoords = new List<Vector2>();
  19. private List<Color> m_Colors = new List<Color>();
  20. private List<Matrix4x4> m_SkinningMatrices = new List<Matrix4x4>();
  21. private bool m_MeshDirty;
  22. private bool m_VerticesDirty;
  23. private bool m_SkinningDirty;
  24. private bool m_WeightsDirty;
  25. private bool m_IndicesDirty;
  26. private bool m_ColorsDirty;
  27. private bool m_EnableSkinning;
  28. public SpriteCache sprite
  29. {
  30. get { return m_Sprite; }
  31. set
  32. {
  33. m_Sprite = value;
  34. InitializeDefaultMesh();
  35. SetMeshDirty();
  36. }
  37. }
  38. public Mesh mesh { get { return m_Mesh; } }
  39. public Mesh defaultMesh { get { return m_DefaultMesh; } }
  40. public bool enableSkinning
  41. {
  42. get
  43. {
  44. return m_EnableSkinning;
  45. }
  46. set
  47. {
  48. if (m_EnableSkinning != value)
  49. {
  50. m_EnableSkinning = value;
  51. SetSkinningDirty();
  52. }
  53. }
  54. }
  55. public bool canSkin
  56. {
  57. get { return CanSkin(); }
  58. }
  59. public List<Vector3> vertices
  60. {
  61. get
  62. {
  63. if (enableSkinning && canSkin)
  64. return m_SkinnedVertices;
  65. return m_Vertices;
  66. }
  67. }
  68. private bool CanSkin()
  69. {
  70. if (m_Vertices.Count == 0 || m_Vertices.Count != m_Weights.Count)
  71. return false;
  72. var bones = sprite.GetBonesFromMode();
  73. Debug.Assert(bones != null);
  74. if (bones.Length == 0)
  75. return false;
  76. foreach (var weight in m_Weights)
  77. {
  78. if (weight.boneIndex0 < 0 || weight.boneIndex0 >= bones.Length ||
  79. weight.boneIndex1 < 0 || weight.boneIndex1 >= bones.Length ||
  80. weight.boneIndex2 < 0 || weight.boneIndex2 >= bones.Length ||
  81. weight.boneIndex3 < 0 || weight.boneIndex3 >= bones.Length)
  82. return false;
  83. }
  84. return true;
  85. }
  86. internal override void OnCreate()
  87. {
  88. m_Mesh = CreateMesh();
  89. m_DefaultMesh = CreateMesh();
  90. }
  91. internal override void OnDestroy()
  92. {
  93. DestroyImmediate(m_Mesh);
  94. DestroyImmediate(m_DefaultMesh);
  95. }
  96. private Mesh CreateMesh()
  97. {
  98. var mesh = new Mesh();
  99. mesh.MarkDynamic();
  100. mesh.hideFlags = HideFlags.DontSave;
  101. return mesh;
  102. }
  103. private void InitializeDefaultMesh()
  104. {
  105. Debug.Assert(sprite != null);
  106. Debug.Assert(m_DefaultMesh != null);
  107. var meshCache = sprite.GetMesh();
  108. Debug.Assert(meshCache != null);
  109. int width, height;
  110. meshCache.textureDataProvider.GetTextureActualWidthAndHeight(out width, out height);
  111. var uvScale = new Vector2(1f / width, 1f / height);
  112. Vector3 position = sprite.textureRect.position;
  113. var size = sprite.textureRect.size;
  114. var vertices = new List<Vector3>()
  115. {
  116. Vector3.zero,
  117. new Vector3(0f, size.y, 0f),
  118. new Vector3(size.x, 0f, 0f),
  119. size,
  120. };
  121. var uvs = new List<Vector2>()
  122. {
  123. Vector3.Scale(vertices[0] + position, uvScale),
  124. Vector3.Scale(vertices[1] + position, uvScale),
  125. Vector3.Scale(vertices[2] + position, uvScale),
  126. Vector3.Scale(vertices[3] + position, uvScale),
  127. };
  128. m_DefaultMesh.SetVertices(vertices);
  129. m_DefaultMesh.SetUVs(0, uvs);
  130. m_DefaultMesh.SetColors(new List<Color>
  131. {
  132. Color.black,
  133. Color.black,
  134. Color.black,
  135. Color.black
  136. });
  137. m_DefaultMesh.SetIndices(new int[]
  138. {
  139. 0, 1, 3, 0, 3, 2
  140. },
  141. MeshTopology.Triangles, 0);
  142. m_DefaultMesh.UploadMeshData(false);
  143. }
  144. public void SetMeshDirty()
  145. {
  146. m_MeshDirty = true;
  147. }
  148. public void SetVerticesDirty()
  149. {
  150. m_VerticesDirty = true;
  151. }
  152. public void SetSkinningDirty()
  153. {
  154. m_SkinningDirty = true;
  155. }
  156. public void SetWeightsDirty()
  157. {
  158. m_WeightsDirty = true;
  159. }
  160. public void SetIndicesDirty()
  161. {
  162. m_IndicesDirty = true;
  163. }
  164. public void SetColorsDirty()
  165. {
  166. m_ColorsDirty = true;
  167. }
  168. public void Prepare()
  169. {
  170. var meshChanged = false;
  171. var meshCache = sprite.GetMesh();
  172. Debug.Assert(meshCache != null);
  173. m_MeshDirty |= m_Vertices.Count != meshCache.vertices.Count;
  174. if (m_MeshDirty)
  175. {
  176. m_Mesh.Clear();
  177. m_VerticesDirty = true;
  178. m_WeightsDirty = true;
  179. m_IndicesDirty = true;
  180. m_SkinningDirty = true;
  181. m_MeshDirty = false;
  182. }
  183. if (m_VerticesDirty)
  184. {
  185. m_Vertices.Clear();
  186. m_TexCoords.Clear();
  187. int width, height;
  188. meshCache.textureDataProvider.GetTextureActualWidthAndHeight(out width, out height);
  189. var uvScale = new Vector2(1f / width, 1f / height);
  190. foreach (var vertex in meshCache.vertices)
  191. {
  192. m_Vertices.Add(vertex.position);
  193. m_TexCoords.Add(Vector2.Scale(vertex.position + sprite.textureRect.position, uvScale));
  194. }
  195. m_Mesh.SetVertices(m_Vertices);
  196. m_Mesh.SetUVs(0, m_TexCoords);
  197. meshChanged = true;
  198. m_VerticesDirty = false;
  199. }
  200. if (m_WeightsDirty)
  201. {
  202. m_Weights.Clear();
  203. for (int i = 0; i < meshCache.vertices.Count; ++i)
  204. {
  205. var vertex = meshCache.vertices[i];
  206. m_Weights.Add(vertex.editableBoneWeight.ToBoneWeight(true));
  207. }
  208. SetColorsDirty();
  209. meshChanged = true;
  210. m_WeightsDirty = false;
  211. }
  212. if (m_ColorsDirty)
  213. {
  214. PrepareColors();
  215. m_Mesh.SetColors(m_Colors);
  216. meshChanged = true;
  217. m_ColorsDirty = false;
  218. }
  219. if (m_IndicesDirty)
  220. {
  221. m_Mesh.SetTriangles(meshCache.indices, 0);
  222. meshChanged = true;
  223. m_IndicesDirty = false;
  224. }
  225. if (m_SkinningDirty)
  226. {
  227. if (enableSkinning && canSkin)
  228. {
  229. SkinVertices();
  230. m_Mesh.SetVertices(m_SkinnedVertices);
  231. meshChanged = true;
  232. }
  233. m_SkinningDirty = false;
  234. }
  235. if (meshChanged)
  236. {
  237. m_Mesh.UploadMeshData(false);
  238. m_Mesh.RecalculateBounds();
  239. skinningCache.events.meshPreviewChanged.Invoke(this);
  240. }
  241. }
  242. private void PrepareColors()
  243. {
  244. var bones = sprite.GetBonesFromMode();
  245. Debug.Assert(bones != null);
  246. m_Colors.Clear();
  247. for (var i = 0; i < m_Weights.Count; ++i)
  248. {
  249. var boneWeight = m_Weights[i];
  250. var weightSum = 0f;
  251. var color = Color.black;
  252. for (var j = 0; j < 4; ++j)
  253. {
  254. var boneIndex = boneWeight.GetBoneIndex(j);
  255. var weight = boneWeight.GetWeight(j);
  256. if (boneIndex >= 0 && boneIndex < bones.Length)
  257. color += bones[boneIndex].bindPoseColor * weight;
  258. weightSum += weight;
  259. }
  260. color.a = 1f;
  261. m_Colors.Add(Color.Lerp(Color.black, color, weightSum));
  262. }
  263. }
  264. private void SkinVertices()
  265. {
  266. Debug.Assert(canSkin);
  267. Debug.Assert(sprite != null);
  268. var bones = sprite.GetBonesFromMode();
  269. var originMatrix = Matrix4x4.TRS(sprite.pivotRectSpace, Quaternion.identity, Vector3.one);
  270. var originInverseMatrix = originMatrix.inverse;
  271. var spriteMatrix = sprite.GetLocalToWorldMatrixFromMode();
  272. var spriteMatrixInv = spriteMatrix.inverse;
  273. m_SkinnedVertices.Clear();
  274. m_SkinningMatrices.Clear();
  275. for (int i = 0; i < bones.Length; ++i)
  276. m_SkinningMatrices.Add(spriteMatrixInv * originInverseMatrix * bones[i].localToWorldMatrix * bones[i].bindPose.matrix.inverse * spriteMatrix);
  277. for (int i = 0; i < m_Vertices.Count; ++i)
  278. {
  279. var position = m_Vertices[i];
  280. BoneWeight boneWeight = m_Weights[i];
  281. float weightSum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3;
  282. if (weightSum > 0f)
  283. {
  284. var weightSumInv = 1f / weightSum;
  285. var skinnedPosition = m_SkinningMatrices[boneWeight.boneIndex0].MultiplyPoint3x4(position) * boneWeight.weight0 * weightSumInv +
  286. m_SkinningMatrices[boneWeight.boneIndex1].MultiplyPoint3x4(position) * boneWeight.weight1 * weightSumInv +
  287. m_SkinningMatrices[boneWeight.boneIndex2].MultiplyPoint3x4(position) * boneWeight.weight2 * weightSumInv +
  288. m_SkinningMatrices[boneWeight.boneIndex3].MultiplyPoint3x4(position) * boneWeight.weight3 * weightSumInv;
  289. position = Vector3.Lerp(position, skinnedPosition, weightSum);
  290. }
  291. m_SkinnedVertices.Add(position);
  292. }
  293. }
  294. protected override void OnAfterDeserialize()
  295. {
  296. SetMeshDirty();
  297. }
  298. }
  299. }