From b577c3bb9f1402236e91cb06889acb1f6a330e1c Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 20 Nov 2024 17:12:18 +0900 Subject: [PATCH] WIP collider --- .../Runtime/Jobs/RotateParticleJobSystem.cs | 280 ++++++------------ .../RotateParticle/Runtime/Jobs/Types.cs | 221 ++++++++++++++ .../RotateParticle/Runtime/Jobs/Types.cs.meta | 11 + 3 files changed, 321 insertions(+), 191 deletions(-) create mode 100644 Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs create mode 100644 Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs.meta diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/RotateParticleJobSystem.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/RotateParticleJobSystem.cs index 2736cb012..ecaadbeda 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/RotateParticleJobSystem.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/RotateParticleJobSystem.cs @@ -13,78 +13,41 @@ using UniVRM10; namespace RotateParticle.Jobs { - public enum TransformType - { - Center, - WarpRootParent, - WarpRoot, - Particle, - } - - public static class TransformTypeExtensions - { - public static bool PositionInput(this TransformType t) - { - return t == TransformType.WarpRoot; - } - - public static bool Movable(this TransformType t) - { - return t == TransformType.Particle; - } - - public static bool Writable(this TransformType t) - { - switch (t) - { - case TransformType.WarpRoot: - case TransformType.Particle: - return true; - default: - return false; - } - } - } - public class RotateParticleJobSystem : IRotateParticleSystem { Vrm10Instance _vrm; - public struct TransformInfo - { - public TransformType TransformType; - public int ParentIndex; - public Quaternion InitLocalRotation; - public Vector3 InitLocalPosition; - public BlittableJointMutable Settings; - } - - public struct TransformData - { - public Matrix4x4 ToWorld; - public Vector3 Position => ToWorld.GetPosition(); - public Quaternion Rotation => ToWorld.rotation; - public Matrix4x4 ToLocal; - - public TransformData(TransformAccess t) - { - ToWorld = t.localToWorldMatrix; - ToLocal = t.worldToLocalMatrix; - } - public TransformData(Transform t) - { - ToWorld = t.localToWorldMatrix; - ToLocal = t.worldToLocalMatrix; - } - } - - public struct WarpInfo - { - public int StartIndex; - public int EndIndex; - } + List _colliderTransforms; + TransformAccessArray _colliderTransformAccessArray; + NativeArray _currentColliders; + NativeArray _colliders; List _transforms; + TransformAccessArray _transformAccessArray; + NativeArray _inputData; + NativeArray _info; + NativeArray _currentPositions; + NativeArray _prevPositions; + NativeArray _nextPositions; + NativeArray _nextRotations; + + NativeArray _warps; + + void IDisposable.Dispose() + { + if (_colliderTransformAccessArray.isCreated) _colliderTransformAccessArray.Dispose(); + if (_currentColliders.IsCreated) _currentColliders.Dispose(); + + if (_warps.IsCreated) _warps.Dispose(); + if (_transformAccessArray.isCreated) _transformAccessArray.Dispose(); + if (_inputData.IsCreated) _inputData.Dispose(); + if (_info.IsCreated) _info.Dispose(); + if (_currentPositions.IsCreated) _currentPositions.Dispose(); + if (_prevPositions.IsCreated) _prevPositions.Dispose(); + if (_nextPositions.IsCreated) _nextPositions.Dispose(); + if (_nextRotations.IsCreated) _nextRotations.Dispose(); + } + (int index, bool isNew) GetTransformIndex(Transform t, TransformInfo info, List infos, @@ -104,132 +67,33 @@ namespace RotateParticle.Jobs return (i, true); } - NativeArray _warps; - - TransformAccessArray _transformAccessArray; - NativeArray _inputData; - NativeArray _info; - NativeArray _currentPositions; - NativeArray _prevPositions; - NativeArray _nextPositions; - NativeArray _nextRotations; - - void IDisposable.Dispose() - { - if (_warps.IsCreated) _warps.Dispose(); - if (_transformAccessArray.isCreated) _transformAccessArray.Dispose(); - if (_inputData.IsCreated) _inputData.Dispose(); - if (_info.IsCreated) _info.Dispose(); - if (_currentPositions.IsCreated) _currentPositions.Dispose(); - if (_prevPositions.IsCreated) _prevPositions.Dispose(); - if (_nextPositions.IsCreated) _nextPositions.Dispose(); - if (_nextRotations.IsCreated) _nextRotations.Dispose(); - } - - // [Input] - public struct InputTransformJob : IJobParallelForTransform - { - [ReadOnly] public NativeArray Info; - [WriteOnly] public NativeArray InputData; - [WriteOnly] public NativeArray CurrentPositions; - public void Execute(int index, TransformAccess transform) - { - InputData[index] = new TransformData(transform); - - var particle = Info[index]; - if (particle.TransformType.PositionInput()) - { - // only warp root position update - CurrentPositions[index] = transform.position; - } - } - } - - public struct VerletJob : IJobParallelFor - { - public FrameInfo Frame; - [ReadOnly] public NativeArray Info; - [ReadOnly] public NativeArray CurrentTransforms; - [ReadOnly] public NativeArray CurrentPositions; - [ReadOnly] public NativeArray PrevPositions; - [WriteOnly] public NativeArray NextPositions; - [WriteOnly] public NativeArray NextRotations; - - public void Execute(int index) - { - var particle = Info[index]; - if (particle.TransformType.Movable()) - { - var parentIndex = particle.ParentIndex; - var parentPosition = CurrentPositions[parentIndex]; - var parent = Info[parentIndex]; - var parentParentRotation = CurrentTransforms[parent.ParentIndex].Rotation; - - var external = (particle.Settings.gravityDir * particle.Settings.gravityPower + Frame.Force) * Frame.DeltaTime; - - var newPosition = CurrentPositions[index] - + (CurrentPositions[index] - PrevPositions[index]) * (1.0f - particle.Settings.dragForce) - + parentParentRotation * parent.InitLocalRotation * particle.InitLocalPosition * - particle.Settings.stiffnessForce * Frame.DeltaTime // 親の回転による子ボーンの移動目標 - + external - ; - - // 位置を長さで拘束 - newPosition = parentPosition + (newPosition - parentPosition).normalized * particle.InitLocalPosition.magnitude; - - NextPositions[index] = newPosition; - } - else - { - // kinematic - NextPositions[index] = CurrentPositions[index]; - } - - NextRotations[index] = CurrentTransforms[index].Rotation; - } - } - - public struct ApplyRotationJob : IJobParallelFor - { - [ReadOnly] public NativeArray Warps; - [ReadOnly] public NativeArray Info; - [ReadOnly] public NativeArray CurrentTransforms; - [ReadOnly] public NativeArray NextPositions; - [NativeDisableParallelForRestriction] public NativeArray NextRotations; - public void Execute(int index) - { - // warp 一本を親から子に再帰的に実行して回転を確定させる - var warp = Warps[index]; - for (int i = warp.StartIndex; i < warp.EndIndex - 1; ++i) - { - //回転を適用 - var p = Info[i]; - var rotation = NextRotations[p.ParentIndex] * Info[i].InitLocalRotation; - NextRotations[i] = Quaternion.FromToRotation( - rotation * Info[i + 1].InitLocalPosition, - NextPositions[i + 1] - NextPositions[i]) * rotation; - } - } - } - - // [Output] - public struct OutputTransformJob : IJobParallelForTransform - { - [ReadOnly] public NativeArray Info; - [ReadOnly] public NativeArray NextRotations; - public void Execute(int index, TransformAccess transform) - { - var info = Info[index]; - if (info.TransformType.Writable()) - { - transform.rotation = NextRotations[index]; - } - } - } - async Task IRotateParticleSystem.InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller) { _vrm = vrm; + + // + // colliders + // + _colliderTransforms = new(); + List colliders = new(); + foreach (var collider in vrm.GetComponentsInChildren()) + { + colliders.Add(new BlittableCollider + { + offset = collider.Offset, + radius = collider.Radius, + tailOrNormal = collider.TailOrNormal, + colliderType = TranslateColliderType(collider.ColliderType) + }); + _colliderTransforms.Add(collider.transform); + } + _colliderTransformAccessArray = new(_colliderTransforms.ToArray(), 128); + _colliders = new(colliders.ToArray(), Allocator.Persistent); + _currentColliders = new(_colliderTransforms.Count, Allocator.Persistent); + + // + // warps + // _transforms = new(); List info = new(); List positions = new(); @@ -305,17 +169,43 @@ namespace RotateParticle.Jobs _info = new(info.ToArray(), Allocator.Persistent); } + private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType) + { + switch (colliderType) + { + case VRM10SpringBoneColliderTypes.Sphere: + return BlittableColliderType.Sphere; + case VRM10SpringBoneColliderTypes.Capsule: + return BlittableColliderType.Capsule; + case VRM10SpringBoneColliderTypes.Plane: + return BlittableColliderType.Plane; + case VRM10SpringBoneColliderTypes.SphereInside: + return BlittableColliderType.SphereInside; + case VRM10SpringBoneColliderTypes.CapsuleInside: + return BlittableColliderType.CapsuleInside; + default: + throw new ArgumentOutOfRangeException(); + } + } + void IRotateParticleSystem.Process(float deltaTime) { var frame = new FrameInfo(deltaTime, Vector3.zero); + JobHandle handle = default; + // input - var handle = new InputTransformJob + handle = new InputColliderJob + { + CurrentCollider = _currentColliders, + }.Schedule(_colliderTransformAccessArray, handle); + + handle = new InputTransformJob { Info = _info, InputData = _inputData, CurrentPositions = _currentPositions, - }.Schedule(_transformAccessArray, default); + }.Schedule(_transformAccessArray, handle); // verlet handle = new VerletJob @@ -329,6 +219,14 @@ namespace RotateParticle.Jobs NextRotations = _nextRotations, }.Schedule(_info.Length, 128, handle); + // collision + handle = new CollisionJob + { + Colliders = _colliders, + CurrentColliders = _currentColliders, + NextPositions = _nextPositions, + }.Schedule(_info.Length, 128, handle); + // NextPositions から NextRotations を作る handle = new ApplyRotationJob { diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs new file mode 100644 index 000000000..f81418139 --- /dev/null +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs @@ -0,0 +1,221 @@ +using System.Collections; +using System.Collections.Generic; +using UniGLTF.SpringBoneJobs.Blittables; +using Unity.Collections; +using Unity.Jobs; +using UnityEngine; +using UnityEngine.Jobs; + +namespace RotateParticle.Jobs +{ + public enum TransformType + { + Center, + WarpRootParent, + WarpRoot, + Particle, + } + + public static class TransformTypeExtensions + { + public static bool PositionInput(this TransformType t) + { + return t == TransformType.WarpRoot; + } + + public static bool Movable(this TransformType t) + { + return t == TransformType.Particle; + } + + public static bool Writable(this TransformType t) + { + switch (t) + { + case TransformType.WarpRoot: + case TransformType.Particle: + return true; + default: + return false; + } + } + } + + public struct TransformInfo + { + public TransformType TransformType; + public int ParentIndex; + public Quaternion InitLocalRotation; + public Vector3 InitLocalPosition; + public BlittableJointMutable Settings; + } + + public struct TransformData + { + public Matrix4x4 ToWorld; + public Vector3 Position => ToWorld.GetPosition(); + public Quaternion Rotation => ToWorld.rotation; + public Matrix4x4 ToLocal; + + public TransformData(TransformAccess t) + { + ToWorld = t.localToWorldMatrix; + ToLocal = t.worldToLocalMatrix; + } + public TransformData(Transform t) + { + ToWorld = t.localToWorldMatrix; + ToLocal = t.worldToLocalMatrix; + } + } + + public struct WarpInfo + { + public int StartIndex; + public int EndIndex; + } + + // [Input] + public struct InputColliderJob : IJobParallelForTransform + { + [WriteOnly] public NativeArray CurrentCollider; + + public void Execute(int index, TransformAccess transform) + { + CurrentCollider[index] = transform.localToWorldMatrix; + } + } + + public struct InputTransformJob : IJobParallelForTransform + { + [ReadOnly] public NativeArray Info; + [WriteOnly] public NativeArray InputData; + [WriteOnly] public NativeArray CurrentPositions; + public void Execute(int index, TransformAccess transform) + { + InputData[index] = new TransformData(transform); + + var particle = Info[index]; + if (particle.TransformType.PositionInput()) + { + // only warp root position update + CurrentPositions[index] = transform.position; + } + } + } + + public struct VerletJob : IJobParallelFor + { + public FrameInfo Frame; + [ReadOnly] public NativeArray Info; + [ReadOnly] public NativeArray CurrentTransforms; + [ReadOnly] public NativeArray CurrentPositions; + [ReadOnly] public NativeArray PrevPositions; + [WriteOnly] public NativeArray NextPositions; + [WriteOnly] public NativeArray NextRotations; + + public void Execute(int index) + { + var particle = Info[index]; + if (particle.TransformType.Movable()) + { + var parentIndex = particle.ParentIndex; + var parentPosition = CurrentPositions[parentIndex]; + var parent = Info[parentIndex]; + var parentParentRotation = CurrentTransforms[parent.ParentIndex].Rotation; + + var external = (particle.Settings.gravityDir * particle.Settings.gravityPower + Frame.Force) * Frame.DeltaTime; + + var newPosition = CurrentPositions[index] + + (CurrentPositions[index] - PrevPositions[index]) * (1.0f - particle.Settings.dragForce) + + parentParentRotation * parent.InitLocalRotation * particle.InitLocalPosition * + particle.Settings.stiffnessForce * Frame.DeltaTime // 親の回転による子ボーンの移動目標 + + external + ; + + // 位置を長さで拘束 + newPosition = parentPosition + (newPosition - parentPosition).normalized * particle.InitLocalPosition.magnitude; + + NextPositions[index] = newPosition; + } + else + { + // kinematic + NextPositions[index] = CurrentPositions[index]; + } + + NextRotations[index] = CurrentTransforms[index].Rotation; + } + } + + public struct CollisionJob : IJobParallelFor + { + [ReadOnly] public NativeArray Colliders; + [ReadOnly] public NativeArray CurrentColliders; + [WriteOnly] public NativeArray NextPositions; + + public void Execute(int index) + { + for (int i = 0; i < Colliders.Length; ++i) + { + var c = Colliders[i]; + switch (c.colliderType) + { + case BlittableColliderType.Sphere: + break; + + default: + // TODO + break; + } + } + // 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; + } + } + + public struct ApplyRotationJob : IJobParallelFor + { + [ReadOnly] public NativeArray Warps; + [ReadOnly] public NativeArray Info; + [ReadOnly] public NativeArray CurrentTransforms; + [ReadOnly] public NativeArray NextPositions; + [NativeDisableParallelForRestriction] public NativeArray NextRotations; + public void Execute(int index) + { + // warp 一本を親から子に再帰的に実行して回転を確定させる + var warp = Warps[index]; + for (int i = warp.StartIndex; i < warp.EndIndex - 1; ++i) + { + //回転を適用 + var p = Info[i]; + var rotation = NextRotations[p.ParentIndex] * Info[i].InitLocalRotation; + NextRotations[i] = Quaternion.FromToRotation( + rotation * Info[i + 1].InitLocalPosition, + NextPositions[i + 1] - NextPositions[i]) * rotation; + } + } + } + + // [Output] + public struct OutputTransformJob : IJobParallelForTransform + { + [ReadOnly] public NativeArray Info; + [ReadOnly] public NativeArray NextRotations; + public void Execute(int index, TransformAccess transform) + { + var info = Info[index]; + if (info.TransformType.Writable()) + { + transform.rotation = NextRotations[index]; + } + } + } +} diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs.meta b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs.meta new file mode 100644 index 000000000..7c59093ea --- /dev/null +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/Jobs/Types.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 139cb8a384ad8c64abc4dcfab37bcaca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: