diff --git a/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs b/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs index 63bb170a0..98aee7693 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs @@ -552,7 +552,7 @@ namespace UniVRM10.Cloth.Viewer void OnInit(RotateParticle.RotateParticleSystem system, Vrm10Instance vrm) { var animator = vrm.GetComponent(); - HumanoidCollider.AddColliders(system, animator); + HumanoidCollider.AddColliders(system._colliderGroups, animator); try { ClothGuess.Guess(animator); diff --git a/Assets/VRM10_Samples/ClothSample/ClothViewer/HumanoidCollider.cs b/Assets/VRM10_Samples/ClothSample/ClothViewer/HumanoidCollider.cs index 1994c261a..4cc67093d 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothViewer/HumanoidCollider.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothViewer/HumanoidCollider.cs @@ -23,16 +23,19 @@ namespace UniVRM10.Cloth.Viewer ("Arm", HumanBodyBones.RightHand, HumanBodyBones.RightMiddleProximal, 0.02f), }; - public static void AddColliders(RotateParticleSystem system, Animator animator) + public static void AddColliders(List _colliderGroups, Animator animator) { foreach (var (group, head, tail, radius) in Capsules) { - AddColliderIfNotExists(system._colliderGroups, group, - animator.GetBoneTransform(head), animator.GetBoneTransform(tail), radius); + AddColliderIfNotExists(_colliderGroups, group, + animator.GetBoneTransform(head), + animator.GetBoneTransform(tail), + radius); } } - static void AddColliderIfNotExists(List _colliderGroups, string groupName, Transform head, Transform tail, float radius) + static void AddColliderIfNotExists(List _colliderGroups, string groupName, + Transform head, Transform tail, float radius) { ColliderGroup group = default; foreach (var g in _colliderGroups) @@ -51,15 +54,18 @@ namespace UniVRM10.Cloth.Viewer foreach (var collider in group.Colliders) { - if (collider.transform == head) + if (collider._vrm.transform == head) { return; } } - var c = GetOrAddComponent(head.gameObject); - c.Tail = tail; - c.Radius = radius; + var vrmCollider = head.gameObject.AddComponent(); + vrmCollider.Radius = radius; + vrmCollider.ColliderType = VRM10SpringBoneColliderTypes.Capsule; + vrmCollider.Tail = head.worldToLocalMatrix.MultiplyPoint(tail.position); + + var c = new SphereCapsuleCollider(vrmCollider); // c.GizmoColor = GetGizmoColor(group); group.Colliders.Add(c); } diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/CapsuleInfo.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/CapsuleInfo.cs index 4b151ebf9..cde732b02 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/CapsuleInfo.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/CapsuleInfo.cs @@ -32,31 +32,31 @@ namespace SphereTriangle { Collider = collider; Triangle = t; - var headDistance = t.Plane.GetDistanceToPoint(collider.transform.position); - var tailDistance = t.Plane.GetDistanceToPoint(collider.Tail.position); + var headDistance = t.Plane.GetDistanceToPoint(collider.HeadWorldPosition); + var tailDistance = t.Plane.GetDistanceToPoint(collider.TailWorldPosition); if (headDistance <= tailDistance) { Reverse = false; MinDistance = headDistance; MaxDistance = tailDistance; - MinOnPlane = t.Plane.ClosestPointOnPlane(collider.transform.position); - MaxOnPlane = t.Plane.ClosestPointOnPlane(collider.Tail.position); - MinClamp = collider.transform.position; - MaxClamp = collider.Tail.position; - MinPos = collider.transform.position; - MaxPos = collider.Tail.position; + MinOnPlane = t.Plane.ClosestPointOnPlane(collider.HeadWorldPosition); + MaxOnPlane = t.Plane.ClosestPointOnPlane(collider.TailWorldPosition); + MinClamp = collider.HeadWorldPosition; + MaxClamp = collider.TailWorldPosition; + MinPos = collider.HeadWorldPosition; + MaxPos = collider.TailWorldPosition; } else { Reverse = true; MaxDistance = headDistance; MinDistance = tailDistance; - MaxOnPlane = t.Plane.ClosestPointOnPlane(collider.transform.position); - MinOnPlane = t.Plane.ClosestPointOnPlane(collider.Tail.position); - MaxClamp = collider.transform.position; - MinClamp = collider.Tail.position; - MaxPos = collider.transform.position; - MinPos = collider.Tail.position; + MaxOnPlane = t.Plane.ClosestPointOnPlane(collider.HeadWorldPosition); + MinOnPlane = t.Plane.ClosestPointOnPlane(collider.TailWorldPosition); + MaxClamp = collider.HeadWorldPosition; + MinClamp = collider.TailWorldPosition; + MaxPos = collider.HeadWorldPosition; + MinPos = collider.TailWorldPosition; } // Intersect @@ -100,11 +100,11 @@ namespace SphereTriangle public void DrawGizmo() { Gizmos.color = Color.blue; - Gizmos.DrawLine(Reverse ? Collider.Tail.position : Collider.transform.position, MinOnPlane); + Gizmos.DrawLine(Reverse ? Collider.TailWorldPosition : Collider.HeadWorldPosition, MinOnPlane); Gizmos.DrawWireSphere(MinOnPlane, 0.01f); Gizmos.color = Color.blue; - Gizmos.DrawLine(Reverse ? Collider.transform.position : Collider.Tail.position, MaxOnPlane); + Gizmos.DrawLine(Reverse ? Collider.HeadWorldPosition : Collider.TailWorldPosition, MaxOnPlane); Gizmos.DrawWireSphere(MaxOnPlane, 0.01f); Gizmos.color = Color.magenta; diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/ClothRectCollision.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/ClothRectCollision.cs index b61537bdb..d1a63d4a5 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/ClothRectCollision.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/ClothRectCollision.cs @@ -60,8 +60,8 @@ namespace SphereTriangle { foreach (var collider in g.Colliders) { - var p = t.Plane.ClosestPointOnPlane(collider.transform.position); - var dot = Vector3.Dot(t.Plane.normal, collider.transform.position - p); + var p = t.Plane.ClosestPointOnPlane(collider.HeadWorldPosition); + var dot = Vector3.Dot(t.Plane.normal, collider.HeadWorldPosition - p); _initialColliderNormalSide[collider] = dot; } } @@ -126,8 +126,8 @@ namespace SphereTriangle continue; } - var p = _triangle0.Plane.ClosestPointOnPlane(collider.transform.position); - var dot = Vector3.Dot(_triangle0.Plane.normal, collider.transform.position - p); + var p = _triangle0.Plane.ClosestPointOnPlane(collider.HeadWorldPosition); + var dot = Vector3.Dot(_triangle0.Plane.normal, collider.HeadWorldPosition - p); if (_initialColliderNormalSide[collider] * dot < 0) { // 片側 @@ -162,19 +162,13 @@ namespace SphereTriangle /// static bool TryCollide(TriangleCapsuleCollisionSolver solver, SphereCapsuleCollider collider, in Triangle t, out LineSegment l) { - if (collider.Tail == null) - { - using var profile = new ProfileSample("Sphere"); - // sphere - return TryCollideSphere(t, collider.transform.position, collider.Radius, out l); - } - else + if (collider.IsCapsule) { // capsule TriangleCapsuleCollisionSolver.Result result = default; using (new ProfileSample("Capsule: Collide")) { - result = solver.Collide(t, collider, new(collider.transform.position, collider.Tail.position), collider.Radius); + result = solver.Collide(t, collider, new(collider.HeadWorldPosition, collider.TailWorldPosition), collider.Radius); } using (new ProfileSample("Capsule: TryGetClosest")) { @@ -182,6 +176,12 @@ namespace SphereTriangle return type.HasValue; } } + else + { + // sphere + using var profile = new ProfileSample("Sphere"); + return TryCollideSphere(t, collider.HeadWorldPosition, collider.Radius, out l); + } } /// diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/LineDistanceGizmo.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/LineDistanceGizmo.cs index f555b5bba..6b7bdd469 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/LineDistanceGizmo.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/LineDistanceGizmo.cs @@ -17,10 +17,10 @@ namespace SphereTriangle public void OnDrawGizmos() { - if (LineA?.Tail != null && LineB?.Tail != null) + if (LineA.IsCapsule && LineB.IsCapsule) { - var a = new LineSegment(LineA.transform.position, LineA.Tail.position); - var b = new LineSegment(LineB.transform.position, LineB.Tail.position); + var a = new LineSegment(LineA.HeadWorldPosition, LineA.TailWorldPosition); + var b = new LineSegment(LineB.HeadWorldPosition, LineB.TailWorldPosition); var (s, t) = LineSegment.CalcClosest(a, b); var a_s = a.GetPoint(s); var b_t = b.GetPoint(t); @@ -30,11 +30,11 @@ namespace SphereTriangle Gizmos.color = Color.gray; if (s < 0) { - Gizmos.DrawLine(LineA.transform.position, a_s); + Gizmos.DrawLine(LineA.HeadWorldPosition, a_s); } else if (s > 1) { - Gizmos.DrawLine(LineA.Tail.position, a_s); + Gizmos.DrawLine(LineA.TailWorldPosition, a_s); } else { @@ -42,11 +42,11 @@ namespace SphereTriangle } if (t < 0) { - Gizmos.DrawLine(LineB.transform.position, b_t); + Gizmos.DrawLine(LineB.HeadWorldPosition, b_t); } else if (t > 1) { - Gizmos.DrawLine(LineB.transform.position, b_t); + Gizmos.DrawLine(LineB.HeadWorldPosition, b_t); } else { diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/SphereCapsuleCollider.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/SphereCapsuleCollider.cs index 2908963f8..4eaf61794 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/SphereCapsuleCollider.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/SphereCapsuleCollider.cs @@ -1,44 +1,41 @@ using UnityEngine; +using UniVRM10; namespace SphereTriangle { - [DisallowMultipleComponent] - public class SphereCapsuleCollider : MonoBehaviour + public class SphereCapsuleCollider { - [SerializeField, Range(0.01f, 1f)] - public float Radius = 0.05f; - - public Transform Tail; - - public Ray? HeadTailRay => Tail == null ? null : new Ray { origin = transform.position, direction = (Tail.position - transform.position) }; - - public float CapsuleLength => Tail == null ? 0 : Vector3.Distance(Tail.position, transform.position); - - + public readonly VRM10SpringBoneCollider _vrm; public Color GizmoColor = Color.yellow; public bool SolidGizmo = false; - public Bounds GetBounds() - { - if (Tail == null) - { - return new Bounds(transform.position, new Vector3(Radius, Radius, Radius)); - } + public float Radius => _vrm.Radius; + public bool IsCapsule => _vrm.ColliderType == VRM10SpringBoneColliderTypes.Capsule; + public Vector3 HeadWorldPosition => _vrm.transform.TransformPoint(_vrm.Offset); + public Vector3 TailWorldPosition => _vrm.transform.TransformPoint(_vrm.TailOrNormal); + public Ray? HeadTailRay => IsCapsule ? new Ray { origin = HeadWorldPosition, direction = TailWorldPosition - HeadWorldPosition } : null; + public float CapsuleLength => !IsCapsule ? 0 : Vector3.Distance(TailWorldPosition, HeadWorldPosition); - var h = transform.position; - var t = Tail.position; - var d = h - t; - var aabb = new Bounds((h + t) * 0.5f, new Vector3(Mathf.Abs(d.x), Mathf.Abs(d.y), Mathf.Abs(d.z))); - aabb.Expand(Radius * 2); - return aabb; + public SphereCapsuleCollider(VRM10SpringBoneCollider vrmCollider) + { + _vrm = vrmCollider; } - public void Reset() + public Bounds GetBounds() { - if (transform.childCount > 0) + if (IsCapsule) { - Tail = transform.GetChild(0); + var h = HeadWorldPosition; + var t = TailWorldPosition; + var d = h - t; + var aabb = new Bounds((h + t) * 0.5f, new Vector3(Mathf.Abs(d.x), Mathf.Abs(d.y), Mathf.Abs(d.z))); + aabb.Expand(_vrm.Radius * 2); + return aabb; + } + else + { + return new Bounds(HeadWorldPosition, new Vector3(_vrm.Radius, _vrm.Radius, _vrm.Radius)); } } @@ -117,13 +114,13 @@ namespace SphereTriangle /// public bool TryCollide(in Vector3 p, float radius, out LineSegment resolved) { - if (Tail != null) + if (IsCapsule) { - return TryCollideCapsuleAndSphere(transform.position, Tail.position, this.Radius, p, radius, out resolved); + return TryCollideCapsuleAndSphere(HeadWorldPosition, TailWorldPosition, this.Radius, p, radius, out resolved); } else { - return TryCollideSphereAndSphere(transform.position, this.Radius, p, radius, out resolved); + return TryCollideSphereAndSphere(HeadWorldPosition, this.Radius, p, radius, out resolved); } } @@ -148,21 +145,21 @@ namespace SphereTriangle if (SolidGizmo) { Gizmos.color = Color.white; - Gizmos.DrawSphere(transform.position, Radius); + Gizmos.DrawSphere(HeadWorldPosition, Radius); } Gizmos.color = GizmoColor; - if (transform.parent) + if (_vrm.transform.parent != null) { - Gizmos.DrawLine(transform.parent.position, transform.position); + Gizmos.DrawLine(HeadWorldPosition, HeadWorldPosition); } - if (Tail != null) + if (IsCapsule) { - DrawCapsuleGizmo(transform.position, Tail.position, Radius); + DrawCapsuleGizmo(HeadWorldPosition, TailWorldPosition, Radius); } else { - Gizmos.DrawWireSphere(transform.position, Radius); + Gizmos.DrawWireSphere(HeadWorldPosition, Radius); } #if AABB_DEBUG diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/TriangleCapsuleGizmo.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/TriangleCapsuleGizmo.cs index f73cd67d4..40f20711c 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/TriangleCapsuleGizmo.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/SphereTriangle/TriangleCapsuleGizmo.cs @@ -35,8 +35,8 @@ namespace SphereTriangle if (C == null) return; var t = new Triangle(transform.position, B.position, C.position); - if (Capsule?.Tail == null) return; - var capsule = new LineSegment(Capsule.transform.position, Capsule.Tail.position); + if (!Capsule.IsCapsule) return; + var capsule = new LineSegment(Capsule.HeadWorldPosition, Capsule.TailWorldPosition); _solver.BeginFrame(); var result = _solver.Collide(t, Capsule, capsule, Capsule.Radius);