mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-07-22 02:00:59 -05:00
SphereCapsuleCollider._vrm
This commit is contained in:
parent
f2ad450dd5
commit
a249fc7f37
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user