diff --git a/Assets/VRM/Runtime/SpringBone/TransformExtensions.cs b/Assets/VRM/Runtime/Extensions/TransformExtensions.cs similarity index 100% rename from Assets/VRM/Runtime/SpringBone/TransformExtensions.cs rename to Assets/VRM/Runtime/Extensions/TransformExtensions.cs diff --git a/Assets/VRM/Runtime/SpringBone/TransformExtensions.cs.meta b/Assets/VRM/Runtime/Extensions/TransformExtensions.cs.meta similarity index 100% rename from Assets/VRM/Runtime/SpringBone/TransformExtensions.cs.meta rename to Assets/VRM/Runtime/Extensions/TransformExtensions.cs.meta diff --git a/Assets/VRM/Runtime/SpringBone/Logic.meta b/Assets/VRM/Runtime/SpringBone/Logic.meta new file mode 100644 index 000000000..778166f77 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b3d9c467d3da3e4aa800f2a9229768c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs new file mode 100644 index 000000000..546673013 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SceneInfo + { + public IReadOnlyList RootBones; + public Transform Center; + public VRMSpringBoneColliderGroup[] ColliderGroups; + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta new file mode 100644 index 000000000..982e67800 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f9f3d46865885b4a8d559a5d962db5a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs new file mode 100644 index 000000000..a59c36e8c --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SphereCollider + { + public readonly Vector3 Position; + public readonly float Radius; + + public SphereCollider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider) + { + Position = transform.TransformPoint(collider.Offset); + var ls = transform.lossyScale; + var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z); + Radius = scale * collider.Radius; + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta new file mode 100644 index 000000000..998c40f98 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 102ef8d07b335ee42b6a198b5657ef80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs new file mode 100644 index 000000000..d15e48201 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace VRM.SpringBone +{ + /// + /// original from + /// http://rocketjump.skr.jp/unity3d/109/ + /// + class SpringBoneJoint + { + Transform m_transform; + public Transform Head => m_transform; + + private Vector3 m_boneAxis; + private Vector3 m_currentTail; + + private readonly float m_length; + private Vector3 m_localDir; + private Vector3 m_prevTail; + + public SpringBoneJoint(Transform center, Transform transform, Vector3 localChildPosition) + { + m_transform = transform; + var worldChildPosition = m_transform.TransformPoint(localChildPosition); + m_currentTail = center != null + ? center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + m_prevTail = m_currentTail; + LocalRotation = transform.localRotation; + m_boneAxis = localChildPosition.normalized; + m_length = localChildPosition.magnitude; + } + + public Vector3 Tail => m_transform.localToWorldMatrix.MultiplyPoint(m_boneAxis * m_length); + + private Quaternion LocalRotation { get; } + + float m_radius; + public void SetRadius(float radius) + { + m_radius = radius * m_transform.UniformedLossyScale(); + } + + private Quaternion ParentRotation => + m_transform.parent != null + ? m_transform.parent.rotation + : Quaternion.identity; + + public void Update(Transform center, + float stiffnessForce, float dragForce, Vector3 external, + List colliders) + { + var currentTail = center != null + ? center.TransformPoint(m_currentTail) + : m_currentTail; + var prevTail = center != null + ? center.TransformPoint(m_prevTail) + : m_prevTail; + + // verlet積分で次の位置を計算 + var nextTail = currentTail + + (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ) + + ParentRotation * LocalRotation * m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標 + + external; // 外力による移動量 + + // 長さをboneLengthに強制 + var position = m_transform.position; + nextTail = position + (nextTail - position).normalized * m_length; + + // Collisionで移動 + nextTail = Collision(colliders, nextTail); + + m_prevTail = center != null + ? center.InverseTransformPoint(currentTail) + : currentTail; + + m_currentTail = center != null + ? center.InverseTransformPoint(nextTail) + : nextTail; + + //回転を適用 + m_transform.rotation = ApplyRotation(nextTail); + } + + protected virtual Quaternion ApplyRotation(Vector3 nextTail) + { + var rotation = ParentRotation * LocalRotation; + return Quaternion.FromToRotation(rotation * m_boneAxis, + nextTail - m_transform.position) * rotation; + } + + protected virtual Vector3 Collision(List colliders, Vector3 nextTail) + { + foreach (var collider in colliders) + { + var r = m_radius + collider.Radius; + if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r)) + { + // ヒット。Colliderの半径方向に押し出す + var normal = (nextTail - collider.Position).normalized; + var posFromCollider = collider.Position + normal * (m_radius + collider.Radius); + // 長さをboneLengthに強制 + nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length; + } + } + return nextTail; + } + + public void DrawGizmo(Transform center, Color color) + { + var currentTail = center != null + ? center.TransformPoint(m_currentTail) + : m_currentTail; + var prevTail = center != null + ? center.TransformPoint(m_prevTail) + : m_prevTail; + + Gizmos.color = Color.gray; + Gizmos.DrawLine(currentTail, prevTail); + Gizmos.DrawWireSphere(prevTail, m_radius); + + Gizmos.color = color; + Gizmos.DrawLine(currentTail, m_transform.position); + Gizmos.DrawWireSphere(currentTail, m_radius); + } + } + +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta new file mode 100644 index 000000000..70dd7502d --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2602939771f9eb2428b140e10fa899f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs new file mode 100644 index 000000000..bc6209047 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +namespace VRM.SpringBone +{ + struct SpringBoneSettings + { + public float StiffnessForce; + public Vector3 GravityDir; + public float GravityPower; + public float HitRadius; + public float DragForce; + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta new file mode 100644 index 000000000..b02b7795e --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c979a822d9cd3754db84ce10c42f3b56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs new file mode 100644 index 000000000..98d5d433d --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -0,0 +1,158 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace VRM.SpringBone +{ + /// + /// 同じ設定のスプリングをまとめて処理する。 + /// + /// root o-o-o-x tail + /// + /// [vrm0] tail は 7cm 遠にダミーの joint があるようにふるまう。 + /// + /// + class SpringBoneSystem + { + Dictionary m_initialLocalRotationMap; + List m_joints = new(); + List m_colliders = new(); + + public void SetLocalRotationsIdentity() + { + foreach (var verlet in m_joints) verlet.Head.localRotation = Quaternion.identity; + } + + public void Setup(SceneInfo scene, bool force) + { + if (force || m_initialLocalRotationMap == null) + { + m_initialLocalRotationMap = new Dictionary(); + } + else + { + foreach (var kv in m_initialLocalRotationMap) kv.Key.localRotation = kv.Value; + m_initialLocalRotationMap.Clear(); + } + m_joints.Clear(); + + foreach (var go in scene.RootBones) + { + if (go != null) + { + foreach (var x in go.transform.GetComponentsInChildren(true)) m_initialLocalRotationMap[x] = x.localRotation; + + SetupRecursive(scene.Center, go); + } + } + } + + private static IEnumerable GetChildren(Transform parent) + { + for (var i = 0; i < parent.childCount; ++i) yield return parent.GetChild(i); + } + + private void SetupRecursive(Transform center, Transform parent) + { + Vector3 localPosition = default; + Vector3 scale = default; + if (parent.childCount == 0) + { + // 子ノードが無い。7cm 固定 + var delta = parent.position - parent.parent.position; + var childPosition = parent.position + delta.normalized * 0.07f * parent.UniformedLossyScale(); + localPosition = parent.worldToLocalMatrix.MultiplyPoint(childPosition); // cancel scale + scale = parent.lossyScale; + } + else + { + var firstChild = GetChildren(parent).First(); + localPosition = firstChild.localPosition; + scale = firstChild.lossyScale; + } + m_joints.Add(new SpringBone.SpringBoneJoint(center, parent, + new Vector3( + localPosition.x * scale.x, + localPosition.y * scale.y, + localPosition.z * scale.z + ))) + ; + + foreach (Transform child in parent) SetupRecursive(center, child); + } + + + public void UpdateProcess(float deltaTime, + SceneInfo scene, + SpringBoneSettings settings + ) + { + if (m_joints == null || m_joints.Count == 0) + { + if (scene.RootBones == null) return; + Setup(scene, false); + } + + m_colliders.Clear(); + if (scene.ColliderGroups != null) + { + foreach (var group in scene.ColliderGroups) + { + if (group != null) + { + foreach (var collider in group.Colliders) + { + m_colliders.Add(new SphereCollider(group.transform, collider)); + } + } + } + } + + var stiffness = settings.StiffnessForce * deltaTime; + var external = settings.GravityDir * (settings.GravityPower * deltaTime); + + foreach (var verlet in m_joints) + { + verlet.SetRadius(settings.HitRadius); + verlet.Update(scene.Center, + stiffness, + settings.DragForce, + external, + m_colliders + ); + } + } + + public void PlayingGizmo(Transform m_center, Color m_gizmoColor) + { + foreach (var verlet in m_joints) + { + verlet.DrawGizmo(m_center, m_gizmoColor); + } + } + + public void EditorGizmo(Transform head, float m_hitRadius) + { + Vector3 childPosition; + Vector3 scale; + if (head.childCount == 0) + { + // 子ノードが無い。7cm 固定 + var delta = head.position - head.parent.position; + childPosition = head.position + delta.normalized * 0.07f * head.UniformedLossyScale(); + scale = head.lossyScale; + } + else + { + var firstChild = GetChildren(head).First(); + childPosition = firstChild.position; + scale = firstChild.lossyScale; + } + + Gizmos.DrawLine(head.position, childPosition); + Gizmos.DrawWireSphere(childPosition, m_hitRadius * scale.x); + + foreach (Transform child in head) EditorGizmo(child, m_hitRadius); + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta new file mode 100644 index 000000000..9ba5abade --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9cc72abc9e20895419ca606484cc7dc0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 5e9d8c7d0..2e971d2cc 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.Linq; using UnityEngine; -using UniGLTF; namespace VRM { @@ -13,30 +11,16 @@ namespace VRM // [RequireComponent(typeof(VCIObject))] public sealed class VRMSpringBone : MonoBehaviour { - [SerializeField] - public string m_comment; - + [SerializeField] public string m_comment; [SerializeField] private Color m_gizmoColor = Color.yellow; - - [SerializeField] - public float m_stiffnessForce = 1.0f; - + [SerializeField] public float m_stiffnessForce = 1.0f; [SerializeField] public float m_gravityPower; - [SerializeField] public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0); - [SerializeField][Range(0, 1)] public float m_dragForce = 0.4f; - [SerializeField] public Transform m_center; - [SerializeField] public List RootBones = new List(); - Dictionary m_initialLocalRotationMap; - - [SerializeField] - public float m_hitRadius = 0.02f; - - [SerializeField] - public VRMSpringBoneColliderGroup[] ColliderGroups; + [SerializeField] public float m_hitRadius = 0.02f; + [SerializeField] public VRMSpringBoneColliderGroup[] ColliderGroups; public enum SpringBoneUpdateType { @@ -44,211 +28,39 @@ namespace VRM FixedUpdate, Manual, } - [SerializeField] - public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate; + [SerializeField] public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate; - /// - /// original from - /// http://rocketjump.skr.jp/unity3d/109/ - /// - private class VRMSpringBoneLogic - { - Transform m_transform; - public Transform Head => m_transform; - - private Vector3 m_boneAxis; - private Vector3 m_currentTail; - - private readonly float m_length; - private Vector3 m_localDir; - private Vector3 m_prevTail; - - public VRMSpringBoneLogic(Transform center, Transform transform, Vector3 localChildPosition) - { - m_transform = transform; - var worldChildPosition = m_transform.TransformPoint(localChildPosition); - m_currentTail = center != null - ? center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - m_prevTail = m_currentTail; - LocalRotation = transform.localRotation; - m_boneAxis = localChildPosition.normalized; - m_length = localChildPosition.magnitude; - } - - public Vector3 Tail => m_transform.localToWorldMatrix.MultiplyPoint(m_boneAxis * m_length); - - private Quaternion LocalRotation { get; } - - float m_radius; - public void SetRadius(float radius) - { - m_radius = radius * m_transform.UniformedLossyScale(); - } - - private Quaternion ParentRotation => - m_transform.parent != null - ? m_transform.parent.rotation - : Quaternion.identity; - - public void Update(Transform center, - float stiffnessForce, float dragForce, Vector3 external, - List colliders) - { - var currentTail = center != null - ? center.TransformPoint(m_currentTail) - : m_currentTail; - var prevTail = center != null - ? center.TransformPoint(m_prevTail) - : m_prevTail; - - // verlet積分で次の位置を計算 - var nextTail = currentTail - + (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ) - + ParentRotation * LocalRotation * m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標 - + external; // 外力による移動量 - - // 長さをboneLengthに強制 - var position = m_transform.position; - nextTail = position + (nextTail - position).normalized * m_length; - - // Collisionで移動 - nextTail = Collision(colliders, nextTail); - - m_prevTail = center != null - ? center.InverseTransformPoint(currentTail) - : currentTail; - - m_currentTail = center != null - ? center.InverseTransformPoint(nextTail) - : nextTail; - - //回転を適用 - m_transform.rotation = ApplyRotation(nextTail); - } - - protected virtual Quaternion ApplyRotation(Vector3 nextTail) - { - var rotation = ParentRotation * LocalRotation; - return Quaternion.FromToRotation(rotation * m_boneAxis, - nextTail - m_transform.position) * rotation; - } - - protected virtual Vector3 Collision(List colliders, Vector3 nextTail) - { - foreach (var collider in colliders) - { - var r = m_radius + collider.Radius; - if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r)) - { - // ヒット。Colliderの半径方向に押し出す - var normal = (nextTail - collider.Position).normalized; - var posFromCollider = collider.Position + normal * (m_radius + collider.Radius); - // 長さをboneLengthに強制 - nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length; - } - } - return nextTail; - } - - public void DrawGizmo(Transform center, Color color) - { - var currentTail = center != null - ? center.TransformPoint(m_currentTail) - : m_currentTail; - var prevTail = center != null - ? center.TransformPoint(m_prevTail) - : m_prevTail; - - Gizmos.color = Color.gray; - Gizmos.DrawLine(currentTail, prevTail); - Gizmos.DrawWireSphere(prevTail, m_radius); - - Gizmos.color = color; - Gizmos.DrawLine(currentTail, m_transform.position); - Gizmos.DrawWireSphere(currentTail, m_radius); - } - } - - List m_verlet = new List(); + SpringBone.SpringBoneSystem m_system = new(); void Awake() { Setup(); } + SpringBone.SceneInfo Scene => new SpringBone.SceneInfo { RootBones = RootBones, Center = m_center }; + SpringBone.SpringBoneSettings Settings => new SpringBone.SpringBoneSettings + { + StiffnessForce = m_stiffnessForce, + GravityDir = m_gravityDir, + GravityPower = m_gravityPower, + HitRadius = m_hitRadius, + DragForce = m_dragForce, + }; + [ContextMenu("Reset bones")] public void Setup(bool force = false) { if (RootBones != null) { - if (force || m_initialLocalRotationMap == null) - { - m_initialLocalRotationMap = new Dictionary(); - } - else - { - foreach (var kv in m_initialLocalRotationMap) kv.Key.localRotation = kv.Value; - m_initialLocalRotationMap.Clear(); - } - m_verlet.Clear(); - - foreach (var go in RootBones) - { - if (go != null) - { - foreach (var x in go.transform.GetComponentsInChildren(true)) m_initialLocalRotationMap[x] = x.localRotation; - - SetupRecursive(m_center, go); - } - } + m_system.Setup(Scene, force); } } - public void SetLocalRotationsIdentity() - { - foreach (var verlet in m_verlet) verlet.Head.localRotation = Quaternion.identity; - } - - private static IEnumerable GetChildren(Transform parent) - { - for (var i = 0; i < parent.childCount; ++i) yield return parent.GetChild(i); - } - - private void SetupRecursive(Transform center, Transform parent) - { - Vector3 localPosition = default; - Vector3 scale = default; - if (parent.childCount == 0) - { - // 子ノードが無い。7cm 固定 - var delta = parent.position - parent.parent.position; - var childPosition = parent.position + delta.normalized * 0.07f * parent.UniformedLossyScale(); - localPosition = parent.worldToLocalMatrix.MultiplyPoint(childPosition); // cancel scale - scale = parent.lossyScale; - } - else - { - var firstChild = GetChildren(parent).First(); - localPosition = firstChild.localPosition; - scale = firstChild.lossyScale; - } - m_verlet.Add(new VRMSpringBoneLogic(center, parent, - new Vector3( - localPosition.x * scale.x, - localPosition.y * scale.y, - localPosition.z * scale.z - ))) - ; - - foreach (Transform child in parent) SetupRecursive(center, child); - } - void LateUpdate() { if (m_updateType == SpringBoneUpdateType.LateUpdate) { - UpdateProcess(Time.deltaTime); + m_system.UpdateProcess(Time.deltaTime, Scene, Settings); } } @@ -256,7 +68,7 @@ namespace VRM { if (m_updateType == SpringBoneUpdateType.FixedUpdate) { - UpdateProcess(Time.fixedDeltaTime); + m_system.UpdateProcess(Time.fixedDeltaTime, Scene, Settings); } } @@ -266,96 +78,14 @@ namespace VRM { throw new System.ArgumentException("require SpringBoneUpdateType.Manual"); } - UpdateProcess(deltaTime); - } - - public struct SphereCollider - { - // public Transform Transform; - public readonly Vector3 Position; - public readonly float Radius; - - public SphereCollider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider) - { - Position = transform.TransformPoint(collider.Offset); - var ls = transform.lossyScale; - var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z); - Radius = scale * collider.Radius; - } - } - - private List m_colliders = new List(); - private void UpdateProcess(float deltaTime) - { - if (m_verlet == null || m_verlet.Count == 0) - { - if (RootBones == null) return; - - Setup(); - } - - m_colliders.Clear(); - if (ColliderGroups != null) - { - foreach (var group in ColliderGroups) - { - if (group != null) - { - foreach (var collider in group.Colliders) - { - m_colliders.Add(new SphereCollider(group.transform, collider)); - } - } - } - } - - var stiffness = m_stiffnessForce * deltaTime; - var external = m_gravityDir * (m_gravityPower * deltaTime); - - foreach (var verlet in m_verlet) - { - verlet.SetRadius(m_hitRadius); - verlet.Update(m_center, - stiffness, - m_dragForce, - external, - m_colliders - ); - } - } - - void EditorGizmo(Transform head) - { - Vector3 childPosition; - Vector3 scale; - if (head.childCount == 0) - { - // 子ノードが無い。7cm 固定 - var delta = head.position - head.parent.position; - childPosition = head.position + delta.normalized * 0.07f * head.UniformedLossyScale(); - scale = head.lossyScale; - } - else - { - var firstChild = GetChildren(head).First(); - childPosition = firstChild.position; - scale = firstChild.lossyScale; - } - - Gizmos.DrawLine(head.position, childPosition); - Gizmos.DrawWireSphere(childPosition, m_hitRadius * scale.x); - - foreach (Transform child in head) EditorGizmo(child); + m_system.UpdateProcess(deltaTime, Scene, Settings); } private void OnDrawGizmosSelected() { if (Application.isPlaying) { - foreach (var verlet in m_verlet) - { - verlet.DrawGizmo(m_center, m_gizmoColor); - } + m_system.PlayingGizmo(m_center, m_gizmoColor); } else { @@ -365,7 +95,7 @@ namespace VRM { if (root != null) { - EditorGizmo(root.transform); + m_system.EditorGizmo(root.transform, m_hitRadius); } } }