ColliderGroupRefRange

This commit is contained in:
ousttrue
2024-11-29 23:54:52 +09:00
parent c2cab1c68c
commit 7fe84e533e
8 changed files with 249 additions and 85 deletions

View File

@@ -10,8 +10,8 @@ namespace UniVRM10.ClothWarp
class ClothRectList
{
readonly List<Transform> _particles;
public List<(SpringConstraint, ClothRect)> List = new();
public readonly ClothGrid[] ClothGrids;
public List<(int, SpringConstraint, ClothRect)> List = new();
public readonly bool[] ClothUsedParticles;
public ClothRectList(List<Transform> particles, Vrm10Instance vrm)
@@ -19,15 +19,16 @@ namespace UniVRM10.ClothWarp
_particles = particles;
ClothUsedParticles = new bool[_particles.Count];
var cloths = vrm.GetComponentsInChildren<ClothGrid>();
foreach (var cloth in cloths)
ClothGrids = vrm.GetComponentsInChildren<ClothGrid>();
for (int i = 0; i < ClothGrids.Length; ++i)
{
AddCloth(cloth, vrm);
AddCloth(i, vrm);
}
}
void AddCloth(ClothGrid cloth, Vrm10Instance vrm)
void AddCloth(int clothGridIndex, Vrm10Instance vrm)
{
var cloth = ClothGrids[clothGridIndex];
for (int i = 1; i < cloth.Warps.Count; ++i)
{
var s0 = cloth.Warps[i - 1];
@@ -53,6 +54,7 @@ namespace UniVRM10.ClothWarp
(c, d) = (d, c);
}
List.Add((
clothGridIndex,
new SpringConstraint(
_particles.IndexOf(a),
_particles.IndexOf(b),
@@ -91,6 +93,7 @@ namespace UniVRM10.ClothWarp
(c, d) = (d, c);
}
List.Add((
clothGridIndex,
new SpringConstraint(
_particles.IndexOf(a),
_particles.IndexOf(b),

View File

@@ -105,7 +105,7 @@ namespace UniVRM10.ClothWarp
_clothRectCollisions = new();
for (int i = 0; i < _clothRects.List.Count; ++i)
{
var (s, r) = _clothRects.List[i];
var (grid, s, r) = _clothRects.List[i];
_clothRectCollisions.Add(new());
var c = _clothRectCollisions.Last();
c.InitializeColliderSide(_newPos, _colliderGroups, r);
@@ -172,7 +172,7 @@ namespace UniVRM10.ClothWarp
// verlet 積分
var time = new FrameTime(deltaTime);
_list.BeginFrame(Env, time, _restPositions);
foreach (var (spring, collision) in _clothRects.List)
foreach (var (gridIndex, spring, collision) in _clothRects.List)
{
// cloth constraint
spring.Resolve(time, _clothFactor, _list._particles);
@@ -194,7 +194,7 @@ namespace UniVRM10.ClothWarp
for (int j = 0; j < _clothRects.List.Count; ++j)
{
var (spring, rect) = _clothRects.List[j];
var (gridIndex, spring, rect) = _clothRects.List[j];
var collision = _clothRectCollisions[j];
// using var prof = new ProfileSample("Collision: Cloth");
// 頂点 abcd は同じ CollisionMask

View File

@@ -7,7 +7,6 @@ using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Jobs;
using UniVRM10;
namespace UniVRM10.ClothWarp.Jobs
@@ -22,12 +21,25 @@ namespace UniVRM10.ClothWarp.Jobs
bool _building = false;
//
// collider
// colliderTransform
//
List<Transform> _colliderTransforms;
TransformAccessArray _colliderTransformAccessArray;
NativeArray<Matrix4x4> _currentColliders;
NativeArray<BlittableCollider> _colliders;
//
// collider
//
List<VRM10SpringBoneCollider> _colliders;
NativeArray<BlittableCollider> _colliderInfo;
//
// colliderGroup
//
List<VRM10SpringBoneColliderGroup> _colliderGroups;
NativeArray<int> _colliderRef;
NativeArray<ArrayRange> _colliderGroup;
NativeArray<int> _colliderGroupRef;
//
// particle
@@ -52,16 +64,25 @@ namespace UniVRM10.ClothWarp.Jobs
NativeArray<WarpInfo> _warps;
//
// cloth
// cloth rect
//
NativeArray<bool> _clothUsedParticles;
NativeArray<(SpringConstraint, SphereTriangle.ClothRect)> _clothRects;
NativeArray<(int ClothGridIndex, SpringConstraint SpringConstraint, SphereTriangle.ClothRect Rect)> _clothRects;
//
// cloth grid
//
NativeArray<ClothInfo> _cloths;
public void Dispose()
{
if (_colliderTransformAccessArray.isCreated) _colliderTransformAccessArray.Dispose();
if (_currentColliders.IsCreated) _currentColliders.Dispose();
if (_colliderRef.IsCreated) _colliderRef.Dispose();
if (_colliderGroup.IsCreated) _colliderGroup.Dispose();
if (_colliderGroupRef.IsCreated) _colliderGroupRef.Dispose();
if (_warps.IsCreated) _warps.Dispose();
if (_transformAccessArray.isCreated) _transformAccessArray.Dispose();
if (_inputData.IsCreated) _inputData.Dispose();
@@ -76,6 +97,7 @@ namespace UniVRM10.ClothWarp.Jobs
if (_forces.IsCreated) _forces.Dispose();
if (_warps.IsCreated) _warps.Dispose();
if (_cloths.IsCreated) _cloths.Dispose();
if (_clothUsedParticles.IsCreated) _clothUsedParticles.Dispose();
if (_clothRects.IsCreated) _clothRects.Dispose();
@@ -100,6 +122,17 @@ namespace UniVRM10.ClothWarp.Jobs
return (i, true);
}
int GetOrAddColliderTransform(Transform t)
{
var index = _colliderTransforms.IndexOf(t);
if (index == -1)
{
index = _colliderTransforms.Count;
_colliderTransforms.Add(t);
}
return index;
}
public async Task InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller)
{
_vrm = vrm;
@@ -114,22 +147,58 @@ namespace UniVRM10.ClothWarp.Jobs
//
// colliders
//
_colliders = new();
_colliderGroups = new();
_colliderTransforms = new();
List<BlittableCollider> colliders = new();
foreach (var collider in vrm.GetComponentsInChildren<VRM10SpringBoneCollider>())
List<BlittableCollider> colliderInfo = new();
List<int> colliderRef = new();
List<ArrayRange> colliderGroups = new();
foreach (var colliderGroup in vrm.GetComponentsInChildren<VRM10SpringBoneColliderGroup>())
{
colliders.Add(new BlittableCollider
if (colliderGroup == null)
{
offset = collider.Offset,
radius = collider.Radius,
tailOrNormal = collider.TailOrNormal,
colliderType = TranslateColliderType(collider.ColliderType)
continue;
}
var startColliderRef = colliderRef.Count;
foreach (var collider in colliderGroup.Colliders)
{
if (collider == null)
{
continue;
}
if (_colliders.Contains(collider))
{
continue;
}
var colliderTransformIndex = GetOrAddColliderTransform(collider.transform);
colliderRef.Add(colliderInfo.Count);
colliderInfo.Add(new BlittableCollider
{
offset = collider.Offset,
radius = collider.Radius,
tailOrNormal = collider.TailOrNormal,
colliderType = TranslateColliderType(collider.ColliderType),
transformIndex = colliderTransformIndex,
});
_colliders.Add(collider);
}
_colliderGroups.Add(colliderGroup);
colliderGroups.Add(new ArrayRange
{
Start = startColliderRef,
End = colliderRef.Count,
});
_colliderTransforms.Add(collider.transform);
}
_colliderTransformAccessArray = new(_colliderTransforms.ToArray(), 128);
_colliders = new(colliders.ToArray(), Allocator.Persistent);
_currentColliders = new(_colliderTransforms.Count, Allocator.Persistent);
_colliderInfo = new(colliderInfo.ToArray(), Allocator.Persistent);
_colliderRef = new(colliderRef.ToArray(), Allocator.Persistent);
_colliderGroup = new(colliderGroups.ToArray(), Allocator.Persistent);
//
// warps => particles
@@ -138,6 +207,7 @@ namespace UniVRM10.ClothWarp.Jobs
List<TransformInfo> info = new();
List<Vector3> positions = new();
List<WarpInfo> warps = new();
List<int> colliderGroupRef = new();
var warpSrcs = vrm.GetComponentsInChildren<Components.ClothWarpRoot>();
for (int warpIndex = 0; warpIndex < warpSrcs.Length; ++warpIndex)
{
@@ -148,14 +218,16 @@ namespace UniVRM10.ClothWarp.Jobs
{
GetTransformIndex(warp.Center, new TransformInfo
{
TransformType = TransformType.Center
TransformType = TransformType.Center,
WarpIndex = warpIndex,
}, info, positions);
start += 1;
}
var warpRootParentTransformIndex = GetTransformIndex(warp.transform.parent, new TransformInfo
{
TransformType = TransformType.WarpRootParent
TransformType = TransformType.WarpRootParent,
WarpIndex = warpIndex,
}, info, positions);
Debug.Assert(warpRootParentTransformIndex.index != -1);
if (warpRootParentTransformIndex.isNew)
@@ -169,6 +241,7 @@ namespace UniVRM10.ClothWarp.Jobs
ParentIndex = warpRootParentTransformIndex.index,
InitLocalPosition = vrm.DefaultTransformStates[warp.transform].LocalPosition,
InitLocalRotation = vrm.DefaultTransformStates[warp.transform].LocalRotation,
WarpIndex = warpIndex,
}, info, positions);
Debug.Assert(warpRootTransformIndex.index != -1);
if (!warpRootTransformIndex.isNew)
@@ -189,11 +262,21 @@ namespace UniVRM10.ClothWarp.Jobs
InitLocalPosition = vrm.DefaultTransformStates[particle.Transform].LocalPosition,
InitLocalRotation = vrm.DefaultTransformStates[particle.Transform].LocalRotation,
Settings = particle.Settings,
WarpIndex = warpIndex,
}, info, positions);
parentIndex = outputParticleTransformIndex.index;
}
}
var colliderGroupRefStart = colliderGroupRef.Count;
foreach (var group in warp.ColliderGroups)
{
if (group != null)
{
colliderGroupRef.Add(_colliderGroups.IndexOf(group));
}
}
warps.Add(new WarpInfo
{
PrticleRange = new ArrayRange
@@ -201,6 +284,11 @@ namespace UniVRM10.ClothWarp.Jobs
Start = start,
End = _transforms.Count,
},
ColliderGroupRefRange = new ArrayRange
{
Start = colliderGroupRefStart,
End = colliderGroupRef.Count,
},
});
await awaitCaller.NextFrame();
@@ -226,6 +314,35 @@ namespace UniVRM10.ClothWarp.Jobs
_clothRects = new(clothRects.List.ToArray(), Allocator.Persistent);
_clothUsedParticles = new(clothRects.ClothUsedParticles, Allocator.Persistent);
_building = false;
List<ClothInfo> cloths = new();
foreach (var grid in clothRects.ClothGrids)
{
var colliderGroupRefStart = colliderGroupRef.Count;
HashSet<VRM10SpringBoneColliderGroup> groups = new();
foreach (var warp in grid.Warps)
{
foreach (var group in warp.ColliderGroups)
{
if (group != null && !groups.Contains(group))
{
groups.Add(group);
colliderGroupRef.Add(_colliderGroups.IndexOf(group));
}
}
}
cloths.Add(new ClothInfo
{
ColliderGroupRefRange = new ArrayRange
{
Start = colliderGroupRefStart,
End = colliderGroupRef.Count,
},
});
}
_cloths = new(cloths.ToArray(), Allocator.Persistent);
_colliderGroupRef = new(colliderGroupRef.ToArray(), Allocator.Persistent);
}
private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType)
@@ -310,18 +427,23 @@ namespace UniVRM10.ClothWarp.Jobs
{
var handle0 = new StrandCollisionJob
{
Colliders = _colliders,
Colliders = _colliderInfo,
CurrentColliders = _currentColliders,
Info = _info,
NextPositions = _nextPositions,
ClothUsedParticles = _clothUsedParticles,
StrandCollision = _strandCollision,
Warps = _warps,
ColliderGroupRef = _colliderGroupRef,
ColliderGroup = _colliderGroup,
ColliderRef = _colliderRef,
}.Schedule(_info.Length, 1, handle);
var handle1 = new ClothCollisionJob
{
Colliders = _colliders,
Colliders = _colliderInfo,
CurrentColliders = _currentColliders,
Info = _info,
@@ -330,6 +452,11 @@ namespace UniVRM10.ClothWarp.Jobs
ClothCollision = _clothCollision,
ClothRects = _clothRects,
Cloths = _cloths,
ColliderGroupRef = _colliderGroupRef,
ColliderGroup = _colliderGroup,
ColliderRef = _colliderRef,
}.Schedule(_clothRects.Length, 1, handle);
handle = JobHandle.CombineDependencies(handle0, handle1);

View File

@@ -10,6 +10,11 @@ using UnityEngine.Jobs;
namespace UniVRM10.ClothWarp.Jobs
{
public struct ClothInfo
{
public ArrayRange ColliderGroupRefRange;
}
public struct InputColliderJob : IJobParallelForTransform
{
[WriteOnly] public NativeArray<Matrix4x4> CurrentCollider;
@@ -32,31 +37,45 @@ namespace UniVRM10.ClothWarp.Jobs
[ReadOnly] public NativeArray<bool> ClothUsedParticles;
[WriteOnly] public NativeArray<Vector3> StrandCollision;
// collider group
[ReadOnly] public NativeArray<WarpInfo> Warps;
[ReadOnly] public NativeArray<int> ColliderGroupRef;
[ReadOnly] public NativeArray<ArrayRange> ColliderGroup;
[ReadOnly] public NativeArray<int> ColliderRef;
public void Execute(int particleIndex)
{
if (!ClothUsedParticles[particleIndex])
{
var info = Info[particleIndex];
var pos = NextPositions[particleIndex];
for (int colliderIndex = 0; colliderIndex < Colliders.Length; ++colliderIndex)
{
var c = Colliders[colliderIndex];
var m = CurrentColliders[colliderIndex];
var warp = Warps[info.WarpIndex];
if (c.colliderType == BlittableColliderType.Capsule)
for (int groupRefIndex = warp.ColliderGroupRefRange.Start; groupRefIndex < warp.ColliderGroupRefRange.End; ++groupRefIndex)
{
var groupIndex = ColliderGroupRef[groupRefIndex];
var group = ColliderGroup[groupIndex];
for (int colliderRefIndex = group.Start; colliderRefIndex < group.End; ++colliderRefIndex)
{
if (TryCollideCapsuleAndSphere(m.MultiplyPoint(c.offset), m.MultiplyPoint(c.tailOrNormal), c.radius,
pos, info.Settings.radius, out var l))
var colliderIndex = ColliderRef[colliderRefIndex];
var c = Colliders[colliderIndex];
var m = CurrentColliders[c.transformIndex];
if (c.colliderType == BlittableColliderType.Capsule)
{
pos += l.GetDelta(c.radius);
if (TryCollideCapsuleAndSphere(m.MultiplyPoint(c.offset), m.MultiplyPoint(c.tailOrNormal), c.radius,
pos, info.Settings.radius, out var l))
{
pos += l.GetDelta(c.radius);
}
}
}
else
{
if (TryCollideSphereAndSphere(m.MultiplyPoint(c.offset), c.radius,
pos, info.Settings.radius, out var l))
else
{
pos += l.GetDelta(c.radius);
if (TryCollideSphereAndSphere(m.MultiplyPoint(c.offset), c.radius,
pos, info.Settings.radius, out var l))
{
pos += l.GetDelta(c.radius);
}
}
}
}
@@ -144,7 +163,13 @@ namespace UniVRM10.ClothWarp.Jobs
[NativeDisableParallelForRestriction] public NativeArray<Vector3> ClothCollision;
// cloth
[ReadOnly] public NativeArray<(SpringConstraint, ClothRect)> ClothRects;
[ReadOnly] public NativeArray<(int, SpringConstraint, ClothRect)> ClothRects;
// collider group
[ReadOnly] public NativeArray<ClothInfo> Cloths;
[ReadOnly] public NativeArray<int> ColliderGroupRef;
[ReadOnly] public NativeArray<ArrayRange> ColliderGroup;
[ReadOnly] public NativeArray<int> ColliderRef;
private void CollisionMove(int particleIndex, LineSegment l, BlittableCollider c)
{
@@ -175,7 +200,7 @@ namespace UniVRM10.ClothWarp.Jobs
public void Execute(int rectIndex)
{
var (spring, rect) = ClothRects[rectIndex];
var (clothGridIndex, spring, rect) = ClothRects[rectIndex];
// using (new ProfileSample("Rect: Prepare"))
// _s0.BeginFrame();
@@ -196,36 +221,44 @@ namespace UniVRM10.ClothWarp.Jobs
// a x-x b
var _triangle0 = new Triangle(a, b, c);
for (int colliderIndex = 0; colliderIndex < Colliders.Length; ++colliderIndex)
var cloth = Cloths[clothGridIndex];
for (int groupRefIndex = cloth.ColliderGroupRefRange.Start; groupRefIndex < cloth.ColliderGroupRefRange.End; ++groupRefIndex)
{
var collider = Colliders[colliderIndex];
var collider_matrix = CurrentColliders[colliderIndex];
if (!aabb.Intersects(GetBounds(collider, collider_matrix)))
{
continue;
}
var groupIndex = ColliderGroupRef[groupRefIndex];
// 面の片側だけにヒットさせる
// 行き過ぎて戻るときに素通りする
// var p = _triangle0.Plane.ClosestPointOnPlane(col_pos);
// var dot = Vector3.Dot(_triangle0.Plane.normal, col_pos - p);
// if (_initialColliderNormalSide[collider] * dot < 0)
// {
// // 片側
// continue;
// }
var group = ColliderGroup[groupIndex];
for (int colliderRefIndex = group.Start; colliderRefIndex < group.End; ++colliderRefIndex)
{
var colliderIndex = ColliderRef[colliderRefIndex];
var collider = Colliders[colliderIndex];
var collider_matrix = CurrentColliders[collider.transformIndex];
if (!aabb.Intersects(GetBounds(collider, collider_matrix)))
{
continue;
}
if (TryCollide(collider, collider_matrix, _triangle0, out var l0))
{
CollisionMove(rect._a, l0, collider);
CollisionMove(rect._b, l0, collider);
CollisionMove(rect._c, l0, collider);
}
if (TryCollide(collider, collider_matrix, _triangle1, out var l1))
{
CollisionMove(rect._c, l1, collider);
CollisionMove(rect._d, l1, collider);
CollisionMove(rect._a, l1, collider);
// 面の片側だけにヒットさせる
// 行き過ぎて戻るときに素通りする
// 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, collider_matrix, _triangle0, out var l0))
{
CollisionMove(rect._a, l0, collider);
CollisionMove(rect._b, l0, collider);
CollisionMove(rect._c, l0, collider);
}
if (TryCollide(collider, collider_matrix, _triangle1, out var l1))
{
CollisionMove(rect._c, l1, collider);
CollisionMove(rect._d, l1, collider);
CollisionMove(rect._a, l1, collider);
}
}
}
}

View File

@@ -30,13 +30,13 @@ namespace UniVRM10.ClothWarp.Jobs
{
public float Hookean;
FrameInfo Frame;
[ReadOnly] public NativeArray<(SpringConstraint, ClothRect)> ClothRects;
[ReadOnly] public NativeArray<(int, SpringConstraint, ClothRect)> ClothRects;
[ReadOnly] public NativeArray<Vector3> CurrentPositions;
[NativeDisableParallelForRestriction] public NativeArray<Vector3> Force;
public void Execute(int rectIndex)
{
var (spring, rect) = ClothRects[rectIndex];
var (clothGridIndex, spring, rect) = ClothRects[rectIndex];
var p0 = CurrentPositions[spring._p0];
var p1 = CurrentPositions[spring._p1];
var d = Vector3.Distance(p0, p1);

View File

@@ -14,6 +14,7 @@ namespace UniVRM10.ClothWarp.Jobs
public Quaternion InitLocalRotation;
public Vector3 InitLocalPosition;
public BlittableJointMutable Settings;
public int WarpIndex;
}
public struct TransformData

View File

@@ -9,6 +9,6 @@ namespace UniVRM10.ClothWarp.Jobs
public struct WarpInfo
{
public ArrayRange PrticleRange;
public ArrayRange ColliderGroupRange;
public ArrayRange ColliderGroupRefRange;
}
}

View File

@@ -230,19 +230,19 @@ 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)
// {