summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs')
-rw-r--r--Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs166
1 files changed, 166 insertions, 0 deletions
diff --git a/Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs b/Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs
new file mode 100644
index 00000000..64ee850d
--- /dev/null
+++ b/Assets/ThirdParty/VRM/MeshUtility/Runtime/BoneMeshEraser.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+
+namespace MeshUtility
+{
+ public static class BoneMeshEraser
+ {
+ private struct ExcludeBoneIndex
+ {
+ public readonly bool Bone0;
+ public readonly bool Bone1;
+ public readonly bool Bone2;
+ public readonly bool Bone3;
+
+ public ExcludeBoneIndex(bool bone0, bool bone1, bool bone2, bool bone3)
+ {
+ Bone0 = bone0;
+ Bone1 = bone1;
+ Bone2 = bone2;
+ Bone3 = bone3;
+ }
+ }
+
+ [Serializable]
+ public struct EraseBone
+ {
+ public Transform Bone;
+ public bool Erase;
+
+ public override string ToString()
+ {
+ return Bone.name + ":" + Erase;
+ }
+ }
+
+ static int ExcludeTriangles(int[] triangles, BoneWeight[] bws, int[] exclude)
+ {
+ int count = 0;
+ if (bws != null && bws.Length > 0)
+ {
+ for (int i = 0; i < triangles.Length; i += 3)
+ {
+ var a = triangles[i];
+ var b = triangles[i + 1];
+ var c = triangles[i + 2];
+
+ {
+ var bw = bws[a];
+ var eb = AreBoneContains(ref exclude, bw.boneIndex0, bw.boneIndex1, bw.boneIndex2, bw.boneIndex3);
+ if (bw.weight0 > 0 && eb.Bone0) continue;
+ if (bw.weight1 > 0 && eb.Bone1) continue;
+ if (bw.weight2 > 0 && eb.Bone2) continue;
+ if (bw.weight3 > 0 && eb.Bone3) continue;
+ }
+ {
+ var bw = bws[b];
+ var eb = AreBoneContains(ref exclude, bw.boneIndex0, bw.boneIndex1, bw.boneIndex2, bw.boneIndex3);
+ if (bw.weight0 > 0 && eb.Bone0) continue;
+ if (bw.weight1 > 0 && eb.Bone1) continue;
+ if (bw.weight2 > 0 && eb.Bone2) continue;
+ if (bw.weight3 > 0 && eb.Bone3) continue;
+ }
+ {
+ var bw = bws[c];
+ var eb = AreBoneContains(ref exclude, bw.boneIndex0, bw.boneIndex1, bw.boneIndex2, bw.boneIndex3);
+ if (bw.weight0 > 0 && eb.Bone0) continue;
+ if (bw.weight1 > 0 && eb.Bone1) continue;
+ if (bw.weight2 > 0 && eb.Bone2) continue;
+ if (bw.weight3 > 0 && eb.Bone3) continue;
+ }
+
+ triangles[count++] = a;
+ triangles[count++] = b;
+ triangles[count++] = c;
+ }
+ }
+
+ return count;
+ }
+
+ private static ExcludeBoneIndex AreBoneContains(ref int[] exclude, int boneIndex0, int boneIndex1,
+ int boneIndex2, int boneIndex3)
+ {
+ var b0 = false;
+ var b1 = false;
+ var b2 = false;
+ var b3 = false;
+ for (int i = 0; i < exclude.Length; i++)
+ {
+ if (exclude[i] == boneIndex0)
+ {
+ b0 = true;
+ continue;
+ }
+
+ if (exclude[i] == boneIndex1)
+ {
+ b1 = true;
+ continue;
+ }
+
+ if (exclude[i] == boneIndex2)
+ {
+ b2 = true;
+ continue;
+ }
+
+ if (exclude[i] == boneIndex3)
+ {
+ b3 = true;
+ }
+ }
+
+ return new ExcludeBoneIndex(b0, b1, b2, b3);
+ }
+
+ public static Mesh CreateErasedMesh(Mesh src, int[] eraseBoneIndices)
+ {
+ /*
+ Debug.LogFormat("{0} exclude: {1}",
+ src.name,
+ String.Join(", ", eraseBoneIndices.Select(x => x.ToString()).ToArray())
+ );
+ */
+ var mesh = new Mesh();
+ mesh.name = src.name + "(erased)";
+
+#if UNITY_2017_3_OR_NEWER
+ mesh.indexFormat = src.indexFormat;
+#endif
+
+ mesh.vertices = src.vertices;
+ mesh.normals = src.normals;
+ mesh.uv = src.uv;
+ mesh.tangents = src.tangents;
+ mesh.boneWeights = src.boneWeights;
+ mesh.bindposes = src.bindposes;
+ mesh.subMeshCount = src.subMeshCount;
+ for (int i = 0; i < src.subMeshCount; ++i)
+ {
+ var indices = src.GetIndices(i);
+ var count = ExcludeTriangles(indices, mesh.boneWeights, eraseBoneIndices);
+ var dst = new int[count];
+ Array.Copy(indices, 0, dst, 0, count);
+ mesh.SetIndices(dst, MeshTopology.Triangles, i);
+ }
+
+ return mesh;
+ }
+
+ public static IEnumerable<Transform> Ancestor(this Transform t)
+ {
+ yield return t;
+
+ if (t.parent != null)
+ {
+ foreach (var x in Ancestor(t.parent))
+ {
+ yield return x;
+ }
+ }
+ }
+ }
+}