SmoothingUtility.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace UnityEditor.U2D.Animation
  5. {
  6. internal class SmoothingUtility
  7. {
  8. private static float[,] m_DataInTemp;
  9. private static float[,] m_DataOutTemp;
  10. private static float[] m_DenominatorTemp;
  11. private static EditableBoneWeight s_BoneWeight = new EditableBoneWeight();
  12. public static void SmoothWeights(BoneWeight[] boneWeightIn, IList<int> indices, int boneCount, out BoneWeight[] boneWeightOut)
  13. {
  14. SmoothWeights(boneWeightIn, indices, boneCount, 1, out boneWeightOut);
  15. }
  16. public static void SmoothWeights(BoneWeight[] boneWeightIn, IList<int> indices, int boneCount, int iterations, out BoneWeight[] boneWeightOut)
  17. {
  18. Debug.Assert(boneWeightIn != null);
  19. boneWeightOut = new BoneWeight[boneWeightIn.Length];
  20. PrepareTempBuffers(boneWeightIn.Length, boneCount);
  21. for (int i = 0; i < boneWeightIn.Length; ++i)
  22. {
  23. s_BoneWeight.SetFromBoneWeight(boneWeightIn[i]);
  24. for (var j = 0; j < s_BoneWeight.Count; ++j)
  25. {
  26. if (s_BoneWeight[j].enabled)
  27. m_DataInTemp[i, s_BoneWeight[j].boneIndex] = s_BoneWeight[j].weight;
  28. }
  29. }
  30. for (var i = 0; i < iterations; ++i)
  31. SmoothPerVertexData(indices, m_DataInTemp, m_DataOutTemp);
  32. for (var i = 0; i < boneWeightIn.Length; ++i)
  33. {
  34. s_BoneWeight.Clear();
  35. for (var j = 0; j < boneCount; ++j)
  36. {
  37. var weight = m_DataOutTemp[i, j];
  38. var boneIndex = weight > 0f ? j : 0;
  39. s_BoneWeight.AddChannel(boneIndex, weight, weight > 0);
  40. }
  41. s_BoneWeight.Clamp(4);
  42. s_BoneWeight.Normalize();
  43. boneWeightOut[i] = s_BoneWeight.ToBoneWeight(false);
  44. }
  45. }
  46. public static void SmoothPerVertexData(IList<int> indices, float[,] dataIn, float[,] dataOut)
  47. {
  48. Debug.Assert(dataIn != null);
  49. Debug.Assert(dataOut != null);
  50. Debug.Assert(dataIn != dataOut);
  51. Debug.Assert(dataIn.Length == dataOut.Length);
  52. int rowLength = dataIn.GetLength(0);
  53. int colLength = dataIn.GetLength(1);
  54. PrepareDenominatorBuffer(rowLength);
  55. for (int i = 0; i < indices.Count / 3; ++i)
  56. {
  57. for (int j = 0; j < 3; ++j)
  58. {
  59. int j1 = (j + 1) % 3;
  60. int j2 = (j + 2) % 3;
  61. for (int k = 0; k < colLength; ++k)
  62. dataOut[indices[i * 3 + j], k] += dataIn[indices[i * 3 + j1], k] + dataIn[indices[i * 3 + j2], k];
  63. m_DenominatorTemp[indices[i * 3 + j]] += 2;
  64. }
  65. }
  66. for (int i = 0; i < rowLength; ++i)
  67. {
  68. var dInv = 1f / Mathf.Max(1f, m_DenominatorTemp[i]);
  69. for (int j = 0; j < colLength; ++j)
  70. dataOut[i, j] *= dInv;
  71. }
  72. }
  73. private static void PrepareDenominatorBuffer(int rowLength)
  74. {
  75. if (m_DenominatorTemp == null || m_DenominatorTemp.Length != rowLength)
  76. m_DenominatorTemp = new float[rowLength];
  77. else
  78. Array.Clear(m_DenominatorTemp, 0, m_DenominatorTemp.Length);
  79. }
  80. private static void PrepareTempBuffers(int rowLength, int colLength)
  81. {
  82. if (m_DataInTemp == null || m_DataInTemp.GetLength(0) != rowLength || m_DataInTemp.GetLength(1) != colLength)
  83. m_DataInTemp = new float[rowLength, colLength];
  84. else
  85. Array.Clear(m_DataInTemp, 0, m_DataInTemp.Length);
  86. if (m_DataOutTemp == null || m_DataOutTemp.GetLength(0) != rowLength || m_DataOutTemp.GetLength(1) != colLength)
  87. m_DataOutTemp = new float[rowLength, colLength];
  88. else
  89. Array.Clear(m_DataOutTemp, 0, m_DataOutTemp.Length);
  90. }
  91. }
  92. }