public static int GetClosestTriangle(Vector2 vert, out Barycentric bestBary)
        {
            float minDist = Mathf.Infinity;
            int   minID   = -1;

            bestBary = default;

            for (int ii = 0; ii < fromt.Length; ii += 3)
            {
                Vector2 a = fromv[fromt[ii + 0]];
                Vector2 b = fromv[fromt[ii + 1]];
                Vector2 c = fromv[fromt[ii + 2]];

                var unclampedBary = new Barycentric(a, b, c, vert);
                var div           = Mathf.Max(1, unclampedBary.u + unclampedBary.v);
                var u             = Mathf.Clamp01(unclampedBary.u / div);
                var v             = Mathf.Clamp01(unclampedBary.v / div);
                var bary          = new Barycentric(u, v, 1 - u - v);

                var clampedPoint = bary.Interpolate(a, b, c);

                var dist = (clampedPoint - vert).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist  = dist;
                    bestBary = bary;
                    minID    = ii;
                }
            }

            return(minID);
        }
        public static void FillSorted(int minID, Barycentric bestBary, out int boneC)
        {
            AddSample(minID, bestBary, 1);

            Sort();

            Normalize(out boneC);
        }
 public static void AddSample(int minID, Barycentric bestBary, float w)
 {
     sums.Clear();
     for (int boneChannel = 0; boneChannel < 4; boneChannel++)
     {
         for (int triCorner = 0; triCorner < 3; triCorner++)
         {
             var weight = Get(fromw[fromt[minID + triCorner]], boneChannel, out int boneID) * bestBary[triCorner] * w;
             if (weight > 0)
             {
                 if (sums.ContainsKey(boneID))
                 {
                     sums[boneID] += weight;
                 }
                 else
                 {
                     sums.Add(boneID, weight);
                 }
             }
         }
     }
 }