CollisionMove

This commit is contained in:
ousttrue
2024-11-30 23:28:31 +09:00
parent 6ebf6a779b
commit 4f40c44fea
5 changed files with 123 additions and 121 deletions

View File

@@ -54,7 +54,7 @@ namespace UniVRM10.ClothWarp.Jobs
NativeArray<Quaternion> _nextRotations;
NativeArray<Vector3> _strandCollision;
NativeArray<int> _clothCollisionCount;
// NativeArray<int> _clothCollisionCount;
NativeArray<Vector3> _clothCollision;
NativeArray<Vector3> _forces;
@@ -92,7 +92,7 @@ namespace UniVRM10.ClothWarp.Jobs
if (_nextPositions.IsCreated) _nextPositions.Dispose();
if (_nextRotations.IsCreated) _nextRotations.Dispose();
if (_strandCollision.IsCreated) _strandCollision.Dispose();
if (_clothCollisionCount.IsCreated) _clothCollisionCount.Dispose();
// if (_clothCollisionCount.IsCreated) _clothCollisionCount.Dispose();
if (_clothCollision.IsCreated) _clothCollision.Dispose();
if (_forces.IsCreated) _forces.Dispose();
@@ -303,7 +303,7 @@ namespace UniVRM10.ClothWarp.Jobs
_nextRotations = new(pos.Length, Allocator.Persistent);
_info = new(info.ToArray(), Allocator.Persistent);
_strandCollision = new(pos.Length, Allocator.Persistent);
_clothCollisionCount = new(pos.Length, Allocator.Persistent);
// _clothCollisionCount = new(pos.Length, Allocator.Persistent);
_clothCollision = new(pos.Length, Allocator.Persistent);
_forces = new(pos.Length, Allocator.Persistent);
@@ -388,7 +388,7 @@ namespace UniVRM10.ClothWarp.Jobs
CurrentPositions = _currentPositions,
Forces = _forces,
CollisionCount = _clothCollisionCount,
// CollisionCount = _clothCollisionCount,
CollisionDelta = _clothCollision,
}.Schedule(_transformAccessArray, handle);
@@ -448,7 +448,7 @@ namespace UniVRM10.ClothWarp.Jobs
Info = _info,
NextPositions = _nextPositions,
CollisionCount = _clothCollisionCount,
// CollisionCount = _clothCollisionCount,
ClothCollision = _clothCollision,
ClothRects = _clothRects,
@@ -465,7 +465,7 @@ namespace UniVRM10.ClothWarp.Jobs
{
ClothUsedParticles = _clothUsedParticles,
StrandCollision = _strandCollision,
ClothCollisionCount = _clothCollisionCount,
// ClothCollisionCount = _clothCollisionCount,
ClothCollision = _clothCollision,
NextPosition = _nextPositions,
}.Schedule(_info.Length, 1, handle);

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using SphereTriangle;
using UniGLTF.SpringBoneJobs.Blittables;
using Unity.Collections;
@@ -63,7 +62,7 @@ namespace UniVRM10.ClothWarp.Jobs
if (c.colliderType == BlittableColliderType.Capsule)
{
if (TryCollideCapsuleAndSphere(m.MultiplyPoint(c.offset), m.MultiplyPoint(c.tailOrNormal), c.radius,
if (SphereSphereCollision.TryCollideCapsuleAndSphere(m.MultiplyPoint(c.offset), m.MultiplyPoint(c.tailOrNormal), c.radius,
pos, info.Settings.radius, out var l))
{
pos += l.GetDelta(c.radius);
@@ -71,7 +70,7 @@ namespace UniVRM10.ClothWarp.Jobs
}
else
{
if (TryCollideSphereAndSphere(m.MultiplyPoint(c.offset), c.radius,
if (SphereSphereCollision.TryCollideSphereAndSphere(m.MultiplyPoint(c.offset), c.radius,
pos, info.Settings.radius, out var l))
{
pos += l.GetDelta(c.radius);
@@ -82,72 +81,6 @@ namespace UniVRM10.ClothWarp.Jobs
StrandCollision[particleIndex] = pos;
}
}
/// <summary>
/// collide sphere a and sphere b.
/// move sphere b to resolved if collide.
/// </summary>
/// <param name="from"></param>
/// <param name="ra"></param>
/// <param name="to"></param>
/// <param name="ba"></param>
/// <param name="resolved"></param>
/// <returns></returns>
static bool TryCollideSphereAndSphere(
in Vector3 from, float ra,
in Vector3 to, float rb,
out LineSegment resolved
)
{
var d = Vector3.Distance(from, to);
if (d > (ra + rb))
{
resolved = default;
return false;
}
Vector3 normal = (to - from).normalized;
resolved = new(from, from + normal * (d - rb));
return true;
}
/// <summary>
/// collide capsule and sphere b.
/// move sphere b to resolved if collide.
/// </summary>
/// <param name="capsuleHead"></param>
/// <param name="capsuleTail"></param>
/// <param name="capsuleRadius"></param>
/// <param name="b"></param>
/// <param name="rb"></param>
static bool TryCollideCapsuleAndSphere(
in Vector3 capsuleHead,
in Vector3 capsuleTail,
float capsuleRadius,
in Vector3 b,
float rb,
out LineSegment resolved
)
{
var P = (capsuleTail - capsuleHead);
var Q = b - capsuleHead;
var dot = Vector3.Dot(P.normalized, Q);
if (dot <= 0)
{
// head側半球の球判定
return TryCollideSphereAndSphere(capsuleHead, capsuleRadius, b, rb, out resolved);
}
var t = dot / P.magnitude;
if (t >= 1.0f)
{
// tail側半球の球判定
return TryCollideSphereAndSphere(capsuleTail, capsuleRadius, b, rb, out resolved);
}
// head-tail上の m_transform.position との最近点
var p = capsuleHead + P * t;
return TryCollideSphereAndSphere(p, capsuleRadius, b, rb, out resolved);
}
}
public struct ClothCollisionJob : IJobParallelFor
@@ -159,7 +92,7 @@ namespace UniVRM10.ClothWarp.Jobs
// particle
[ReadOnly] public NativeArray<TransformInfo> Info;
[ReadOnly] public NativeArray<Vector3> NextPositions;
[NativeDisableParallelForRestriction] public NativeArray<int> CollisionCount;
// [NativeDisableParallelForRestriction] public NativeArray<int> CollisionCount;
[NativeDisableParallelForRestriction] public NativeArray<Vector3> ClothCollision;
// cloth
@@ -171,41 +104,10 @@ namespace UniVRM10.ClothWarp.Jobs
[ReadOnly] public NativeArray<ArrayRange> ColliderGroup;
[ReadOnly] public NativeArray<int> ColliderRef;
private void CollisionMove(int particleIndex, LineSegment l, BlittableCollider c)
{
#if false
CollisionCount[particleIndex] = 1;
ClothCollision[particleIndex] = l.GetPoint(c.radius);
#else
var delta = l.GetDelta(c.radius);
#if false
// 足して割る
CollisionCount[particleIndex] += 1;
CollisionDelta[particleIndex] += delta;
#elif false
// 足す
CollisionCount[particleIndex] = 1;
CollisionDelta[particleIndex] += delta;
#else
// max
if (delta.sqrMagnitude > ClothCollision[particleIndex].sqrMagnitude)
{
CollisionCount[particleIndex] = 1;
ClothCollision[particleIndex] = delta;
}
#endif
#endif
}
public void Execute(int rectIndex)
{
var (clothGridIndex, spring, rect) = ClothRects[rectIndex];
// using (new ProfileSample("Rect: Prepare"))
// _s0.BeginFrame();
// _s1.BeginFrame();
var a = NextPositions[rect._a];
var b = NextPositions[rect._b];
var c = NextPositions[rect._c];
@@ -222,6 +124,7 @@ namespace UniVRM10.ClothWarp.Jobs
var _triangle0 = new Triangle(a, b, c);
var cloth = Cloths[clothGridIndex];
for (int groupRefIndex = cloth.ColliderGroupRefRange.Start; groupRefIndex < cloth.ColliderGroupRefRange.End; ++groupRefIndex)
{
var groupIndex = ColliderGroupRef[groupRefIndex];
@@ -247,20 +150,34 @@ namespace UniVRM10.ClothWarp.Jobs
// continue;
// }
if (TryCollide(collider, collider_matrix, _triangle0, out var l0))
var abc = TryCollide(collider, collider_matrix, _triangle0, out var l0);
var cda = TryCollide(collider, collider_matrix, _triangle1, out var l1);
if (abc && cda)
{
CollisionMove(rect._a, l0, collider);
CollisionMove(rect._b, l0, collider);
CollisionMove(rect._c, l0, collider);
a += l0.GetDelta(collider.radius);
b += l0.GetDelta(collider.radius);
c += l1.GetDelta(collider.radius);
d += l1.GetDelta(collider.radius);
}
if (TryCollide(collider, collider_matrix, _triangle1, out var l1))
else if (abc)
{
CollisionMove(rect._c, l1, collider);
CollisionMove(rect._d, l1, collider);
CollisionMove(rect._a, l1, collider);
a += l0.GetDelta(collider.radius);
b += l0.GetDelta(collider.radius);
c += l0.GetDelta(collider.radius);
}
else if (cda)
{
c += l1.GetDelta(collider.radius);
d += l1.GetDelta(collider.radius);
a += l1.GetDelta(collider.radius);
}
}
}
ClothCollision[rect._a] = a;
ClothCollision[rect._b] = b;
ClothCollision[rect._c] = c;
ClothCollision[rect._d] = d;
}
static bool TryCollide(BlittableCollider collider, in Matrix4x4 colliderMatrix, in Triangle t, out LineSegment l)
@@ -351,7 +268,7 @@ namespace UniVRM10.ClothWarp.Jobs
{
[ReadOnly] public NativeArray<bool> ClothUsedParticles;
[ReadOnly] public NativeArray<Vector3> StrandCollision;
[ReadOnly] public NativeArray<int> ClothCollisionCount;
// [ReadOnly] public NativeArray<int> ClothCollisionCount;
[ReadOnly] public NativeArray<Vector3> ClothCollision;
[NativeDisableParallelForRestriction] public NativeArray<Vector3> NextPosition;
@@ -359,10 +276,10 @@ namespace UniVRM10.ClothWarp.Jobs
{
if (ClothUsedParticles[particleIndex])
{
if (ClothCollisionCount[particleIndex] > 0)
// if (ClothCollisionCount[particleIndex] > 0)
{
NextPosition[particleIndex] += (ClothCollision[particleIndex] / ClothCollisionCount[particleIndex]);
// NextPosition[particleIndex] = ClothCollision[particleIndex];
// NextPosition[particleIndex] += (ClothCollision[particleIndex] / ClothCollisionCount[particleIndex]);
NextPosition[particleIndex] = ClothCollision[particleIndex];
}
}
else

View File

@@ -43,7 +43,7 @@ namespace UniVRM10.ClothWarp.Jobs
[WriteOnly] public NativeArray<TransformData> InputData;
[WriteOnly] public NativeArray<Vector3> CurrentPositions;
[WriteOnly] public NativeArray<int> CollisionCount;
// [WriteOnly] public NativeArray<int> CollisionCount;
[WriteOnly] public NativeArray<Vector3> CollisionDelta;
[WriteOnly] public NativeArray<Vector3> Forces;
@@ -59,7 +59,7 @@ namespace UniVRM10.ClothWarp.Jobs
}
// clear cloth
CollisionCount[particleIndex] = 0;
// CollisionCount[particleIndex] = 0;
CollisionDelta[particleIndex] = Vector3.zero;
Forces[particleIndex] = Vector3.zero;
}

View File

@@ -0,0 +1,74 @@
using UnityEngine;
namespace SphereTriangle
{
public static class SphereSphereCollision
{
/// <summary>
/// collide sphere a and sphere b.
/// move sphere b to resolved if collide.
/// </summary>
/// <param name="from"></param>
/// <param name="ra"></param>
/// <param name="to"></param>
/// <param name="ba"></param>
/// <param name="resolved"></param>
/// <returns></returns>
public static bool TryCollideSphereAndSphere(
in Vector3 from, float ra,
in Vector3 to, float rb,
out LineSegment resolved
)
{
var d = Vector3.Distance(from, to);
if (d > (ra + rb))
{
resolved = default;
return false;
}
Vector3 normal = (to - from).normalized;
resolved = new(from, from + normal * (d - rb));
return true;
}
/// <summary>
/// collide capsule and sphere b.
/// move sphere b to resolved if collide.
/// </summary>
/// <param name="capsuleHead"></param>
/// <param name="capsuleTail"></param>
/// <param name="capsuleRadius"></param>
/// <param name="b"></param>
/// <param name="rb"></param>
public static bool TryCollideCapsuleAndSphere(
in Vector3 capsuleHead,
in Vector3 capsuleTail,
float capsuleRadius,
in Vector3 b,
float rb,
out LineSegment resolved
)
{
var P = (capsuleTail - capsuleHead);
var Q = b - capsuleHead;
var dot = Vector3.Dot(P.normalized, Q);
if (dot <= 0)
{
// head側半球の球判定
return TryCollideSphereAndSphere(capsuleHead, capsuleRadius, b, rb, out resolved);
}
var t = dot / P.magnitude;
if (t >= 1.0f)
{
// tail側半球の球判定
return TryCollideSphereAndSphere(capsuleTail, capsuleRadius, b, rb, out resolved);
}
// head-tail上の m_transform.position との最近点
var p = capsuleHead + P * t;
return TryCollideSphereAndSphere(p, capsuleRadius, b, rb, out resolved);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 990d1e921d604e348ab7fd04216b01d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: