summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs')
-rw-r--r--Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs158
1 files changed, 158 insertions, 0 deletions
diff --git a/Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs b/Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs
new file mode 100644
index 00000000..23e233e5
--- /dev/null
+++ b/Assets/ThirdParty/VRM/MeshUtility/Runtime/BindposeGizmo.cs
@@ -0,0 +1,158 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+// using UniGLTF;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+
+namespace MeshUtility
+{
+ [DisallowMultipleComponent]
+ public class BindposeGizmo : MonoBehaviour
+ {
+ [SerializeField]
+ Mesh m_target;
+
+ [SerializeField]
+ float[] m_boneWeights;
+
+ [SerializeField, Range(0.1f, 1.0f)]
+ float m_gizmoSize = 0.02f;
+
+ [SerializeField]
+ Color m_meshGizmoColor = Color.yellow;
+
+ [SerializeField]
+ Color m_bindGizmoColor = Color.red;
+
+ private void Reset()
+ {
+ var renderer = GetComponent<SkinnedMeshRenderer>();
+ if (renderer == null) return;
+ m_target = renderer.sharedMesh;
+ }
+
+#if UNITY_EDITOR
+ #region ToBindpose
+ [ContextMenu("ToBindpose")]
+ void ToBindpose()
+ {
+ var renderer = GetComponent<SkinnedMeshRenderer>();
+
+ var root =
+ renderer.bones
+ .Select(x => Ancestors(x).Reverse().ToArray())
+ .Aggregate((a, b) =>
+ {
+ int i = 0;
+ for (; i < a.Length && i < b.Length; ++i)
+ {
+ if (a[i] != b[i])
+ {
+ break;
+ }
+ }
+ return a.Take(i).ToArray();
+ })
+ .Last()
+ ;
+
+ var map = new Dictionary<Transform, Matrix4x4>();
+ for (int i = 0; i < renderer.bones.Length; ++i)
+ {
+ map[renderer.bones[i]] = m_target.bindposes[i];
+ }
+
+ {
+ var bones = Traverse(root);
+ Undo.RecordObjects(bones.ToArray(), "toBindpose");
+
+ foreach (var x in bones)
+ {
+ var bind = default(Matrix4x4);
+ if (map.TryGetValue(x, out bind))
+ {
+ var toWorld = renderer.transform.localToWorldMatrix * bind.inverse;
+ x.position = toWorld.GetColumn(3);
+ x.rotation = toWorld.ExtractRotation();
+ }
+ }
+
+ //EditorUtility.SetDirty(transform);
+ }
+ }
+
+ IEnumerable<Transform> Traverse(Transform self)
+ {
+ yield return self;
+
+ foreach (Transform child in self)
+ {
+ foreach (var x in Traverse(child))
+ {
+ yield return x;
+ }
+ }
+ }
+
+ IEnumerable<Transform> Ancestors(Transform self)
+ {
+ yield return self;
+
+ if (self.parent != null)
+ {
+ foreach (var x in Ancestors(self.parent))
+ {
+ yield return x;
+ }
+ }
+ }
+ #endregion
+#endif
+
+ private void OnDrawGizmos()
+ {
+ if (m_target == null)
+ {
+ return;
+ }
+
+ Gizmos.matrix = transform.localToWorldMatrix;
+
+ if (m_target.bindposes != null && m_target.bindposes.Length > 0)
+ {
+ if (m_boneWeights == null || m_boneWeights.Length != m_target.bindposes.Length)
+ {
+ m_boneWeights = new float[m_target.bindposes.Length];
+ foreach (var bw in m_target.boneWeights)
+ {
+ if (bw.weight0 > 0) m_boneWeights[bw.boneIndex0] += bw.weight0;
+ if (bw.weight1 > 0) m_boneWeights[bw.boneIndex1] += bw.weight1;
+ if (bw.weight2 > 0) m_boneWeights[bw.boneIndex2] += bw.weight2;
+ if (bw.weight3 > 0) m_boneWeights[bw.boneIndex3] += bw.weight3;
+ }
+ }
+
+ Gizmos.color = m_meshGizmoColor;
+ Gizmos.DrawWireMesh(m_target);
+
+ for (var i = 0; i < m_target.bindposes.Length; ++i)
+ {
+ var color = m_bindGizmoColor * m_boneWeights[i];
+ color.a = 1.0f;
+ Gizmos.color = color;
+
+ Gizmos.matrix = transform.localToWorldMatrix * m_target.bindposes[i].inverse;
+ Gizmos.DrawWireCube(Vector3.zero, Vector3.one * m_gizmoSize);
+ }
+ }
+ else
+ {
+ Gizmos.color = Color.gray;
+ Gizmos.DrawWireMesh(m_target);
+ }
+ }
+ }
+}