From 5f41b780ae1585b25eb750b08e371856a8532ea0 Mon Sep 17 00:00:00 2001 From: notargs Date: Wed, 29 Sep 2021 17:02:45 +0900 Subject: [PATCH] Add fastSpringBone10 --- Assets/VRM10/Runtime/FastSpringBone.meta | 8 + .../Runtime/FastSpringBone/Blittables.meta | 8 + .../Blittables/BlittableCollider.cs | 20 +++ .../Blittables/BlittableCollider.cs.meta | 3 + .../Blittables/BlittableColliderGroup.cs | 20 +++ .../Blittables/BlittableColliderGroup.cs.meta | 3 + .../Blittables/BlittableColliderGroups.cs | 34 ++++ .../BlittableColliderGroups.cs.meta | 3 + .../Blittables/BlittableColliders.cs | 19 +++ .../Blittables/BlittableColliders.cs.meta | 3 + .../Blittables/BlittablePoint.cs | 149 ++++++++++++++++++ .../Blittables/BlittablePoint.cs.meta | 3 + .../Blittables/BlittablePoints.cs | 23 +++ .../Blittables/BlittablePoints.cs.meta | 3 + .../Blittables/BlittableRootBone.cs | 64 ++++++++ .../Blittables/BlittableRootBone.cs.meta | 3 + .../Blittables/BlittableTransform.cs | 72 +++++++++ .../Blittables/BlittableTransform.cs.meta | 3 + .../Runtime/FastSpringBone/Components.meta | 8 + .../Components/FastSpringBoneColliderGroup.cs | 31 ++++ .../FastSpringBoneColliderGroup.cs.meta | 3 + .../Components/FastSpringBoneScheduler.cs | 100 ++++++++++++ .../FastSpringBoneScheduler.cs.meta | 3 + .../Components/FastSpringRootBone.cs | 124 +++++++++++++++ .../Components/FastSpringRootBone.cs.meta | 3 + .../FastSpringBone/FastSpringBone10.asmdef | 21 +++ .../FastSpringBone10.asmdef.meta | 7 + .../FastSpringBone/NativeWrappers.meta | 8 + .../NativeWrappers/NativeColliderGroup.cs | 31 ++++ .../NativeColliderGroup.cs.meta | 3 + .../NativeWrappers/NativeColliderGroups.cs | 78 +++++++++ .../NativeColliderGroups.cs.meta | 3 + .../NativeWrappers/NativePointer.cs | 35 ++++ .../NativeWrappers/NativePointer.cs.meta | 3 + .../NativeWrappers/NativePoints.cs | 39 +++++ .../NativeWrappers/NativePoints.cs.meta | 3 + .../NativeWrappers/NativeTransform.cs | 43 +++++ .../NativeWrappers/NativeTransform.cs.meta | 3 + .../Runtime/FastSpringBone/Registries.meta | 8 + .../Registries/ColliderGroupRegistry.cs | 8 + .../Registries/ColliderGroupRegistry.cs.meta | 3 + .../FastSpringBone/Registries/Registry.cs | 28 ++++ .../Registries/Registry.cs.meta | 3 + .../Registries/RootBoneRegistry.cs | 12 ++ .../Registries/RootBoneRegistry.cs.meta | 3 + .../Registries/TransformRegistry.cs | 60 +++++++ .../Registries/TransformRegistry.cs.meta | 3 + .../TransformSynchronizationType.cs | 8 + .../TransformSynchronizationType.cs.meta | 3 + .../Runtime/FastSpringBone/Schedulers.meta | 8 + .../Schedulers/PullTransformJobScheduler.cs | 119 ++++++++++++++ .../PullTransformJobScheduler.cs.meta | 3 + .../Schedulers/PushTransformJobScheduler.cs | 119 ++++++++++++++ .../PushTransformJobScheduler.cs.meta | 3 + .../UpdateSpringBoneJobScheduler.cs | 113 +++++++++++++ .../UpdateSpringBoneJobScheduler.cs.meta | 3 + 56 files changed, 1497 insertions(+) create mode 100644 Assets/VRM10/Runtime/FastSpringBone.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef create mode 100644 Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs.meta create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs create mode 100644 Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs.meta diff --git a/Assets/VRM10/Runtime/FastSpringBone.meta b/Assets/VRM10/Runtime/FastSpringBone.meta new file mode 100644 index 000000000..f7e4648ad --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 197e77a1310790d4786b7d9adca918b6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables.meta new file mode 100644 index 000000000..45d059d0f --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9d242d5eb124c341a1685fa016f73b7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs new file mode 100644 index 000000000..351806a00 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// VRMSpringBoneのSphereColliderをBlittableにしたもの + /// 位置情報は親であるColliderGroupが持つ + /// + public readonly struct BlittableCollider + { + public Vector3 Offset { get; } + public float Radius { get; } + + public BlittableCollider(Vector3 offset, float radius) + { + Offset = offset; + Radius = radius; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs.meta new file mode 100644 index 000000000..22ed26aa2 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableCollider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 67352bbe9afc01940af2be44aa1416fc +timeCreated: 1550209189 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs new file mode 100644 index 000000000..a53c1ab79 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs @@ -0,0 +1,20 @@ +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// VRMSpringBoneのColliderGroupをBlittableにしたもの + /// + public readonly struct BlittableColliderGroup + { + public BlittableColliders Colliders { get; } + public unsafe BlittableTransform* Transform { get; } + + public unsafe BlittableColliderGroup(NativeArray colliders, BlittableTransform* transform) + { + Colliders = new BlittableColliders((BlittableCollider*)colliders.GetUnsafePtr(), colliders.Length); + Transform = transform; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs.meta new file mode 100644 index 000000000..222c88810 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 478b0f68277d5a346a9e909e398451aa +timeCreated: 1550223602 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs new file mode 100644 index 000000000..e8eb037bc --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// BlittableColliderGroupのポインタの配列 + /// + public readonly unsafe struct BlittableColliderGroups + { + private readonly BlittableColliderGroup* _data; + public int Length { get; } + + public BlittableColliderGroup this[int i] => _data[i]; + + public void DrawGizmos() + { + for (var i = 0; i < Length; i++) + { + var group = this[i]; + var colliders = group.Colliders; + for (var j = 0; j < colliders.Count; ++j) + { + Gizmos.DrawWireSphere(group.Transform->WorldPosition, colliders[j].Radius); + } + } + } + + public BlittableColliderGroups(BlittableColliderGroup* data, int length) + { + _data = data; + Length = length; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs.meta new file mode 100644 index 000000000..d15dc6a18 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliderGroups.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d8ecae557f477ff4fa60ef840e6b6167 +timeCreated: 1550563011 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs new file mode 100644 index 000000000..adbc4d739 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs @@ -0,0 +1,19 @@ +namespace VRM.FastSpringBones.Blittables +{ + /// + /// BlittableColliderのポインタの配列 + /// + public unsafe struct BlittableColliders + { + private readonly BlittableCollider* _colliders; + public int Count { get; } + + public BlittableCollider this[int i] => _colliders[i]; + + public BlittableColliders(BlittableCollider* colliders, int count) + { + _colliders = colliders; + Count = count; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs.meta new file mode 100644 index 000000000..2bdef092c --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableColliders.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 14be485b03404da4a9a5ba19211f9c1b +timeCreated: 1550562383 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs new file mode 100644 index 000000000..f508200c8 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs @@ -0,0 +1,149 @@ +using UnityEngine; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// VRMSpringBoneLogicをBlittableにしたもの + /// ベルレ積分など、コアな計算を行う + /// + public unsafe struct BlittablePoint + { + private readonly float _length; + private readonly Quaternion _localRotation; + private readonly Vector3 _boneAxis; + private readonly float _radius; + private Vector3 _prevPosition; + + private readonly BlittableColliderGroups* _blittableColliderGroups; + private readonly BlittableTransform* _center; + + public Vector3 CurrentPosition { get; private set; } + + private readonly BlittableTransform* _transform; + + public BlittablePoint( + Transform transform, + float radius, + BlittableTransform* center, + BlittableColliderGroups* blittableColliderGroups, + BlittableTransform* blittableTransform) + { + Vector3 localPosition; + if (transform.childCount == 0) + { + var delta = transform.position - transform.parent.position; + var childPosition = transform.position + delta.normalized * 0.07f; + localPosition = transform.worldToLocalMatrix.MultiplyPoint(childPosition); + } + else + { + var firstChild = transform.GetChild(0); + var scale = firstChild.lossyScale; + localPosition = firstChild.localPosition; + localPosition.x *= scale.x; + localPosition.y *= scale.y; + localPosition.z *= scale.z; + } + + var worldChildPosition = (Vector3)transform.TransformPoint(localPosition); + _prevPosition = CurrentPosition = center != null ? center->LocalToWorld.inverse.MultiplyPoint3x4(worldChildPosition) : worldChildPosition; + + _localRotation = transform.localRotation; + _boneAxis = localPosition.normalized; + _length = localPosition.magnitude; + _radius = radius; + _blittableColliderGroups = blittableColliderGroups; + _transform = blittableTransform; + _center = center; + } + + public void Update(float stiffnessForce, float dragForce, Vector3 external) + { + // 親のRotationが変わっている可能性があるので更新する + _transform->UpdateLocalToWorldMatrix(); + + Vector3 currentPosition; + Vector3 prevPosition; + + if (_center == null) + { + currentPosition = CurrentPosition; + prevPosition = _prevPosition; + } + else + { + var centerLocalToWorld = _center->LocalToWorld; + currentPosition = centerLocalToWorld.MultiplyPoint3x4(CurrentPosition); + prevPosition = centerLocalToWorld.MultiplyPoint3x4(_prevPosition); + } + + // verlet積分で次の位置を計算 + var nextPosition = currentPosition + + (currentPosition - prevPosition) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ) + + _transform->ParentWorldRotation * _localRotation * _boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標 + + external; // 外力による移動量 + + // 長さをboneLengthに強制 + var position = _transform->WorldPosition; + nextPosition = position + (nextPosition - position).normalized * _length; + + nextPosition = Collision(nextPosition, position); + + if (_center == null) + { + _prevPosition = currentPosition; + CurrentPosition = nextPosition; + } + else + { + var centerWorldToLocal = _center->LocalToWorld.inverse; + _prevPosition = centerWorldToLocal.MultiplyPoint3x4(currentPosition); + CurrentPosition = centerWorldToLocal.MultiplyPoint3x4(nextPosition); + } + + //回転を適用 + _transform->SetWorldRotation(ApplyRotation(nextPosition)); + } + + private Vector3 Collision(Vector3 nextPosition, Vector3 position) + { + for (var i = 0; i < _blittableColliderGroups->Length; ++i) + { + var colliderGroup = (*_blittableColliderGroups)[i]; + + for (var j = 0; j < colliderGroup.Colliders.Count; ++j) + { + var collider = colliderGroup.Colliders[j]; + var colliderPosition = colliderGroup.Transform->TransformPoint(collider.Offset); + var r = _radius + collider.Radius; + + if (!((nextPosition - colliderPosition).sqrMagnitude <= (r * r))) continue; + + // ヒット。Colliderの半径方向に押し出す + var normal = (nextPosition - colliderPosition).normalized; + var posFromCollider = colliderPosition + normal * (_radius + collider.Radius); + + // 長さをboneLengthに強制 + nextPosition = position + (posFromCollider - position).normalized * _length; + } + } + return nextPosition; + } + + private static Quaternion FromToRotation(Vector3 from, Vector3 to) + => Quaternion.AxisAngle( + angle: Mathf.Acos(Mathf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1f, 1f)), + axis: Vector3.Cross(from, to).normalized + ); + + private Quaternion ApplyRotation(Vector3 nextTail) + { + var rotation = _transform->ParentWorldRotation * _localRotation; + return + FromToRotation( + rotation * _boneAxis, + nextTail - _transform->WorldPosition) * + rotation; + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs.meta new file mode 100644 index 000000000..de8b9f605 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoint.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8299788b0fbfe574397e8940e718f50f +timeCreated: 1549430605 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs new file mode 100644 index 000000000..8a91baf39 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs @@ -0,0 +1,23 @@ +namespace VRM.FastSpringBones.Blittables +{ + /// + /// BlittablePointのポインタの配列 + /// + public unsafe struct BlittablePoints + { + private readonly BlittablePoint* _points; + public int Count { get; } + + public BlittablePoint this[int i] + { + get => _points[i]; + set => _points[i] = value; + } + + public BlittablePoints(BlittablePoint* points, int count) + { + _points = points; + Count = count; + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs.meta new file mode 100644 index 000000000..322e60643 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittablePoints.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 55f68ce7085cb7640a50cb133741361b +timeCreated: 1550721598 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs new file mode 100644 index 000000000..81753210d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs @@ -0,0 +1,64 @@ +using UnityEngine; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// 1本の毛束を示すBlittable型 + /// + public unsafe readonly struct BlittableRootBone + { + private readonly float _gravityPower; + private readonly Vector3 _gravityDir; + private readonly float _dragForce; + private readonly float _stiffnessForce; + private readonly BlittablePoints* _blittablePoints; + + public void DrawGizmos() + { + for (var i = 0; i < _blittablePoints->Count; i++) + { + var point = (*_blittablePoints)[i]; + Gizmos.DrawWireSphere(point.CurrentPosition, 0.05f); + } + for (var i = 0; i < _blittablePoints->Count - 1; i++) + { + var point1 = (*_blittablePoints)[i]; + var point2 = (*_blittablePoints)[i + 1]; + Gizmos.DrawLine(point1.CurrentPosition, point2.CurrentPosition); + } + } + + public BlittableRootBone( + float gravityPower, + Vector3 gravityDir, + float dragForce, + float stiffnessForce, + BlittablePoints* blittablePoints) + { + _gravityPower = gravityPower; + _gravityDir = gravityDir; + _dragForce = dragForce; + _stiffnessForce = stiffnessForce; + _blittablePoints = blittablePoints; + } + + public void Update(float deltaTime) + { + var stiffness = _stiffnessForce * deltaTime; + var external = _gravityDir * (_gravityPower * deltaTime); + for (var i = 0; i < _blittablePoints->Count; i++) + { + var point = (*_blittablePoints)[i]; + + // Pointを更新 + point.Update( + stiffness, + _dragForce, + external + ); + + (*_blittablePoints)[i] = point; + } + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs.meta new file mode 100644 index 000000000..5be432cd9 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableRootBone.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 30738bbbf18309448a80f7944ec2aef3 +timeCreated: 1549952425 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs new file mode 100644 index 000000000..b2e4f9947 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs @@ -0,0 +1,72 @@ +using UnityEngine; +using UnityEngine.Jobs; + +namespace VRM.FastSpringBones.Blittables +{ + /// + /// Transformの必要な機能だけを絞り、Blittableに対応させたクラス + /// + public unsafe struct BlittableTransform + { + private readonly BlittableTransform* _parent; + private Quaternion _worldRotation; + private Vector3 _localPosition; + private Vector3 _localScale; + private Quaternion _localRotation; + private Matrix4x4 _localToWorld; + + public Vector3 WorldPosition { get; private set; } + + public void SetWorldRotation(Quaternion rotation) + { + var parentWorldRotation = ParentWorldRotation; + _localRotation = Quaternion.Inverse(parentWorldRotation) * rotation; + UpdateLocalToWorldMatrix(); + } + + public Matrix4x4 LocalToWorld => _localToWorld; + + private Matrix4x4 LocalTransform => Matrix4x4.TRS(_localPosition, _localRotation, _localScale); + + public Quaternion ParentWorldRotation => _parent != null ? _parent->_worldRotation : Quaternion.identity; + + public BlittableTransform(BlittableTransform* parent, Transform transform) + { + _parent = parent; + + WorldPosition = transform.position; + _worldRotation = transform.rotation; + _localPosition = transform.localPosition; + _localRotation = transform.localRotation; + _localScale = transform.localScale; + + _localToWorld = transform.localToWorldMatrix; + } + + public void PullFrom(TransformAccess transform) + { + WorldPosition = transform.position; + _worldRotation = transform.rotation; + _localPosition = transform.localPosition; + _localRotation = transform.localRotation; + _localScale = transform.localScale; + + _localToWorld = transform.localToWorldMatrix; + } + + public void PushTo(TransformAccess transform) + { + transform.localPosition = _localPosition; + transform.localRotation = _localRotation; + } + + public Vector3 TransformPoint(Vector3 offset) => _localToWorld.MultiplyPoint3x4(offset); + + public void UpdateLocalToWorldMatrix() + { + _localToWorld = _parent == null ? LocalTransform : _parent->_localToWorld * LocalTransform; + WorldPosition = _localToWorld.MultiplyPoint3x4(Vector3.zero); + _worldRotation = _localToWorld.rotation; + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs.meta new file mode 100644 index 000000000..f2b4e7fda --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Blittables/BlittableTransform.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 95fac2f4af221054f99dbe868d26fc4b +timeCreated: 1550544819 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components.meta b/Assets/VRM10/Runtime/FastSpringBone/Components.meta new file mode 100644 index 000000000..93cfd9293 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57b934d4e245cef49acc06524c3e1f7d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs new file mode 100644 index 000000000..b5fe7be3b --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.Components +{ + /// + /// VRMSpringBoneColliderGroupに対応したクラス + /// バッファの作成も行う + /// + public sealed unsafe class FastSpringBoneColliderGroup : MonoBehaviour + { + private NativeTransform _nativeTransform; + private NativeColliderGroup _nativeColliderGroup; + + public BlittableColliderGroup* ColliderGroupPtr => _nativeColliderGroup.GetUnsafePtr(); + + public void Initialize(TransformRegistry transformRegistry, BlittableCollider[] colliders) + { + _nativeTransform = new NativeTransform(transformRegistry, TransformSynchronizationType.PullOnly, transform); + _nativeColliderGroup = new NativeColliderGroup(colliders, _nativeTransform); + } + + private void OnDestroy() + { + _nativeTransform?.Dispose(); + _nativeColliderGroup?.Dispose(); + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs.meta new file mode 100644 index 000000000..2d20097b1 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneColliderGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b5fe6672f5b7b1049bb9e1bed44ee015 +timeCreated: 1550213674 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs new file mode 100644 index 000000000..fc125b062 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs @@ -0,0 +1,100 @@ +using Unity.Jobs; +using UnityEngine; +using UnityEngine.Profiling; +using VRM.FastSpringBones.Registries; +using VRM.FastSpringBones.Schedulers; + +namespace VRM.FastSpringBones.Components +{ + /// + /// Jobを連続して発火させるComponent + /// シーンに1つだけあればいい + /// + [DefaultExecutionOrder(11000)] + public sealed class FastSpringBoneScheduler : MonoBehaviour + { + [SerializeField] private bool showGizmos; + + private CustomSampler _updateSampler; + + private PullTransformJobScheduler _pullTransformJobScheduler; + private PushTransformJobScheduler _pushTransformJobScheduler; + private UpdateSpringBoneJobScheduler _updateSpringBoneJobScheduler; + + private RootBoneRegistry _rootBoneRegistry; + private ColliderGroupRegistry _colliderGroupRegistry; + + private JobHandle _prevJobHandle; + + public bool ShowGizmos { get => showGizmos; set => showGizmos = value; } + + public void Initialize( + RootBoneRegistry rootBoneRegistry, + TransformRegistry transformRegistry, + ColliderGroupRegistry colliderGroupRegistry) + { + _rootBoneRegistry = rootBoneRegistry; + _colliderGroupRegistry = colliderGroupRegistry; + + _updateSampler = CustomSampler.Create("FastSpringBone(Update)"); + + _pullTransformJobScheduler = new PullTransformJobScheduler(transformRegistry); + _pushTransformJobScheduler = new PushTransformJobScheduler(transformRegistry); + _updateSpringBoneJobScheduler = new UpdateSpringBoneJobScheduler(_rootBoneRegistry); + + _rootBoneRegistry.SubscribeOnValueChanged(OnRootBoneChanged); + } + + private void OnDestroy() + { + _rootBoneRegistry.UnSubscribeOnValueChanged(OnRootBoneChanged); + _prevJobHandle.Complete(); + + _pullTransformJobScheduler.Dispose(); + _pushTransformJobScheduler.Dispose(); + _updateSpringBoneJobScheduler.Dispose(); + } + + private void OnRootBoneChanged() + { + _prevJobHandle.Complete(); + } + +#if UNITY_EDITOR + private void OnDrawGizmos() + { + if (!ShowGizmos) return; + + _prevJobHandle.Complete(); + + Gizmos.color = Color.blue; + foreach (var rootBoneWrapper in _rootBoneRegistry.Items) + { + rootBoneWrapper.Value.DrawGizmos(); + } + + Gizmos.color = Color.yellow; + foreach (var colliderGroup in _colliderGroupRegistry.Items) + { + colliderGroup.DrawGizmos(); + } + } +#endif + + private void LateUpdate() + { + _updateSampler.Begin(); + + _prevJobHandle.Complete(); + + var tempJobHandle = default(JobHandle); + tempJobHandle = _pullTransformJobScheduler.Schedule(tempJobHandle); + tempJobHandle = _updateSpringBoneJobScheduler.Schedule(tempJobHandle); + tempJobHandle = _pushTransformJobScheduler.Schedule(tempJobHandle); + + _prevJobHandle = tempJobHandle; + + _updateSampler.End(); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs.meta new file mode 100644 index 000000000..2f156ce92 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringBoneScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3affa859639024f439b13d4cd4a9b0f6 +timeCreated: 1549521562 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs new file mode 100644 index 000000000..a6ec42ece --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.Components +{ + /// + /// SpringBoneの1本の毛束の処理を担当するクラス + /// + public sealed class FastSpringRootBone : IDisposable + { + private readonly TransformRegistry _transformRegistry; + private readonly RootBoneRegistry _rootBoneRegistry; + private readonly ColliderGroupRegistry _colliderGroupRegistry; + private readonly Transform _transform; + + private float _radius; + private NativeTransform _center; + + private IReadOnlyDictionary _transformIndexMap; + private NativeColliderGroups _nativeColliderGroups; + + private NativePoints _nativePoints; + private NativePointer _rootBoneWrapper; + + private readonly IList _transformWrappers = new List(); + private readonly IList> _points = new List>(); + + public FastSpringRootBone( + TransformRegistry transformRegistry, + Transform transform, + RootBoneRegistry rootBoneRegistry, + ColliderGroupRegistry colliderGroupRegistry + ) + { + _transformRegistry = transformRegistry; + _transform = transform; + _rootBoneRegistry = rootBoneRegistry; + _colliderGroupRegistry = colliderGroupRegistry; + } + + public IReadOnlyList ColliderGroups + { + get => _nativeColliderGroups.ColliderGroups; + set => _nativeColliderGroups.ColliderGroups = value; + } + + public unsafe void Initialize( + float gravityPower, + Vector3 gravityDir, + float dragForce, + float stiffnessForce, + IReadOnlyList colliderGroups, + float radius, + Transform center) + { + _radius = radius; + if (center != null) + { + _center = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, center); + } + + _nativeColliderGroups = new NativeColliderGroups(colliderGroups); + + NativeTransform parent = null; + if (_transform.parent) + { + parent = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, _transform.parent); + } + SetupRecursive(_transform, parent); + + _nativePoints = new NativePoints(_points); + + _rootBoneWrapper = new NativePointer(new BlittableRootBone(gravityPower, gravityDir, dragForce, stiffnessForce, _nativePoints.GetUnsafePtr())); + _rootBoneRegistry.Register(_rootBoneWrapper); + _colliderGroupRegistry.Register(_nativeColliderGroups); + } + + public void Dispose() + { + _colliderGroupRegistry.Unregister(_nativeColliderGroups); + _rootBoneRegistry.Unregister(_rootBoneWrapper); + + foreach (var transformWrapper in _transformWrappers) + { + transformWrapper.Dispose(); + } + + foreach (var point in _points) + { + point.Dispose(); + } + + _center?.Dispose(); + _nativeColliderGroups?.Dispose(); + _nativePoints.Dispose(); + _rootBoneWrapper.Dispose(); + } + + private unsafe void SetupRecursive(Transform trs, NativeTransform parent = null) + { + var transformWrapper = new NativeTransform(_transformRegistry, TransformSynchronizationType.PushOnly, trs, parent); + _transformWrappers.Add(transformWrapper); + + var point = new NativePointer( + new BlittablePoint( + trs, + _radius, + _center != null ? _center.GetUnsafePtr() : null, + _nativeColliderGroups.GetUnsafePtr(), + transformWrapper.GetUnsafePtr()) + ); + _points.Add(point); + + for (var i = 0; i < trs.childCount; ++i) + { + SetupRecursive(trs.GetChild(i), transformWrapper); + } + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs.meta new file mode 100644 index 000000000..d92fb08fa --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Components/FastSpringRootBone.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 03e3a3dad32f6e64a9fd0327d74c8305 +timeCreated: 1550036996 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef new file mode 100644 index 000000000..70ab6d305 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef @@ -0,0 +1,21 @@ +{ + "name": "FastSpringBone10", + "references": [ + "GUID:2665a8d13d1b3f18800f46e256720795" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.burst", + "expression": "0.0.1", + "define": "ENABLE_SPRINGBONE_BURST" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef.meta b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef.meta new file mode 100644 index 000000000..3abaf0aae --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBone10.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f2ca1407928ebdc4bbe7765cc278be44 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers.meta new file mode 100644 index 000000000..5b4b75b94 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b6633497ce721ce4c81d514187ef4407 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs new file mode 100644 index 000000000..821d7acc7 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs @@ -0,0 +1,31 @@ +using System; +using Unity.Collections; +using VRM.FastSpringBones.Blittables; + +namespace VRM.FastSpringBones.NativeWrappers +{ + /// + /// BlittableColliderGroupのライフサイクルを管理するWrapper + /// + public sealed unsafe class NativeColliderGroup : IDisposable + { + private readonly NativePointer _nativePointer; + + private NativeArray Colliders { get; } + + public BlittableColliderGroup* GetUnsafePtr() => _nativePointer.GetUnsafePtr(); + + public NativeColliderGroup(BlittableCollider[] colliders, NativeTransform nativeTransform) + { + Colliders = new NativeArray(colliders, Allocator.Persistent); + _nativePointer = new NativePointer(new BlittableColliderGroup(Colliders, nativeTransform.GetUnsafePtr())); + } + + public void Dispose() + { + if (Colliders.IsCreated) Colliders.Dispose(); + + _nativePointer.Dispose(); + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs.meta new file mode 100644 index 000000000..3c88d6a2d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a8d248be1ab9abe46abd06caa4758d6b +timeCreated: 1550640666 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs new file mode 100644 index 000000000..751dfd571 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.Components; + +namespace VRM.FastSpringBones.NativeWrappers +{ + /// + /// BlittableColliderGroupsのライフサイクルを管理するWrapper + /// + public sealed unsafe class NativeColliderGroups : IDisposable + { + private readonly NativePointer _nativePointer = new NativePointer(); + private NativeArray _colliderGroupArray; + private IReadOnlyList _colliderGroups; + + //Disposeされた後にUpdateColliderGroupsが呼ばれるのを防ぐためのフラグ + private bool _isDisposed; + + public BlittableColliderGroups* GetUnsafePtr() => _nativePointer.GetUnsafePtr(); + public void DrawGizmos() => _nativePointer.Value.DrawGizmos(); + + public IReadOnlyList ColliderGroups + { + get => _colliderGroups; + set + { + _colliderGroups = value; + UpdateColliderGroups(); + } + } + + private void UpdateColliderGroups() + { + if (_isDisposed) return; + if (_colliderGroupArray.IsCreated) + { + _colliderGroupArray.Dispose(); + } + CreateColliderGroupArray(_colliderGroups); + UpdateData(); + } + + public NativeColliderGroups(IReadOnlyList colliderGroups) + { + _colliderGroups = colliderGroups; + UpdateColliderGroups(); + } + + public void Dispose() + { + if (_colliderGroupArray.IsCreated) + { + _colliderGroupArray.Dispose(); + _isDisposed = true; + } + _nativePointer.Dispose(); + } + + private void CreateColliderGroupArray(IReadOnlyList colliderGroups) + { + _colliderGroupArray = new NativeArray(colliderGroups.Count, Allocator.Persistent); + for (var i = 0; i < _colliderGroupArray.Length; ++i) + { + _colliderGroupArray[i] = *colliderGroups[i].ColliderGroupPtr; + } + } + + private void UpdateData() + { + _nativePointer.Value = new BlittableColliderGroups( + (BlittableColliderGroup*)_colliderGroupArray.GetUnsafePtr(), + _colliderGroupArray.Length); + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs.meta new file mode 100644 index 000000000..65493a207 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeColliderGroups.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 73c3eb940b180fc48a3e7cdacc621543 +timeCreated: 1550645184 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs new file mode 100644 index 000000000..cc42524d7 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs @@ -0,0 +1,35 @@ +using System; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace VRM.FastSpringBones.NativeWrappers +{ + public sealed class NativePointer : IDisposable where T : unmanaged + { + private readonly unsafe T* _unsafePtr; + + public unsafe T* GetUnsafePtr() => _unsafePtr; + + public unsafe T Value + { + get => *_unsafePtr; + set => *_unsafePtr = value; + } + + public unsafe NativePointer() + { + _unsafePtr = (T*)UnsafeUtility.Malloc(sizeof(T), 16, Allocator.Persistent); + } + + public unsafe NativePointer(T value) + { + _unsafePtr = (T*)UnsafeUtility.Malloc(sizeof(T), 16, Allocator.Persistent); + Value = value; + } + + public unsafe void Dispose() + { + UnsafeUtility.Free(_unsafePtr, Allocator.Persistent); + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs.meta new file mode 100644 index 000000000..00bbc2603 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePointer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7c4d1058273489b478b053eb13702d6e +timeCreated: 1595316733 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs new file mode 100644 index 000000000..f62b0baaf --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using VRM.FastSpringBones.Blittables; + +namespace VRM.FastSpringBones.NativeWrappers +{ + /// + /// BlittablePointsGroupのライフサイクルを管理するWrapper + /// + public sealed unsafe class NativePoints : IDisposable + { + private readonly NativePointer _nativePointer; + private NativeArray _buffer; + + public BlittablePoints* GetUnsafePtr() => _nativePointer.GetUnsafePtr(); + + public NativePoints(IList> points) + { + _buffer = new NativeArray(points.Count, Allocator.Persistent); + for (var i = 0; i < _buffer.Length; ++i) + { + _buffer[i] = points[i].Value; + } + + _nativePointer = new NativePointer(new BlittablePoints((BlittablePoint*) _buffer.GetUnsafePtr(), _buffer.Length)); + } + + public void Dispose() + { + if (_buffer.IsCreated) + { + _buffer.Dispose(); + } + _nativePointer.Dispose(); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs.meta new file mode 100644 index 000000000..9be582f2d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativePoints.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 91cb239111add8342b25267432c53894 +timeCreated: 1550723674 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs new file mode 100644 index 000000000..89c592c11 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs @@ -0,0 +1,43 @@ +using System; +using UnityEngine; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.NativeWrappers +{ + /// + /// BlittableTransformのライフサイクルを管理するWrapper + /// + public sealed class NativeTransform : IDisposable + { + private readonly NativePointer _nativePointer; + public Transform Transform { get; } + + private readonly TransformRegistry _transformRegistry; + + public unsafe BlittableTransform* GetUnsafePtr() => _nativePointer.GetUnsafePtr(); + public BlittableTransform Value => _nativePointer.Value; + + public unsafe NativeTransform( + TransformRegistry transformRegistry, + TransformSynchronizationType transformSynchronizationType, + Transform transform, + NativeTransform parent = null + ) + { + _nativePointer = new NativePointer(new BlittableTransform(parent != null ? parent.GetUnsafePtr() : null, transform)); + + Transform = transform; + + _transformRegistry = transformRegistry; + _transformRegistry.Register(this, transformSynchronizationType); + } + + public void Dispose() + { + _transformRegistry.Unregister(this); + + _nativePointer.Dispose(); + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs.meta new file mode 100644 index 000000000..5b2c5ab2d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/NativeWrappers/NativeTransform.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 31fdb7a504d498242a3e459e3a63bf2d +timeCreated: 1550545201 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries.meta new file mode 100644 index 000000000..eac274d9b --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a590127469e104049996cf9b123db183 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs b/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs new file mode 100644 index 000000000..2af47cc47 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs @@ -0,0 +1,8 @@ +using VRM.FastSpringBones.NativeWrappers; + +namespace VRM.FastSpringBones.Registries +{ + public sealed class ColliderGroupRegistry : Registry + { + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs.meta new file mode 100644 index 000000000..8be0a80f7 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/ColliderGroupRegistry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9f5847b2d8bb16242aac76bda14b0202 +timeCreated: 1594963749 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs b/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs new file mode 100644 index 000000000..ce0209d49 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace VRM.FastSpringBones.Registries +{ + public class Registry + { + private readonly List _items = new List(); + private Action _onValueChanged; + + public IReadOnlyList Items => _items; + + public void Register(T value) + { + _items.Add(value); + _onValueChanged?.Invoke(); + } + + public void Unregister(T value) + { + _items.Remove(value); + _onValueChanged?.Invoke(); + } + + public void SubscribeOnValueChanged(Action action) => _onValueChanged += action; + public void UnSubscribeOnValueChanged(Action action) => _onValueChanged -= action; + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs.meta new file mode 100644 index 000000000..c16cd67d9 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/Registry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d127e4a4d5d05a46929eb3d3692d720 +timeCreated: 1595407071 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs b/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs new file mode 100644 index 000000000..8da01d254 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs @@ -0,0 +1,12 @@ +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; + +namespace VRM.FastSpringBones.Registries +{ + /// + /// 今生きているRootBoneの一覧を返すクラス + /// + public sealed class RootBoneRegistry : Registry> + { + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs.meta new file mode 100644 index 000000000..89ea5400e --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/RootBoneRegistry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 34da1f63315656e479315841b7112d7c +timeCreated: 1550734399 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs new file mode 100644 index 000000000..05c956f2b --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using VRM.FastSpringBones.NativeWrappers; + +namespace VRM.FastSpringBones.Registries +{ + /// + /// 今生きているTransformの一覧を返すクラス + /// + public sealed class TransformRegistry + { + private readonly List _transforms = new List(); + public IReadOnlyList Transforms => _transforms; + + private readonly List _pullTargets = new List(); + public IReadOnlyList PullTargets => _pullTargets; + + private readonly List _pushTargets = new List(); + public IReadOnlyList PushTargets => _pushTargets; + + private Action _onValueChanged; + + public void SubscribeOnValueChanged(Action action) => _onValueChanged += action; + + public void UnSubscribeOnValueChanged(Action action) => _onValueChanged -= action; + + public void Register(NativeTransform nativeTransform, TransformSynchronizationType synchronizationType) + { + _transforms.Add(nativeTransform); + switch (synchronizationType) + { + case TransformSynchronizationType.PullOnly: + _pullTargets.Add(nativeTransform); + break; + case TransformSynchronizationType.PushOnly: + _pushTargets.Add(nativeTransform); + break; + default: + throw new ArgumentOutOfRangeException(nameof(synchronizationType), synchronizationType, null); + } + _onValueChanged?.Invoke(); + } + + public void Unregister(NativeTransform nativeTransform) + { + _transforms.Remove(nativeTransform); + + if (_pullTargets.Contains(nativeTransform)) + { + _pullTargets.Remove(nativeTransform); + } + + if (_pushTargets.Contains(nativeTransform)) + { + _pushTargets.Remove(nativeTransform); + } + _onValueChanged?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs.meta new file mode 100644 index 000000000..d22ac48d1 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformRegistry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0603b4348a649df4fa966eeb3cd1011a +timeCreated: 1550666913 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs new file mode 100644 index 000000000..bd5a34b87 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs @@ -0,0 +1,8 @@ +namespace VRM.FastSpringBones.Registries +{ + public enum TransformSynchronizationType + { + PullOnly, + PushOnly, + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs.meta new file mode 100644 index 000000000..c3ef76238 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Registries/TransformSynchronizationType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 03978423768dd5542875359a745a0d6d +timeCreated: 1551169872 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers.meta b/Assets/VRM10/Runtime/FastSpringBone/Schedulers.meta new file mode 100644 index 000000000..2a3440920 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 160bc0dc84d022a48862d46add47a26c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs new file mode 100644 index 000000000..600ac0d39 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +#if ENABLE_SPRINGBONE_BURST +using Unity.Burst; +#endif +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using UnityEngine.Jobs; +using UnityEngine.Profiling; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.Schedulers +{ + /// + /// GameObjectの世界からBlittableな世界へTransformを複製する処理を行うクラス + /// + public sealed unsafe class PullTransformJobScheduler : IDisposable + { + private BlittableTransform** _transformPointers; + private TransformAccessArray _transformAccessArray; + + private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob"); + private readonly TransformRegistry _transformRegistry; + + private bool _dirty = true; + + private IReadOnlyList Targets => _transformRegistry.PullTargets; + + public PullTransformJobScheduler(TransformRegistry transformRegistry) + { + _transformRegistry = transformRegistry; + + _transformRegistry.SubscribeOnValueChanged(OnTransformChanged); + } + + private void OnTransformChanged() + { + _dirty = true; + } + + public JobHandle Schedule(JobHandle dependOn = default(JobHandle)) + { + if (Targets.Count == 0) + { + return dependOn; + } + + _sampler.Begin(); + + // リストが変更されていたらバッファを再構築 + if (_dirty) + { + ReconstructBuffers(); + + _dirty = false; + } + + // ジョブを発火 + var job = new Job { TransformPointers = _transformPointers }; + var jobHandle = job.Schedule(_transformAccessArray, dependOn); + + _sampler.End(); + + return jobHandle; + } + + private void ReconstructBuffers() + { + ReleaseBuffers(); + + var transforms = Targets; + _transformPointers = (BlittableTransform**)UnsafeUtility.Malloc( + sizeof(BlittableTransform*) * transforms.Count, + 16, + Allocator.Persistent + ); + + _transformAccessArray = new TransformAccessArray(transforms.Count); + + for (var i = 0; i < transforms.Count; i++) + { + _transformPointers[i] = transforms[i].GetUnsafePtr(); + _transformAccessArray.Add(transforms[i].Transform); + } + } + + public void Dispose() + { + ReleaseBuffers(); + _transformRegistry.UnSubscribeOnValueChanged(OnTransformChanged); + } + + private void ReleaseBuffers() + { + if (_transformAccessArray.isCreated) _transformAccessArray.Dispose(); + if (_transformPointers != null) + { + UnsafeUtility.Free(_transformPointers, Allocator.Persistent); + _transformPointers = null; + } + } + +#if ENABLE_SPRINGBONE_BURST + [BurstCompile] +#endif + private struct Job : IJobParallelForTransform + { + [NativeDisableUnsafePtrRestriction] public BlittableTransform** TransformPointers; + + public void Execute(int index, TransformAccess transform) + { + TransformPointers[index]->PullFrom(transform); + } + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs.meta new file mode 100644 index 000000000..6443d9e8d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PullTransformJobScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4ac8728e24e9f5240aa45867878dcc10 +timeCreated: 1550547066 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs new file mode 100644 index 000000000..6d66f61f9 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +#if ENABLE_SPRINGBONE_BURST +using Unity.Burst; +#endif +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using UnityEngine.Jobs; +using UnityEngine.Profiling; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.Schedulers +{ + /// + /// Blittableな世界からGameObjectの世界へTransformを送り込む処理を行うクラス + /// + public sealed unsafe class PushTransformJobScheduler : IDisposable + { + private BlittableTransform** _transformPointers; + private TransformAccessArray _transformAccessArray; + + private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob"); + private readonly TransformRegistry _transformRegistry; + + private bool _dirty = true; + + private IReadOnlyList Targets => _transformRegistry.PushTargets; + + public PushTransformJobScheduler(TransformRegistry transformRegistry) + { + _transformRegistry = transformRegistry; + + _transformRegistry.SubscribeOnValueChanged(OnTransformChanged); + } + + private void OnTransformChanged() + { + _dirty = true; + } + + public JobHandle Schedule(JobHandle dependOn = default(JobHandle)) + { + if (Targets.Count == 0) + { + return dependOn; + } + + _sampler.Begin(); + + // リストが変更されていたらバッファを再構築 + if (_dirty) + { + ReconstructBuffers(); + + _dirty = false; + } + + // Jobを発火 + var job = new Job { TransformPointers = _transformPointers }; + var jobHandle = job.Schedule(_transformAccessArray, dependOn); + + _sampler.End(); + + return jobHandle; + } + + private void ReconstructBuffers() + { + ReleaseBuffers(); + + var transforms = Targets; + _transformPointers = (BlittableTransform**)UnsafeUtility.Malloc( + sizeof(BlittableTransform*) * transforms.Count, + 16, + Allocator.Persistent + ); + + _transformAccessArray = new TransformAccessArray(transforms.Count); + + for (var i = 0; i < transforms.Count; i++) + { + _transformPointers[i] = transforms[i].GetUnsafePtr(); + _transformAccessArray.Add(transforms[i].Transform); + } + } + + public void Dispose() + { + ReleaseBuffers(); + _transformRegistry.UnSubscribeOnValueChanged(OnTransformChanged); + } + + private void ReleaseBuffers() + { + if (_transformAccessArray.isCreated) _transformAccessArray.Dispose(); + if (_transformPointers != null) + { + UnsafeUtility.Free(_transformPointers, Allocator.Persistent); + _transformPointers = null; + } + } + +#if ENABLE_SPRINGBONE_BURST + [BurstCompile] +#endif + private struct Job : IJobParallelForTransform + { + [NativeDisableUnsafePtrRestriction] public BlittableTransform** TransformPointers; + + public void Execute(int index, TransformAccess transform) + { + TransformPointers[index]->PushTo(transform); + } + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs.meta new file mode 100644 index 000000000..cf42b82ad --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/PushTransformJobScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 91e1bc2d3c93f1b4db3e08534237e6a0 +timeCreated: 1550717407 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs new file mode 100644 index 000000000..74297dc2d --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +#if ENABLE_SPRINGBONE_BURST +using Unity.Burst; +#endif +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using UnityEngine; +using UnityEngine.Profiling; +using VRM.FastSpringBones.Blittables; +using VRM.FastSpringBones.NativeWrappers; +using VRM.FastSpringBones.Registries; + +namespace VRM.FastSpringBones.Schedulers +{ + /// + /// SpringBoneを更新する処理を行うクラス + /// + public sealed unsafe class UpdateSpringBoneJobScheduler : IDisposable + { + private BlittableRootBone** _rootBonePointers; + + private readonly RootBoneRegistry _rootBoneRegistry; + private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob"); + + private bool _dirty = true; + + private IReadOnlyList> Targets => _rootBoneRegistry.Items; + + public UpdateSpringBoneJobScheduler(RootBoneRegistry rootBoneRegistry) + { + _rootBoneRegistry = rootBoneRegistry; + + _rootBoneRegistry.SubscribeOnValueChanged(OnRootBoneChanged); + } + + public void Dispose() + { + ReleaseBuffer(); + _rootBoneRegistry.UnSubscribeOnValueChanged(OnRootBoneChanged); + } + + private void OnRootBoneChanged() + { + _dirty = true; + } + + public JobHandle Schedule(JobHandle dependOn = default(JobHandle)) + { + if (Targets.Count == 0) + { + return dependOn; + } + + _sampler.Begin(); + + // リストが変更されていたらバッファを再構築 + if (_dirty) + { + ReconstructBuffers(); + + _dirty = false; + } + + // Jobを発火 + var job = new Job { RootBonePointers = _rootBonePointers, DeltaTime = Time.deltaTime }; + var jobHandle = job.Schedule(Targets.Count, 0, dependOn); + + _sampler.End(); + + return jobHandle; + } + + private void ReconstructBuffers() + { + ReleaseBuffer(); + + _rootBonePointers = (BlittableRootBone**)UnsafeUtility.Malloc( + sizeof(BlittableTransform*) * Targets.Count, + 16, + Allocator.Persistent + ); + + for (var i = 0; i < Targets.Count; i++) + { + _rootBonePointers[i] = Targets[i].GetUnsafePtr(); + } + } + + private void ReleaseBuffer() + { + if (_rootBonePointers == null) return; + UnsafeUtility.Free(_rootBonePointers, Allocator.Persistent); + _rootBonePointers = null; + } + +#if ENABLE_SPRINGBONE_BURST + [BurstCompile] +#endif + private struct Job : IJobParallelFor + { + [NativeDisableUnsafePtrRestriction] public BlittableRootBone** RootBonePointers; + public float DeltaTime; + + public void Execute(int index) + { + // 各点を更新する + RootBonePointers[index]->Update(DeltaTime); + } + } + } +} diff --git a/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs.meta b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs.meta new file mode 100644 index 000000000..963580382 --- /dev/null +++ b/Assets/VRM10/Runtime/FastSpringBone/Schedulers/UpdateSpringBoneJobScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 39839e9c65fc7a54abacaadf2d519fbf +timeCreated: 1549516763 \ No newline at end of file