Cloth x Capsule

This commit is contained in:
ousttrue
2024-11-26 02:09:42 +09:00
parent a8b998eb2b
commit 4f41ed76f4
7 changed files with 160 additions and 170 deletions

View File

@@ -87,7 +87,10 @@ namespace UniVRM10
{
foreach (var collider in Colliders)
{
collider.DrawGizmos();
if (collider != null)
{
collider.DrawGizmos();
}
}
}
}

View File

@@ -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":

View File

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

View File

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

View File

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

View File

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

View File

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