From c270da62e120421f7adf04c08d994ab11746638b Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 30 Aug 2024 15:32:34 +0900 Subject: [PATCH 1/6] SpringBoneSystem --- .../SpringBone/Logic/SpringBoneJoint.cs | 129 --------------- .../SpringBone/Logic/SpringBoneJointState.cs | 147 ++++++++++++++++++ ...t.cs.meta => SpringBoneJointState.cs.meta} | 0 .../SpringBone/Logic/SpringBoneSystem.cs | 32 ++-- .../VRM/Runtime/SpringBone/VRMSpringBone.cs | 2 +- 5 files changed, 158 insertions(+), 152 deletions(-) delete mode 100644 Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs create mode 100644 Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs rename Assets/VRM/Runtime/SpringBone/Logic/{SpringBoneJoint.cs.meta => SpringBoneJointState.cs.meta} (100%) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs deleted file mode 100644 index d15e48201..000000000 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs +++ /dev/null @@ -1,129 +0,0 @@ -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/SpringBoneJointState.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs new file mode 100644 index 000000000..d2ac8b3c9 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs @@ -0,0 +1,147 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace VRM.SpringBone +{ + struct JointInit + { + public Vector3 BoneAxis; + public float Length; + public Quaternion LocalRotation; + + public Quaternion ApplyRotation(Transform m_transform, Vector3 nextTail) + { + var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; + return Quaternion.FromToRotation(rotation * BoneAxis, + nextTail - m_transform.position) * rotation; + } + }; + + struct JointState + { + public Vector3 CurrentTail; + public Vector3 PrevTail; + + public static JointState Init(Transform center, Transform transform, Vector3 localChildPosition) + { + var worldChildPosition = transform.TransformPoint(localChildPosition); + var tail = center != null + ? center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + return new JointState + { + CurrentTail = tail, + PrevTail = tail, + }; + } + + public static JointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) + { + return new JointState + { + PrevTail = center != null + ? center.InverseTransformPoint(currentTail) + : currentTail, + CurrentTail = center != null + ? center.InverseTransformPoint(nextTail) + : nextTail, + }; + } + + public JointState ToWorld(Transform center) + { + return new JointState + { + CurrentTail = center != null + ? center.TransformPoint(CurrentTail) + : CurrentTail, + PrevTail = center != null + ? center.TransformPoint(PrevTail) + : PrevTail, + }; + } + }; + + /// + /// original from + /// http://rocketjump.skr.jp/unity3d/109/ + /// + /// Joint 状態(初期・フレーム)を管理する + /// + class SpringBoneJointState + { + // 不変 + JointInit m_init; + // フレーム状態 + JointState m_state; + + public SpringBoneJointState(Transform center, Transform transform, Vector3 localChildPosition) + { + m_state = JointState.Init(center, transform, localChildPosition); + m_init = new JointInit + { + LocalRotation = transform.localRotation, + BoneAxis = localChildPosition.normalized, + Length = localChildPosition.magnitude, + }; + } + + public void Update(float deltaTime, Transform center, Transform m_transform, + SpringBoneSettings settings, + List colliders, bool calcScale = false) + { + var state = m_state.ToWorld(center); + + // verlet積分で次の位置を計算 + var scaleFactor = calcScale ? m_transform.UniformedLossyScale() : 1.0f; + var nextTail = state.CurrentTail + + (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ) + + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * m_init.LocalRotation * m_init.BoneAxis * settings.StiffnessForce * deltaTime * scaleFactor // 親の回転による子ボーンの移動目標 + + settings.GravityDir * (settings.GravityPower * deltaTime) * scaleFactor; // 外力による移動量 + + // 長さをboneLengthに強制 + var position = m_transform.position; + nextTail = position + (nextTail - position).normalized * m_init.Length; + + // Collisionで移動 + nextTail = Collision(m_transform, settings, colliders, nextTail); + + m_state = JointState.Make(center, currentTail: state.CurrentTail, nextTail: nextTail); + + //回転を適用 + m_transform.rotation = m_init.ApplyRotation(m_transform, nextTail); + } + + Vector3 Collision(Transform m_transform, SpringBoneSettings settings, List colliders, Vector3 nextTail) + { + foreach (var collider in colliders) + { + var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); + 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_init.Length; + } + } + return nextTail; + } + + public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color) + { + var state = m_state.ToWorld(center); + var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); + + Gizmos.color = Color.gray; + Gizmos.DrawLine(state.CurrentTail, state.PrevTail); + Gizmos.DrawWireSphere(state.PrevTail, m_radius); + + Gizmos.color = color; + Gizmos.DrawLine(state.CurrentTail, m_transform.position); + Gizmos.DrawWireSphere(state.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/SpringBoneJointState.cs.meta similarity index 100% rename from Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJoint.cs.meta rename to Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs.meta diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index 98d5d433d..2b7b0d517 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -15,14 +15,9 @@ namespace VRM.SpringBone class SpringBoneSystem { Dictionary m_initialLocalRotationMap; - List m_joints = new(); + List<(Transform, SpringBoneJointState)> 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) @@ -70,18 +65,18 @@ namespace VRM.SpringBone localPosition = firstChild.localPosition; scale = firstChild.lossyScale; } - m_joints.Add(new SpringBone.SpringBoneJoint(center, parent, + m_joints.Add(( + parent, + new SpringBoneJointState(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 @@ -108,26 +103,19 @@ namespace VRM.SpringBone } } - var stiffness = settings.StiffnessForce * deltaTime; - var external = settings.GravityDir * (settings.GravityPower * deltaTime); - - foreach (var verlet in m_joints) + foreach (var (transform, verlet) in m_joints) { - verlet.SetRadius(settings.HitRadius); - verlet.Update(scene.Center, - stiffness, - settings.DragForce, - external, + verlet.Update(deltaTime, scene.Center, transform, settings, m_colliders ); } } - public void PlayingGizmo(Transform m_center, Color m_gizmoColor) + public void PlayingGizmo(Transform m_center, SpringBoneSettings settings, Color m_gizmoColor) { - foreach (var verlet in m_joints) + foreach (var (transform, verlet) in m_joints) { - verlet.DrawGizmo(m_center, m_gizmoColor); + verlet.DrawGizmo(m_center, transform, settings, m_gizmoColor); } } diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index 2e971d2cc..a35a47e54 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -85,7 +85,7 @@ namespace VRM { if (Application.isPlaying) { - m_system.PlayingGizmo(m_center, m_gizmoColor); + m_system.PlayingGizmo(m_center, Settings, m_gizmoColor); } else { From ee68e48f0f398b145f79b17650900a04e4ad44f7 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 30 Aug 2024 17:09:21 +0900 Subject: [PATCH 2/6] rename --- .../SpringBone/Logic/SpringBoneJointInit.cs | 49 ++++++++ .../Logic/SpringBoneJointInit.cs.meta | 11 ++ .../SpringBone/Logic/SpringBoneJointState.cs | 105 ++++-------------- .../SpringBone/Logic/SpringBoneSystem.cs | 35 ++++-- 4 files changed, 102 insertions(+), 98 deletions(-) create mode 100644 Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs create mode 100644 Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs new file mode 100644 index 000000000..d4cad9ab3 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs @@ -0,0 +1,49 @@ +using UnityEngine; + +namespace VRM.SpringBone +{ + struct JointState + { + public Vector3 CurrentTail; + public Vector3 PrevTail; + + public static JointState Init(Transform center, Transform transform, Vector3 localChildPosition) + { + var worldChildPosition = transform.TransformPoint(localChildPosition); + var tail = center != null + ? center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + return new JointState + { + CurrentTail = tail, + PrevTail = tail, + }; + } + + public static JointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) + { + return new JointState + { + PrevTail = center != null + ? center.InverseTransformPoint(currentTail) + : currentTail, + CurrentTail = center != null + ? center.InverseTransformPoint(nextTail) + : nextTail, + }; + } + + public JointState ToWorld(Transform center) + { + return new JointState + { + CurrentTail = center != null + ? center.TransformPoint(CurrentTail) + : CurrentTail, + PrevTail = center != null + ? center.TransformPoint(PrevTail) + : PrevTail, + }; + } + }; +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta new file mode 100644 index 000000000..b68add524 --- /dev/null +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3bbcafd66c035184b8aa868b65c01c1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs index d2ac8b3c9..873bd7b22 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs @@ -3,113 +3,45 @@ using UnityEngine; namespace VRM.SpringBone { - struct JointInit - { - public Vector3 BoneAxis; - public float Length; - public Quaternion LocalRotation; - - public Quaternion ApplyRotation(Transform m_transform, Vector3 nextTail) - { - var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; - return Quaternion.FromToRotation(rotation * BoneAxis, - nextTail - m_transform.position) * rotation; - } - }; - - struct JointState - { - public Vector3 CurrentTail; - public Vector3 PrevTail; - - public static JointState Init(Transform center, Transform transform, Vector3 localChildPosition) - { - var worldChildPosition = transform.TransformPoint(localChildPosition); - var tail = center != null - ? center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - return new JointState - { - CurrentTail = tail, - PrevTail = tail, - }; - } - - public static JointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) - { - return new JointState - { - PrevTail = center != null - ? center.InverseTransformPoint(currentTail) - : currentTail, - CurrentTail = center != null - ? center.InverseTransformPoint(nextTail) - : nextTail, - }; - } - - public JointState ToWorld(Transform center) - { - return new JointState - { - CurrentTail = center != null - ? center.TransformPoint(CurrentTail) - : CurrentTail, - PrevTail = center != null - ? center.TransformPoint(PrevTail) - : PrevTail, - }; - } - }; - /// /// original from /// http://rocketjump.skr.jp/unity3d/109/ /// /// Joint 状態(初期・フレーム)を管理する /// - class SpringBoneJointState + struct SpringBoneJointInit { - // 不変 - JointInit m_init; - // フレーム状態 - JointState m_state; + public Vector3 BoneAxis; + public float Length; + public Quaternion LocalRotation; - public SpringBoneJointState(Transform center, Transform transform, Vector3 localChildPosition) + public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail) { - m_state = JointState.Init(center, transform, localChildPosition); - m_init = new JointInit - { - LocalRotation = transform.localRotation, - BoneAxis = localChildPosition.normalized, - Length = localChildPosition.magnitude, - }; + var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; + return Quaternion.FromToRotation(rotation * BoneAxis, + nextTail - m_transform.position) * rotation; } - public void Update(float deltaTime, Transform center, Transform m_transform, + public JointState Update(float deltaTime, Transform center, Transform m_transform, SpringBoneSettings settings, - List colliders, bool calcScale = false) + List colliders, JointState _state) { - var state = m_state.ToWorld(center); + var state = _state.ToWorld(center); // verlet積分で次の位置を計算 - var scaleFactor = calcScale ? m_transform.UniformedLossyScale() : 1.0f; var nextTail = state.CurrentTail + (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ) - + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * m_init.LocalRotation * m_init.BoneAxis * settings.StiffnessForce * deltaTime * scaleFactor // 親の回転による子ボーンの移動目標 - + settings.GravityDir * (settings.GravityPower * deltaTime) * scaleFactor; // 外力による移動量 + + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標 + + settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量 // 長さをboneLengthに強制 var position = m_transform.position; - nextTail = position + (nextTail - position).normalized * m_init.Length; + nextTail = position + (nextTail - position).normalized * Length; // Collisionで移動 nextTail = Collision(m_transform, settings, colliders, nextTail); - m_state = JointState.Make(center, currentTail: state.CurrentTail, nextTail: nextTail); - - //回転を適用 - m_transform.rotation = m_init.ApplyRotation(m_transform, nextTail); + return JointState.Make(center, currentTail: state.CurrentTail, nextTail: nextTail); } Vector3 Collision(Transform m_transform, SpringBoneSettings settings, List colliders, Vector3 nextTail) @@ -124,13 +56,13 @@ namespace VRM.SpringBone 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_init.Length; + nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * Length; } } return nextTail; } - public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color) + public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color, JointState m_state) { var state = m_state.ToWorld(center); var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); @@ -143,5 +75,6 @@ namespace VRM.SpringBone Gizmos.DrawLine(state.CurrentTail, m_transform.position); Gizmos.DrawWireSphere(state.CurrentTail, m_radius); } - } + + }; } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index 2b7b0d517..d7c6e17fe 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -15,7 +15,7 @@ namespace VRM.SpringBone class SpringBoneSystem { Dictionary m_initialLocalRotationMap; - List<(Transform, SpringBoneJointState)> m_joints = new(); + List<(Transform, SpringBoneJointInit, JointState)> m_joints = new(); List m_colliders = new(); public void Setup(SceneInfo scene, bool force) @@ -65,14 +65,21 @@ namespace VRM.SpringBone localPosition = firstChild.localPosition; scale = firstChild.lossyScale; } - m_joints.Add(( - parent, - new SpringBoneJointState(center, parent, - new Vector3( + + var localChildPosition = new Vector3( localPosition.x * scale.x, localPosition.y * scale.y, localPosition.z * scale.z - )))); + ); + m_joints.Add(( + parent, + new SpringBoneJointInit + { + LocalRotation = parent.localRotation, + BoneAxis = localChildPosition.normalized, + Length = localChildPosition.magnitude, + }, + JointState.Init(center, parent, localChildPosition))); foreach (Transform child in parent) SetupRecursive(center, child); } @@ -103,19 +110,23 @@ namespace VRM.SpringBone } } - foreach (var (transform, verlet) in m_joints) + for (int i = 0; i < m_joints.Count; ++i) { - verlet.Update(deltaTime, scene.Center, transform, settings, - m_colliders - ); + var (transform, init, state) = m_joints[i]; + var nextState = init.Update(deltaTime, scene.Center, transform, settings, m_colliders, state); + m_joints[i] = (transform, init, nextState); + + //回転を適用 + var r = init.CalcRotation(transform, nextState.CurrentTail); + transform.rotation = r; } } public void PlayingGizmo(Transform m_center, SpringBoneSettings settings, Color m_gizmoColor) { - foreach (var (transform, verlet) in m_joints) + foreach (var (transform, init, state) in m_joints) { - verlet.DrawGizmo(m_center, transform, settings, m_gizmoColor); + init.DrawGizmo(m_center, transform, settings, m_gizmoColor, state); } } From 2cc166f193b89822719f6dcd86c823d74b080c79 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 30 Aug 2024 17:32:27 +0900 Subject: [PATCH 3/6] collision --- .../SpringBone/Logic/SphereCollider.cs | 15 +++ .../SpringBone/Logic/SpringBoneJointInit.cs | 74 +++++++------- .../Logic/SpringBoneJointInit.cs.meta | 2 +- .../SpringBone/Logic/SpringBoneJointState.cs | 98 +++++++------------ .../Logic/SpringBoneJointState.cs.meta | 2 +- .../SpringBone/Logic/SpringBoneSystem.cs | 29 +++--- 6 files changed, 109 insertions(+), 111 deletions(-) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs index a59c36e8c..880ebeb49 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs @@ -14,5 +14,20 @@ namespace VRM.SpringBone var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z); Radius = scale * collider.Radius; } + + public Vector3 Collide(SpringBoneSettings settings, Transform m_transform, SpringBoneJointInit init, Vector3 nextTail) + { + var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); + var r = m_radius + Radius; + if (Vector3.SqrMagnitude(nextTail - Position) <= (r * r)) + { + // ヒット。Colliderの半径方向に押し出す + var normal = (nextTail - Position).normalized; + var posFromCollider = Position + normal * (m_radius + Radius); + // 長さをboneLengthに強制 + nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * init.Length; + } + return nextTail; + } } } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs index d4cad9ab3..59f8ce7e3 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs @@ -1,49 +1,57 @@ +using System.Collections.Generic; using UnityEngine; namespace VRM.SpringBone { - struct JointState + /// + /// original from + /// http://rocketjump.skr.jp/unity3d/109/ + /// + /// この型のフィールドはSpringBoneのライフサイクルを通じて不変。 + /// + struct SpringBoneJointInit { - public Vector3 CurrentTail; - public Vector3 PrevTail; + public Vector3 BoneAxis; + public float Length; + public Quaternion LocalRotation; - public static JointState Init(Transform center, Transform transform, Vector3 localChildPosition) + public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail) { - var worldChildPosition = transform.TransformPoint(localChildPosition); - var tail = center != null - ? center.InverseTransformPoint(worldChildPosition) - : worldChildPosition; - return new JointState - { - CurrentTail = tail, - PrevTail = tail, - }; + var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; + return Quaternion.FromToRotation(rotation * BoneAxis, + nextTail - m_transform.position) * rotation; } - public static JointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) + public Vector3 CalcNextTail(float deltaTime, Transform center, Transform m_transform, + SpringBoneSettings settings, SpringBoneJointState _state) { - return new JointState - { - PrevTail = center != null - ? center.InverseTransformPoint(currentTail) - : currentTail, - CurrentTail = center != null - ? center.InverseTransformPoint(nextTail) - : nextTail, - }; + var state = _state.ToWorld(center); + + // verlet積分で次の位置を計算 + var nextTail = state.CurrentTail + + (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ) + + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標 + + settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量 + + // 長さをboneLengthに強制 + var position = m_transform.position; + nextTail = position + (nextTail - position).normalized * Length; + return nextTail; } - public JointState ToWorld(Transform center) + public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color, SpringBoneJointState m_state) { - return new JointState - { - CurrentTail = center != null - ? center.TransformPoint(CurrentTail) - : CurrentTail, - PrevTail = center != null - ? center.TransformPoint(PrevTail) - : PrevTail, - }; + var state = m_state.ToWorld(center); + var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); + + Gizmos.color = Color.gray; + Gizmos.DrawLine(state.CurrentTail, state.PrevTail); + Gizmos.DrawWireSphere(state.PrevTail, m_radius); + + Gizmos.color = color; + Gizmos.DrawLine(state.CurrentTail, m_transform.position); + Gizmos.DrawWireSphere(state.CurrentTail, m_radius); } + }; } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta index b68add524..70dd7502d 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3bbcafd66c035184b8aa868b65c01c1d +guid: 2602939771f9eb2428b140e10fa899f2 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs index 873bd7b22..c54b74a5a 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs @@ -1,80 +1,52 @@ -using System.Collections.Generic; using UnityEngine; namespace VRM.SpringBone { /// - /// original from - /// http://rocketjump.skr.jp/unity3d/109/ - /// - /// Joint 状態(初期・フレーム)を管理する + /// 毎フレーム更新される Verlet 積分の位置状態 /// - struct SpringBoneJointInit + struct SpringBoneJointState { - public Vector3 BoneAxis; - public float Length; - public Quaternion LocalRotation; + public Vector3 CurrentTail; + public Vector3 PrevTail; - public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail) + public static SpringBoneJointState Init(Transform center, Transform transform, Vector3 localChildPosition) { - var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; - return Quaternion.FromToRotation(rotation * BoneAxis, - nextTail - m_transform.position) * rotation; - } - - public JointState Update(float deltaTime, Transform center, Transform m_transform, - SpringBoneSettings settings, - List colliders, JointState _state) - { - var state = _state.ToWorld(center); - - // verlet積分で次の位置を計算 - var nextTail = state.CurrentTail - + (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ) - + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標 - + settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量 - - // 長さをboneLengthに強制 - var position = m_transform.position; - nextTail = position + (nextTail - position).normalized * Length; - - // Collisionで移動 - nextTail = Collision(m_transform, settings, colliders, nextTail); - - return JointState.Make(center, currentTail: state.CurrentTail, nextTail: nextTail); - } - - Vector3 Collision(Transform m_transform, SpringBoneSettings settings, List colliders, Vector3 nextTail) - { - foreach (var collider in colliders) + var worldChildPosition = transform.TransformPoint(localChildPosition); + var tail = center != null + ? center.InverseTransformPoint(worldChildPosition) + : worldChildPosition; + return new SpringBoneJointState { - var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); - 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 * Length; - } - } - return nextTail; + CurrentTail = tail, + PrevTail = tail, + }; } - public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color, JointState m_state) + public static SpringBoneJointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) { - var state = m_state.ToWorld(center); - var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); - - Gizmos.color = Color.gray; - Gizmos.DrawLine(state.CurrentTail, state.PrevTail); - Gizmos.DrawWireSphere(state.PrevTail, m_radius); - - Gizmos.color = color; - Gizmos.DrawLine(state.CurrentTail, m_transform.position); - Gizmos.DrawWireSphere(state.CurrentTail, m_radius); + return new SpringBoneJointState + { + PrevTail = center != null + ? center.InverseTransformPoint(currentTail) + : currentTail, + CurrentTail = center != null + ? center.InverseTransformPoint(nextTail) + : nextTail, + }; } + public SpringBoneJointState ToWorld(Transform center) + { + return new SpringBoneJointState + { + CurrentTail = center != null + ? center.TransformPoint(CurrentTail) + : CurrentTail, + PrevTail = center != null + ? center.TransformPoint(PrevTail) + : PrevTail, + }; + } }; } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs.meta b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs.meta index 70dd7502d..b68add524 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs.meta +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2602939771f9eb2428b140e10fa899f2 +guid: 3bbcafd66c035184b8aa868b65c01c1d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index d7c6e17fe..84154bd18 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -4,18 +4,10 @@ using UnityEngine; namespace VRM.SpringBone { - /// - /// 同じ設定のスプリングをまとめて処理する。 - /// - /// root o-o-o-x tail - /// - /// [vrm0] tail は 7cm 遠にダミーの joint があるようにふるまう。 - /// - /// class SpringBoneSystem { Dictionary m_initialLocalRotationMap; - List<(Transform, SpringBoneJointInit, JointState)> m_joints = new(); + List<(Transform, SpringBoneJointInit, SpringBoneJointState)> m_joints = new(); List m_colliders = new(); public void Setup(SceneInfo scene, bool force) @@ -79,7 +71,7 @@ namespace VRM.SpringBone BoneAxis = localChildPosition.normalized, Length = localChildPosition.magnitude, }, - JointState.Init(center, parent, localChildPosition))); + SpringBoneJointState.Init(center, parent, localChildPosition))); foreach (Transform child in parent) SetupRecursive(center, child); } @@ -95,6 +87,7 @@ namespace VRM.SpringBone Setup(scene, false); } + // collider の収集 m_colliders.Clear(); if (scene.ColliderGroups != null) { @@ -113,11 +106,21 @@ namespace VRM.SpringBone for (int i = 0; i < m_joints.Count; ++i) { var (transform, init, state) = m_joints[i]; - var nextState = init.Update(deltaTime, scene.Center, transform, settings, m_colliders, state); - m_joints[i] = (transform, init, nextState); + + // Spring処理 + var nextTail = init.CalcNextTail(deltaTime, scene.Center, transform, settings, state); + + // Collision + foreach (var collider in m_colliders) + { + nextTail = collider.Collide(settings, transform, init, nextTail); + } + + // 状態更新 + m_joints[i] = (transform, init, SpringBoneJointState.Make(scene.Center, currentTail: state.CurrentTail, nextTail: nextTail)); //回転を適用 - var r = init.CalcRotation(transform, nextState.CurrentTail); + var r = init.CalcRotation(transform, nextTail); transform.rotation = r; } } From fc1b2a80fd2a7afde2d9508df53e6b9cd8a84a3e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 30 Aug 2024 17:37:30 +0900 Subject: [PATCH 4/6] comment --- .../Runtime/SpringBone/Logic/SpringBoneJointInit.cs | 10 ++++++++-- .../VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs index 59f8ce7e3..079706853 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs @@ -15,14 +15,20 @@ namespace VRM.SpringBone public float Length; public Quaternion LocalRotation; - public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail) + /// + /// しっぽの位置から回転を計算する + /// + public Quaternion WorldRotationFromTailPosition(Transform m_transform, Vector3 nextTail) { var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation; return Quaternion.FromToRotation(rotation * BoneAxis, nextTail - m_transform.position) * rotation; } - public Vector3 CalcNextTail(float deltaTime, Transform center, Transform m_transform, + /// + /// Verlet積分で次の位置を計算する + /// + public Vector3 VerletIntegration(float deltaTime, Transform center, Transform m_transform, SpringBoneSettings settings, SpringBoneJointState _state) { var state = _state.ToWorld(center); diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index 84154bd18..805f42fdc 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -108,7 +108,7 @@ namespace VRM.SpringBone var (transform, init, state) = m_joints[i]; // Spring処理 - var nextTail = init.CalcNextTail(deltaTime, scene.Center, transform, settings, state); + var nextTail = init.VerletIntegration(deltaTime, scene.Center, transform, settings, state); // Collision foreach (var collider in m_colliders) @@ -120,7 +120,7 @@ namespace VRM.SpringBone m_joints[i] = (transform, init, SpringBoneJointState.Make(scene.Center, currentTail: state.CurrentTail, nextTail: nextTail)); //回転を適用 - var r = init.CalcRotation(transform, nextTail); + var r = init.WorldRotationFromTailPosition(transform, nextTail); transform.rotation = r; } } From dba1788c2370766c862900ad01e6c5c301d88e44 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 30 Aug 2024 17:58:36 +0900 Subject: [PATCH 5/6] TryCollide --- .../Runtime/SpringBone/Logic/SphereCollider.cs | 15 +++++++++------ .../SpringBone/Logic/SpringBoneJointInit.cs | 8 ++------ .../Runtime/SpringBone/Logic/SpringBoneSystem.cs | 16 +++++++++++----- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs index 880ebeb49..46185aa8f 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs @@ -15,19 +15,22 @@ namespace VRM.SpringBone Radius = scale * collider.Radius; } - public Vector3 Collide(SpringBoneSettings settings, Transform m_transform, SpringBoneJointInit init, Vector3 nextTail) + public bool TryCollide(SpringBoneSettings settings, Transform transform, Vector3 nextTail, out Vector3 posFromCollider) { - var m_radius = settings.HitRadius * m_transform.UniformedLossyScale(); + var m_radius = settings.HitRadius * transform.UniformedLossyScale(); var r = m_radius + Radius; if (Vector3.SqrMagnitude(nextTail - Position) <= (r * r)) { // ヒット。Colliderの半径方向に押し出す var normal = (nextTail - Position).normalized; - var posFromCollider = Position + normal * (m_radius + Radius); - // 長さをboneLengthに強制 - nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * init.Length; + posFromCollider = Position + normal * (m_radius + Radius); + return true; + } + else + { + posFromCollider = default; + return false; } - return nextTail; } } } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs index 079706853..676224756 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs @@ -28,7 +28,7 @@ namespace VRM.SpringBone /// /// Verlet積分で次の位置を計算する /// - public Vector3 VerletIntegration(float deltaTime, Transform center, Transform m_transform, + public Vector3 VerletIntegration(float deltaTime, Transform center, Quaternion parentRotation, SpringBoneSettings settings, SpringBoneJointState _state) { var state = _state.ToWorld(center); @@ -36,12 +36,8 @@ namespace VRM.SpringBone // verlet積分で次の位置を計算 var nextTail = state.CurrentTail + (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ) - + (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標 + + parentRotation * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標 + settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量 - - // 長さをboneLengthに強制 - var position = m_transform.position; - nextTail = position + (nextTail - position).normalized * Length; return nextTail; } diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index 805f42fdc..f8a179630 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -108,20 +108,26 @@ namespace VRM.SpringBone var (transform, init, state) = m_joints[i]; // Spring処理 - var nextTail = init.VerletIntegration(deltaTime, scene.Center, transform, settings, state); + var parentRotation = (transform.parent != null ? transform.parent.rotation : Quaternion.identity); + var nextTail = init.VerletIntegration(deltaTime, scene.Center, parentRotation, settings, state); + + // 長さをboneLengthに強制 + nextTail = transform.position + (nextTail - transform.position).normalized * init.Length; // Collision foreach (var collider in m_colliders) { - nextTail = collider.Collide(settings, transform, init, nextTail); + if (collider.TryCollide(settings, transform, nextTail, out var posFromCollider)) + { + // 長さをboneLengthに強制 + nextTail = transform.position + (posFromCollider - transform.position).normalized * init.Length; + } } // 状態更新 m_joints[i] = (transform, init, SpringBoneJointState.Make(scene.Center, currentTail: state.CurrentTail, nextTail: nextTail)); - //回転を適用 - var r = init.WorldRotationFromTailPosition(transform, nextTail); - transform.rotation = r; + transform.rotation = init.WorldRotationFromTailPosition(transform, nextTail); } } From 014530b4000b103b9f78c57c187541b8663b3c6d Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 3 Sep 2024 15:59:16 +0900 Subject: [PATCH 6/6] readonly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SceneInfo に ColliderGroups を投入するの忘れていた --- .../VRM/Runtime/SpringBone/Logic/SceneInfo.cs | 14 +++++--- .../SpringBone/Logic/SphereCollider.cs | 2 +- .../SpringBone/Logic/SpringBoneJointInit.cs | 13 +++++--- .../SpringBone/Logic/SpringBoneJointState.cs | 33 +++++++++---------- .../SpringBone/Logic/SpringBoneSettings.cs | 15 +++++---- .../SpringBone/Logic/SpringBoneSystem.cs | 14 ++++---- .../VRM/Runtime/SpringBone/VRMSpringBone.cs | 20 ++++++----- 7 files changed, 62 insertions(+), 49 deletions(-) diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs index 546673013..15053e9d2 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SceneInfo.cs @@ -3,10 +3,16 @@ using UnityEngine; namespace VRM.SpringBone { - struct SceneInfo + readonly struct SceneInfo { - public IReadOnlyList RootBones; - public Transform Center; - public VRMSpringBoneColliderGroup[] ColliderGroups; + public readonly IReadOnlyList RootBones; + public readonly Transform Center; + public readonly VRMSpringBoneColliderGroup[] ColliderGroups; + + public SceneInfo( + IReadOnlyList rootBones, + Transform center, + VRMSpringBoneColliderGroup[] colliderGroups) => + (RootBones, Center, ColliderGroups) = (rootBones, center, colliderGroups); } } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs index 46185aa8f..ded97a744 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SphereCollider.cs @@ -2,7 +2,7 @@ using UnityEngine; namespace VRM.SpringBone { - struct SphereCollider + readonly struct SphereCollider { public readonly Vector3 Position; public readonly float Radius; diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs index 676224756..6b2b92ce0 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointInit.cs @@ -9,11 +9,16 @@ namespace VRM.SpringBone /// /// この型のフィールドはSpringBoneのライフサイクルを通じて不変。 /// - struct SpringBoneJointInit + readonly struct SpringBoneJointInit { - public Vector3 BoneAxis; - public float Length; - public Quaternion LocalRotation; + public readonly Vector3 BoneAxis; + public readonly float Length; + public readonly Quaternion LocalRotation; + + public SpringBoneJointInit( + Vector3 boneAxis, + float length, + Quaternion localRotation) => (BoneAxis, Length, LocalRotation) = (boneAxis, length, localRotation); /// /// しっぽの位置から回転を計算する diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs index c54b74a5a..31bde5ea7 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneJointState.cs @@ -5,10 +5,13 @@ namespace VRM.SpringBone /// /// 毎フレーム更新される Verlet 積分の位置状態 /// - struct SpringBoneJointState + readonly struct SpringBoneJointState { - public Vector3 CurrentTail; - public Vector3 PrevTail; + public readonly Vector3 CurrentTail; + public readonly Vector3 PrevTail; + + public SpringBoneJointState(Vector3 currentTail, Vector3 prevTail) => + (CurrentTail, PrevTail) = (currentTail, prevTail); public static SpringBoneJointState Init(Transform center, Transform transform, Vector3 localChildPosition) { @@ -16,37 +19,31 @@ namespace VRM.SpringBone var tail = center != null ? center.InverseTransformPoint(worldChildPosition) : worldChildPosition; - return new SpringBoneJointState - { - CurrentTail = tail, - PrevTail = tail, - }; + return new SpringBoneJointState(currentTail: tail, prevTail: tail); } public static SpringBoneJointState Make(Transform center, Vector3 currentTail, Vector3 nextTail) { return new SpringBoneJointState - { - PrevTail = center != null + ( + prevTail: center != null ? center.InverseTransformPoint(currentTail) : currentTail, - CurrentTail = center != null + currentTail: center != null ? center.InverseTransformPoint(nextTail) - : nextTail, - }; + : nextTail); } public SpringBoneJointState ToWorld(Transform center) { return new SpringBoneJointState - { - CurrentTail = center != null + ( + currentTail: center != null ? center.TransformPoint(CurrentTail) : CurrentTail, - PrevTail = center != null + prevTail: center != null ? center.TransformPoint(PrevTail) - : PrevTail, - }; + : PrevTail); } }; } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs index bc6209047..8ddabf49d 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSettings.cs @@ -2,12 +2,15 @@ using UnityEngine; namespace VRM.SpringBone { - struct SpringBoneSettings + readonly struct SpringBoneSettings { - public float StiffnessForce; - public Vector3 GravityDir; - public float GravityPower; - public float HitRadius; - public float DragForce; + public readonly float StiffnessForce; + public readonly float DragForce; + public readonly Vector3 GravityDir; + public readonly float GravityPower; + public readonly float HitRadius; + + public SpringBoneSettings(float stiffnessForce, float dragForce, Vector3 gravityDir, float gravityPower, float hitRadius) => + (StiffnessForce, DragForce, GravityDir, GravityPower, HitRadius) = (stiffnessForce, dragForce, gravityDir, gravityPower, hitRadius); } } \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs index f8a179630..1badea980 100644 --- a/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs +++ b/Assets/VRM/Runtime/SpringBone/Logic/SpringBoneSystem.cs @@ -41,8 +41,8 @@ namespace VRM.SpringBone private void SetupRecursive(Transform center, Transform parent) { - Vector3 localPosition = default; - Vector3 scale = default; + Vector3 localPosition; + Vector3 scale; if (parent.childCount == 0) { // 子ノードが無い。7cm 固定 @@ -66,11 +66,11 @@ namespace VRM.SpringBone m_joints.Add(( parent, new SpringBoneJointInit - { - LocalRotation = parent.localRotation, - BoneAxis = localChildPosition.normalized, - Length = localChildPosition.magnitude, - }, + ( + localRotation: parent.localRotation, + boneAxis: localChildPosition.normalized, + length: localChildPosition.magnitude + ), SpringBoneJointState.Init(center, parent, localChildPosition))); foreach (Transform child in parent) SetupRecursive(center, child); diff --git a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs index a35a47e54..9932e3394 100644 --- a/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs +++ b/Assets/VRM/Runtime/SpringBone/VRMSpringBone.cs @@ -37,15 +37,17 @@ namespace VRM 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, - }; + SpringBone.SceneInfo Scene => new( + rootBones: RootBones, + center: m_center, + colliderGroups: ColliderGroups); + SpringBone.SpringBoneSettings Settings => new + ( + stiffnessForce: m_stiffnessForce, + dragForce: m_dragForce, + gravityDir: m_gravityDir, + gravityPower: m_gravityPower, + hitRadius: m_hitRadius); [ContextMenu("Reset bones")] public void Setup(bool force = false)