SphereCapsuleCollider._vrm

This commit is contained in:
ousttrue 2024-11-16 02:44:56 +09:00
parent f2ad450dd5
commit a249fc7f37
7 changed files with 85 additions and 82 deletions

View File

@ -552,7 +552,7 @@ namespace UniVRM10.Cloth.Viewer
void OnInit(RotateParticle.RotateParticleSystem system, Vrm10Instance vrm)
{
var animator = vrm.GetComponent<Animator>();
HumanoidCollider.AddColliders(system, animator);
HumanoidCollider.AddColliders(system._colliderGroups, animator);
try
{
ClothGuess.Guess(animator);

View File

@ -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<ColliderGroup> _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<ColliderGroup> _colliderGroups, string groupName, Transform head, Transform tail, float radius)
static void AddColliderIfNotExists(List<ColliderGroup> _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<SphereCapsuleCollider>(head.gameObject);
c.Tail = tail;
c.Radius = radius;
var vrmCollider = head.gameObject.AddComponent<VRM10SpringBoneCollider>();
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);
}

View File

@ -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;

View File

@ -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
/// <returns></returns>
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);
}
}
/// <summary>

View File

@ -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
{

View File

@ -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
/// <returns></returns>
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

View File

@ -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);