mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-10 04:49:28 -05:00
Cloth x Capsule
This commit is contained in:
@@ -87,7 +87,10 @@ namespace UniVRM10
|
||||
{
|
||||
foreach (var collider in Colliders)
|
||||
{
|
||||
collider.DrawGizmos();
|
||||
if (collider != null)
|
||||
{
|
||||
collider.DrawGizmos();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,9 +242,15 @@ namespace UniVRM10
|
||||
|
||||
private static MToon10AlphaMode GetMToon10AlphaMode(glTFMaterial material)
|
||||
{
|
||||
if (material == null)
|
||||
{
|
||||
return MToon10AlphaMode.Opaque;
|
||||
}
|
||||
|
||||
switch (material?.alphaMode)
|
||||
{
|
||||
case null:
|
||||
return MToon10AlphaMode.Opaque;
|
||||
case "OPAQUE":
|
||||
return MToon10AlphaMode.Opaque;
|
||||
case "MASK":
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SphereTriangle;
|
||||
using UniGLTF.SpringBoneJobs.Blittables;
|
||||
using Unity.Collections;
|
||||
@@ -111,71 +112,51 @@ namespace RotateParticle.Jobs
|
||||
for (int colliderIndex = 0; colliderIndex < Colliders.Length; ++colliderIndex)
|
||||
{
|
||||
var collider = Colliders[colliderIndex];
|
||||
var col_pos = CurrentColliders[colliderIndex].MultiplyPoint(collider.offset);
|
||||
switch (collider.colliderType)
|
||||
var collider_matrix = CurrentColliders[colliderIndex];
|
||||
if (!aabb.Intersects(GetBounds(collider, collider_matrix)))
|
||||
{
|
||||
case BlittableColliderType.Sphere:
|
||||
{
|
||||
// using (new ProfileSample("Rect: Collide"))
|
||||
{
|
||||
if (!aabb.Intersects(GetBounds(collider, col_pos)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 面の片側だけにヒットさせる
|
||||
// 行き過ぎて戻るときに素通りする
|
||||
// var p = _triangle0.Plane.ClosestPointOnPlane(col_pos);
|
||||
// var dot = Vector3.Dot(_triangle0.Plane.normal, col_pos - p);
|
||||
// if (_initialColliderNormalSide[collider] * dot < 0)
|
||||
// {
|
||||
// // 片側
|
||||
// continue;
|
||||
// }
|
||||
}
|
||||
// 面の片側だけにヒットさせる
|
||||
// 行き過ぎて戻るときに素通りする
|
||||
// var p = _triangle0.Plane.ClosestPointOnPlane(col_pos);
|
||||
// var dot = Vector3.Dot(_triangle0.Plane.normal, col_pos - p);
|
||||
// if (_initialColliderNormalSide[collider] * dot < 0)
|
||||
// {
|
||||
// // 片側
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (TryCollide(collider, col_pos, _triangle0, out var l0))
|
||||
{
|
||||
CollisionMove(rect._a, l0.GetDelta(collider.radius));
|
||||
CollisionMove(rect._b, l0.GetDelta(collider.radius));
|
||||
CollisionMove(rect._c, l0.GetDelta(collider.radius));
|
||||
}
|
||||
if (TryCollide(collider, col_pos, _triangle1, out var l1))
|
||||
{
|
||||
CollisionMove(rect._c, l1.GetDelta(collider.radius));
|
||||
CollisionMove(rect._d, l1.GetDelta(collider.radius));
|
||||
CollisionMove(rect._a, l1.GetDelta(collider.radius));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (TryCollide(collider, collider_matrix, _triangle0, out var l0))
|
||||
{
|
||||
CollisionMove(rect._a, l0.GetDelta(collider.radius));
|
||||
CollisionMove(rect._b, l0.GetDelta(collider.radius));
|
||||
CollisionMove(rect._c, l0.GetDelta(collider.radius));
|
||||
}
|
||||
if (TryCollide(collider, collider_matrix, _triangle1, out var l1))
|
||||
{
|
||||
CollisionMove(rect._c, l1.GetDelta(collider.radius));
|
||||
CollisionMove(rect._d, l1.GetDelta(collider.radius));
|
||||
CollisionMove(rect._a, l1.GetDelta(collider.radius));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryCollide(BlittableCollider collider, Vector3 col_pos, in Triangle t, out LineSegment l)
|
||||
static bool TryCollide(BlittableCollider collider, in Matrix4x4 colliderMatrix, in Triangle t, out LineSegment l)
|
||||
{
|
||||
var col_pos = colliderMatrix.MultiplyPoint(collider.offset);
|
||||
if (collider.colliderType == BlittableColliderType.Capsule)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// // capsule
|
||||
// TriangleCapsuleCollisionSolver.Result result = default;
|
||||
// // using (new ProfileSample("Capsule: Collide"))
|
||||
// {
|
||||
// result = solver.Collide(t, collider, new(collider.HeadWorldPosition, collider.TailWorldPosition), collider.Radius);
|
||||
// }
|
||||
// // using (new ProfileSample("Capsule: TryGetClosest"))
|
||||
// {
|
||||
// var type = result.TryGetClosest(out l);
|
||||
// return type.HasValue;
|
||||
// }
|
||||
// capsule
|
||||
var tail_pos = colliderMatrix.MultiplyPoint(collider.tailOrNormal);
|
||||
var result = TriangleCapsuleCollisionSolver.Collide(t, new LineSegment(col_pos, tail_pos), collider.radius);
|
||||
var type = result.TryGetClosest(out l);
|
||||
return type.HasValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sphere
|
||||
// using var profile = new ProfileSample("Sphere");
|
||||
return TryCollideSphere(t, col_pos, collider.radius, out l);
|
||||
}
|
||||
}
|
||||
@@ -222,23 +203,22 @@ namespace RotateParticle.Jobs
|
||||
return aabb;
|
||||
}
|
||||
|
||||
public static Bounds GetBounds(BlittableCollider collider, Vector3 col_pos)
|
||||
public static Bounds GetBounds(BlittableCollider collider, Matrix4x4 m)
|
||||
{
|
||||
switch (collider.colliderType)
|
||||
{
|
||||
case BlittableColliderType.Capsule:
|
||||
{
|
||||
// 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(Radius * 2);
|
||||
// return aabb;
|
||||
throw new NotImplementedException();
|
||||
var h = m.MultiplyPoint(collider.offset);
|
||||
var t = m.MultiplyPoint(collider.tailOrNormal);
|
||||
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(collider.radius * 2);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
case BlittableColliderType.Sphere:
|
||||
return new Bounds(col_pos, new Vector3(collider.radius, collider.radius, collider.radius));
|
||||
return new Bounds(m.MultiplyPoint(collider.offset), new Vector3(collider.radius, collider.radius, collider.radius));
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace RotateParticle
|
||||
public ParticleList _list = new();
|
||||
|
||||
ClothRectList _clothRects;
|
||||
public List<ClothRectCollision> _clothRectCollisions;
|
||||
public List<ClothRectCollision> _clothRectCollisions = new();
|
||||
|
||||
public PositionList _newPos;
|
||||
Vector3[] _restPositions;
|
||||
@@ -85,7 +85,10 @@ namespace RotateParticle
|
||||
{
|
||||
foreach (var c in g.Colliders)
|
||||
{
|
||||
AddColliderIfNotExists(g.name, c);
|
||||
if (c != null)
|
||||
{
|
||||
AddColliderIfNotExists(g.name, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +109,7 @@ namespace RotateParticle
|
||||
c.InitializeColliderSide(_newPos, _colliderGroups, r);
|
||||
}
|
||||
|
||||
await awaitCaller.NextFrame();
|
||||
// await awaitCaller.NextFrame();
|
||||
|
||||
_initialized = true;
|
||||
_building = false;
|
||||
@@ -276,6 +279,10 @@ namespace RotateParticle
|
||||
|
||||
foreach (var collider in group.Colliders)
|
||||
{
|
||||
if (collider == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (collider == c)
|
||||
{
|
||||
return;
|
||||
@@ -379,7 +386,7 @@ namespace RotateParticle
|
||||
{
|
||||
// var (spring, rect) = _clothRects[i];
|
||||
var collision = _clothRectCollisions[i];
|
||||
collision.DrawGizmos();
|
||||
// collision.DrawGizmos();
|
||||
}
|
||||
|
||||
if (_newPos != null)
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace SphereTriangle
|
||||
Triangle _triangle1;
|
||||
float _triangle1Collision;
|
||||
|
||||
TriangleCapsuleCollisionSolver _s0 = new();
|
||||
TriangleCapsuleCollisionSolver _s1 = new();
|
||||
// TriangleCapsuleCollisionSolver _s0 = new();
|
||||
// TriangleCapsuleCollisionSolver _s1 = new();
|
||||
|
||||
// 各コライダーが初期姿勢で三角形ABCの法線の正か負のどちらにあるのかを記録する
|
||||
Dictionary<VRM10SpringBoneCollider, float> _initialColliderNormalSide = new();
|
||||
@@ -75,8 +75,8 @@ namespace SphereTriangle
|
||||
{
|
||||
// using (new ProfileSample("Rect: Prepare"))
|
||||
{
|
||||
_s0.BeginFrame();
|
||||
_s1.BeginFrame();
|
||||
// _s0.BeginFrame();
|
||||
// _s1.BeginFrame();
|
||||
|
||||
var a = list.Get(_rect._a);
|
||||
var b = list.Get(_rect._b);
|
||||
@@ -126,14 +126,14 @@ namespace SphereTriangle
|
||||
}
|
||||
}
|
||||
|
||||
if (TryCollide(_s0, collider, _triangle0, out var l0))
|
||||
if (TryCollide(collider, _triangle0, out var l0))
|
||||
{
|
||||
_trinagle0Collision = 1.0f;
|
||||
list.CollisionMove(_rect._a, l0, collider.Radius);
|
||||
list.CollisionMove(_rect._b, l0, collider.Radius);
|
||||
list.CollisionMove(_rect._c, l0, collider.Radius);
|
||||
}
|
||||
if (TryCollide(_s1, collider, _triangle1, out var l1))
|
||||
if (TryCollide(collider, _triangle1, out var l1))
|
||||
{
|
||||
_triangle1Collision = 1.0f;
|
||||
list.CollisionMove(_rect._c, l1, collider.Radius);
|
||||
@@ -151,21 +151,14 @@ namespace SphereTriangle
|
||||
/// <param name="t"></param>
|
||||
/// <param name="l"></param>
|
||||
/// <returns></returns>
|
||||
static bool TryCollide(TriangleCapsuleCollisionSolver solver, VRM10SpringBoneCollider collider, in Triangle t, out LineSegment l)
|
||||
static bool TryCollide(VRM10SpringBoneCollider collider, in Triangle t, out LineSegment l)
|
||||
{
|
||||
if (collider.ColliderType == VRM10SpringBoneColliderTypes.Capsule)
|
||||
{
|
||||
// capsule
|
||||
TriangleCapsuleCollisionSolver.Result result = default;
|
||||
// using (new ProfileSample("Capsule: Collide"))
|
||||
{
|
||||
result = solver.Collide(t, collider, new(collider.HeadWorldPosition, collider.TailWorldPosition), collider.Radius);
|
||||
}
|
||||
// using (new ProfileSample("Capsule: TryGetClosest"))
|
||||
{
|
||||
var type = result.TryGetClosest(out l);
|
||||
return type.HasValue;
|
||||
}
|
||||
var result = TriangleCapsuleCollisionSolver.Collide(t, new(collider.HeadWorldPosition, collider.TailWorldPosition), collider.Radius);
|
||||
var type = result.TryGetClosest(out l);
|
||||
return type.HasValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -208,23 +201,23 @@ namespace SphereTriangle
|
||||
return true;
|
||||
}
|
||||
|
||||
public void DrawGizmos()
|
||||
{
|
||||
var r = Vector3.Distance(_triangle0.b, _triangle0.c) * 0.1f;
|
||||
_DrawGizmos(_triangle0, _s0, _trinagle0Collision, r);
|
||||
_DrawGizmos(_triangle1, _s1, _triangle1Collision, r);
|
||||
// public void DrawGizmos()
|
||||
// {
|
||||
// var r = Vector3.Distance(_triangle0.b, _triangle0.c) * 0.1f;
|
||||
// _DrawGizmos(_triangle0, _s0, _trinagle0Collision, r);
|
||||
// _DrawGizmos(_triangle1, _s1, _triangle1Collision, r);
|
||||
|
||||
#if AABB_DEBUG
|
||||
Gizmos.matrix = Matrix4x4.identity;
|
||||
Gizmos.color = Color.cyan;
|
||||
var aabb = GetBoundsFrom4(_triangle0.a, _triangle0.b, _triangle1.a, _triangle1.b);
|
||||
Gizmos.DrawWireCube(aabb.center, aabb.size);
|
||||
#endif
|
||||
}
|
||||
// #if AABB_DEBUG
|
||||
// Gizmos.matrix = Matrix4x4.identity;
|
||||
// Gizmos.color = Color.cyan;
|
||||
// var aabb = GetBoundsFrom4(_triangle0.a, _triangle0.b, _triangle1.a, _triangle1.b);
|
||||
// Gizmos.DrawWireCube(aabb.center, aabb.size);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
void _DrawGizmos(in Triangle t, TriangleCapsuleCollisionSolver solver, float collision, float radius)
|
||||
{
|
||||
solver.DrawGizmos(t, collision, radius);
|
||||
}
|
||||
// void _DrawGizmos(in Triangle t, TriangleCapsuleCollisionSolver solver, float collision, float radius)
|
||||
// {
|
||||
// solver.DrawGizmos(t, collision, radius);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace SphereTriangle
|
||||
}
|
||||
};
|
||||
|
||||
public class Status
|
||||
public struct Status
|
||||
{
|
||||
/// <summary>
|
||||
/// Capsule clamped by radius distance from plane
|
||||
@@ -125,36 +125,37 @@ namespace SphereTriangle
|
||||
/// </summary>
|
||||
public Vector3 PE;
|
||||
|
||||
public int CollisionCount = 0;
|
||||
public int CollisionCount;
|
||||
|
||||
public Result Result;
|
||||
}
|
||||
|
||||
// 複数コライダーのデバッグ表示のため
|
||||
public Dictionary<VRM10SpringBoneCollider, Status> collider_status_map = new();
|
||||
// public Dictionary<VRM10SpringBoneCollider, Status> collider_status_map = new();
|
||||
|
||||
public void BeginFrame()
|
||||
{
|
||||
collider_status_map.Clear();
|
||||
}
|
||||
// public void BeginFrame()
|
||||
// {
|
||||
// collider_status_map.Clear();
|
||||
// }
|
||||
|
||||
public Result Collide(in Triangle t, VRM10SpringBoneCollider collider, in LineSegment capsule, float radius)
|
||||
public static Result Collide(in Triangle t, in LineSegment capsule, float radius)
|
||||
{
|
||||
if (collider == null)
|
||||
{
|
||||
throw new ArgumentNullException("collider");
|
||||
}
|
||||
// if (collider == null)
|
||||
// {
|
||||
// throw new ArgumentNullException("collider");
|
||||
// }
|
||||
Status status = default;
|
||||
|
||||
// using (new ProfileSample("Parallel Prepare"))
|
||||
{
|
||||
if (collider_status_map.TryGetValue(collider, out status))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
status = new Status();
|
||||
collider_status_map[collider] = status;
|
||||
}
|
||||
// if (collider_status_map.TryGetValue(collider, out status))
|
||||
// {
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// status = new Status();
|
||||
// collider_status_map[collider] = status;
|
||||
// }
|
||||
|
||||
float dot = default;
|
||||
// using (new ProfileSample("Dot"))
|
||||
@@ -289,7 +290,7 @@ namespace SphereTriangle
|
||||
return new LineSegment(p, a);
|
||||
}
|
||||
|
||||
LineSegment? calcEdgeDistance(in LineSegment ab, in LineSegment clamped, float radius)
|
||||
static LineSegment? calcEdgeDistance(in LineSegment ab, in LineSegment clamped, float radius)
|
||||
{
|
||||
var (a_s, a_t) = LineSegment.CalcClosest(ab, clamped);
|
||||
|
||||
@@ -314,34 +315,34 @@ namespace SphereTriangle
|
||||
return Color.Lerp(g, type.ToColor(), color);
|
||||
}
|
||||
|
||||
public void DrawGizmos(in Triangle t, float collision, float radius)
|
||||
{
|
||||
Gizmos.matrix = Matrix4x4.identity;
|
||||
// public void DrawGizmos(in Triangle t, float collision, float radius)
|
||||
// {
|
||||
// Gizmos.matrix = Matrix4x4.identity;
|
||||
|
||||
var hit = false;
|
||||
foreach (var (_, status) in collider_status_map)
|
||||
{
|
||||
var type = status.Result.TryGetClosest(out var l);
|
||||
if (!type.HasValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// var hit = false;
|
||||
// foreach (var (_, status) in collider_status_map)
|
||||
// {
|
||||
// var type = status.Result.TryGetClosest(out var l);
|
||||
// if (!type.HasValue)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// capsule
|
||||
hit = true;
|
||||
Gizmos.color = GetGizmoColor(type.Value, collision);
|
||||
t.DrawGizmos();
|
||||
l.DrawGizmos();
|
||||
Gizmos.DrawSphere(l.End, radius);
|
||||
Gizmos.DrawWireSphere(l.Start, radius);
|
||||
}
|
||||
// // capsule
|
||||
// hit = true;
|
||||
// Gizmos.color = GetGizmoColor(type.Value, collision);
|
||||
// t.DrawGizmos();
|
||||
// l.DrawGizmos();
|
||||
// Gizmos.DrawSphere(l.End, radius);
|
||||
// Gizmos.DrawWireSphere(l.Start, radius);
|
||||
// }
|
||||
|
||||
if (!hit)
|
||||
{
|
||||
Gizmos.color = Color.gray;
|
||||
t.DrawGizmos();
|
||||
}
|
||||
}
|
||||
// if (!hit)
|
||||
// {
|
||||
// Gizmos.color = Color.gray;
|
||||
// t.DrawGizmos();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public static class IntersectionTypeExtensions
|
||||
|
||||
@@ -30,36 +30,36 @@ namespace SphereTriangle
|
||||
[SerializeField]
|
||||
TriangleCapsuleCollisionSolver _solver = new();
|
||||
|
||||
public void OnDrawGizmos()
|
||||
{
|
||||
if (B == null) return;
|
||||
if (C == null) return;
|
||||
var t = new Triangle(transform.position, B.position, C.position);
|
||||
// public void OnDrawGizmos()
|
||||
// {
|
||||
// if (B == null) return;
|
||||
// if (C == null) return;
|
||||
// var t = new Triangle(transform.position, B.position, C.position);
|
||||
|
||||
if (Capsule.ColliderType != VRM10SpringBoneColliderTypes.Capsule) return;
|
||||
var capsule = new LineSegment(Capsule.HeadWorldPosition, Capsule.TailWorldPosition);
|
||||
// if (Capsule.ColliderType != VRM10SpringBoneColliderTypes.Capsule) return;
|
||||
// var capsule = new LineSegment(Capsule.HeadWorldPosition, Capsule.TailWorldPosition);
|
||||
|
||||
_solver.BeginFrame();
|
||||
var result = _solver.Collide(t, Capsule, capsule, Capsule.Radius);
|
||||
var type = result.TryGetClosest(out var l);
|
||||
if (!type.HasValue)
|
||||
{
|
||||
Gizmos.color = Color.gray;
|
||||
t.DrawGizmos();
|
||||
return;
|
||||
}
|
||||
// _solver.BeginFrame();
|
||||
// var result = _solver.Collide(t, Capsule, capsule, Capsule.Radius);
|
||||
// var type = result.TryGetClosest(out var l);
|
||||
// if (!type.HasValue)
|
||||
// {
|
||||
// Gizmos.color = Color.gray;
|
||||
// t.DrawGizmos();
|
||||
// return;
|
||||
// }
|
||||
|
||||
_solver.DrawGizmos(t, 1.0f, Capsule.Radius);
|
||||
// _solver.DrawGizmos(t, 1.0f, Capsule.Radius);
|
||||
|
||||
Gizmos.color = Color.magenta;
|
||||
Gizmos.DrawLine(l.Start, l.End);
|
||||
Gizmos.DrawSphere(l.End, 0.01f);
|
||||
Gizmos.DrawWireSphere(l.Start, 0.02f);
|
||||
// Gizmos.color = Color.magenta;
|
||||
// Gizmos.DrawLine(l.Start, l.End);
|
||||
// Gizmos.DrawSphere(l.End, 0.01f);
|
||||
// Gizmos.DrawWireSphere(l.Start, 0.02f);
|
||||
|
||||
var delta = l.Vector.normalized * (Capsule.Radius - l.Length);
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawLine(l.End, l.End + delta);
|
||||
Gizmos.DrawSphere(l.End + delta, 0.01f);
|
||||
}
|
||||
// var delta = l.Vector.normalized * (Capsule.Radius - l.Length);
|
||||
// Gizmos.color = Color.green;
|
||||
// Gizmos.DrawLine(l.End, l.End + delta);
|
||||
// Gizmos.DrawSphere(l.End + delta, 0.01f);
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user