diff --git a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs index 5f3da4974..6c29a1270 100644 --- a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs +++ b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs @@ -9,6 +9,7 @@ namespace UniVRM10 Capsule, Plane, SphereInside, + CapsuleInside, } [Serializable] @@ -44,28 +45,46 @@ namespace UniVRM10 break; case VRM10SpringBoneColliderTypes.Capsule: - Gizmos.color = new Color(1.0f, 0.1f, 0.1f); - Gizmos.DrawWireSphere(Offset, Radius); - Gizmos.DrawWireSphere(Tail, Radius); - Gizmos.DrawLine(Offset, Tail); + Gizmos.color = Color.magenta; + DrawCapsuleGizmo(transform.localToWorldMatrix.MultiplyPoint(Offset), transform.localToWorldMatrix.MultiplyPoint(Tail), Radius); break; case VRM10SpringBoneColliderTypes.Plane: Gizmos.color = new Color(1.0f, 0.5f, 0.0f); - // normal offset DrawPlane(transform.localToWorldMatrix, Offset, Normal, Radius); break; case VRM10SpringBoneColliderTypes.SphereInside: - Gizmos.color = Color.cyan; + Gizmos.color = new Color(0.5f, 0, 1.0f); Gizmos.DrawWireSphere(Offset, Radius); break; + case VRM10SpringBoneColliderTypes.CapsuleInside: + Gizmos.color = new Color(0.5f, 0, 1.0f); + DrawCapsuleGizmo(transform.localToWorldMatrix.MultiplyPoint(Offset), transform.localToWorldMatrix.MultiplyPoint(Tail), Radius); + break; + default: throw new NotImplementedException(); } } + public static void DrawCapsuleGizmo(Vector3 start, Vector3 end, float radius) + { + var tail = end - start; + var distance = (end - start).magnitude; + Gizmos.matrix = Matrix4x4.TRS(start, Quaternion.FromToRotation(Vector3.forward, tail), Vector3.one); + Gizmos.DrawWireSphere(Vector3.zero, radius); + Gizmos.DrawWireSphere(Vector3.forward * distance, radius); + var capsuleEnd = Vector3.forward * distance; + var offsets = new Vector3[] { new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, -1.0f, 0.0f) }; + for (int i = 0; i < offsets.Length; i++) + { + Gizmos.DrawLine(offsets[i] * radius, capsuleEnd + offsets[i] * radius); + } + Gizmos.matrix = Matrix4x4.identity; + } + public static void DrawPlane(in Matrix4x4 m, in Vector3 offset, in Vector3 _n, float radius) { var n = _n.normalized; diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs index 93ddef69a..69ea0f91d 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderType.cs @@ -6,5 +6,6 @@ namespace UniVRM10.FastSpringBones.Blittables Capsule, Plane, SphereInside, + CapsuleInside, } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs index 5a442e35e..0dcd85281 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/System/UpdateFastSpringBoneJob.cs @@ -92,11 +92,15 @@ namespace UniVRM10.FastSpringBones.System break; case BlittableColliderType.Plane: - ResolvePlaneCollision(joint, collider, colliderTransform, logic, ref nextTail); + ResolvePlaneCollision(joint, collider, colliderTransform, ref nextTail); break; case BlittableColliderType.SphereInside: - ResolveSphereCollisionInside(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); + // ResolveSphereCollisionInside(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); + break; + + case BlittableColliderType.CapsuleInside: + // ResolveCapsuleCollisionInside(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); break; default: @@ -219,65 +223,27 @@ namespace UniVRM10.FastSpringBones.System private static void ResolveSphereCollisionInside( BlittableJoint joint, BlittableCollider collider, + BlittableTransform colliderTransform, Vector3 worldPosition, BlittableTransform headTransform, float maxColliderScale, BlittableLogic logic, ref Vector3 nextTail) { - var r = joint.radius + collider.radius * maxColliderScale; - if (Vector3.SqrMagnitude(nextTail - worldPosition) <= (r * r)) - { - // ヒット。Colliderの半径方向に押し出す - var normal = (nextTail - worldPosition).normalized; - var posFromCollider = worldPosition + normal * r; - // 長さをboneLengthに強制 - nextTail = headTransform.position + (posFromCollider - headTransform.position).normalized * logic.length; - } - - // let transformedOffset = colliderOffset * colliderTransform; - // let transformedTail = colliderTail * colliderTransform; - // let offsetToTail = transformedTail - transformedOffset; - // let lengthSqCapsule = lengthSq(offsetToTail); - - // let dot = dot(offsetToTail, delta); - - // var delta = jointPosition - transformedOffset; - - // if (dot < 0.0) { - // // ジョイントがカプセルの始点側にある場合 - // // なにもしない - // } else if (dot > lengthSqCapsule) { - // // ジョイントがカプセルの終点側にある場合 - // delta -= offsetToTail; - // } else { - // // ジョイントがカプセルの始点と終点の間にある場合 - // delta -= offsetToTail * (dot / lengthSqCapsule); - // } - - // // ジョイントとコライダーの距離。負の値は衝突していることを示す - // let distance = colliderRadius - jointRadius - length(delta); - - // // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す - // let direction = -normalize(delta); } /// - /// SpringのJoint(head-tail)のとColliderの衝突処理。 - /// nextTail が変化しうる。 + /// Collision with SpringJoint and PlaneCollider. + /// If collide update nextTail. /// /// joint /// collier - /// colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset); - /// jointのhead - /// Mathf.Max(Mathf.Max(Mathf.Abs(colliderScale.x), Mathf.Abs(colliderScale.y)), Mathf.Abs(colliderScale.z)); - /// joint - /// verlet 積分による tail の移動予定 + /// colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset); + /// result of verlet integration private static void ResolvePlaneCollision( BlittableJoint joint, BlittableCollider collider, BlittableTransform colliderTransform, - BlittableLogic logic, ref Vector3 nextTail) { var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset); diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 86b753389..7a26cd8d5 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -361,6 +361,17 @@ namespace UniVRM10 break; } + case VRM10SpringBoneColliderTypes.CapsuleInside: + { + shape.Capsule = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeCapsule + { + Radius = z.Radius, + Offset = ReverseX(z.Offset), + Tail = ReverseX(z.Tail), + }; + break; + } + case VRM10SpringBoneColliderTypes.Plane: { shape.Plane = new UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapePlane @@ -425,7 +436,10 @@ namespace UniVRM10 Node = getNodeIndexFromTransform(c.transform), Shape = ExportShape(c), }; - if (c.ColliderType == VRM10SpringBoneColliderTypes.SphereInside || c.ColliderType == VRM10SpringBoneColliderTypes.Plane) + if (c.ColliderType == VRM10SpringBoneColliderTypes.SphereInside + || c.ColliderType == VRM10SpringBoneColliderTypes.CapsuleInside + || c.ColliderType == VRM10SpringBoneColliderTypes.Plane + ) { exportCollider.Extensions = new UniGLTF.Extensions.VRMC_springBone_extended_collider.VRMC_springBone_extended_collider { diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index f200a7dd0..98d7ac94b 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -546,7 +546,7 @@ namespace UniVRM10 { if (exCollider.Shape.Sphere is UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeSphere exSphere) { - collider.ColliderType = VRM10SpringBoneColliderTypes.Sphere; + collider.ColliderType = exSphere.Inside.GetValueOrDefault() ? VRM10SpringBoneColliderTypes.SphereInside : VRM10SpringBoneColliderTypes.Sphere; collider.Offset = Vector3InvertX(exSphere.Offset); collider.Radius = exSphere.Radius.Value; if (exSphere.Inside.HasValue && exSphere.Inside.Value) @@ -556,7 +556,7 @@ namespace UniVRM10 } else if (exCollider.Shape.Capsule is UniGLTF.Extensions.VRMC_springBone_extended_collider.ExtendedColliderShapeCapsule exCapsule) { - collider.ColliderType = VRM10SpringBoneColliderTypes.Capsule; + collider.ColliderType = exCapsule.Inside.GetValueOrDefault() ? VRM10SpringBoneColliderTypes.CapsuleInside : VRM10SpringBoneColliderTypes.Capsule; collider.Offset = Vector3InvertX(exCapsule.Offset); collider.Tail = Vector3InvertX(exCapsule.Tail); collider.Radius = exCapsule.Radius.Value;