diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit.meta new file mode 100644 index 000000000..7185a9b0e --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b09ae318bccbfce4993fafb418e1e8c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs new file mode 100644 index 000000000..178ab3d23 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs @@ -0,0 +1,91 @@ +using UniGLTF.SpringBoneJobs.Blittables; +using Unity.Mathematics; + +namespace UniGLTF.SpringBoneJobs +{ + public static class Anglelimit + { + public static float3 Apply( + in BlittableJointImmutable logic, in BlittableJointMutable joint, + in quaternion parentRotation, in float3 head, in float3 nextTail) + { + switch (joint.anglelimitType) + { + case AnglelimitTypes.None: + // do nothing + return nextTail; + + case AnglelimitTypes.Cone: + { + var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation); + var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head)); + tailDir = AnglelimitCone.Apply(tailDir, joint.anglelimit1); + return head + math.mul(angleSpaceToWorld, tailDir) * logic.length; + } + + case AnglelimitTypes.Hinge: + { + var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation); + var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head)); + tailDir = AnglelimitHinge.Apply(tailDir, joint.anglelimit1); + return head + math.mul(angleSpaceToWorld, tailDir) * logic.length; + } + + + case AnglelimitTypes.Spherical: + { + var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation); + var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalize(nextTail - head)); + tailDir = AnglelimitSpherical.Apply(tailDir, joint.anglelimit1, joint.anglelimit2); + return head + math.mul(angleSpaceToWorld, tailDir) * logic.length; + } + + default: + throw new System.ArgumentException($"unknown joint.anglelimitType: {joint.anglelimitType}"); + } + } + + /// nextTail(position vector in world space) + /// tailDir(directionay vector in angle space) + /// + public static quaternion anglelimitSpaceToWorld(in BlittableJointImmutable logic, in BlittableJointMutable joint, + in quaternion parentRotation) + { + // Y+方向からjointのheadからtailに向かうベクトルへの最小回転 + var axisRotation = fromToQuaternion(new float3(0, 1, 0), logic.boneAxis); + + // limitのローカル空間をワールド空間に写像する回転 + return + math.mul(parentRotation, + math.mul(logic.localRotation, + math.mul(axisRotation, + joint.anglelimitOffset))) + ; + } + + // https://discussions.unity.com/t/unity-mathematics-equivalent-to-quaternion-fromtorotation/237459 + public static quaternion fromToQuaternion(in float3 from, in float3 to) + { + var fromNorm = math.normalize(from); + var toNorm = math.normalize(to); + var dot = math.dot(fromNorm, toNorm); + + // Handle the case where from and to are parallel but opposite + if (math.abs(dot + 1f) < 1e-6f) // dot is approximately -1 + { + // Find a perpendicular axis + var perpAxis = math.abs(fromNorm.x) > math.abs(fromNorm.z) + ? new float3(-fromNorm.y, fromNorm.x, 0f) + : new float3(0f, -fromNorm.z, fromNorm.y); + return quaternion.AxisAngle(math.normalize(perpAxis), math.PI); + } + + // General case + return quaternion.AxisAngle( + angle: math.acos(math.clamp(dot, -1f, 1f)), + axis: math.normalize(math.cross(fromNorm, toNorm)) + ); + } + + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs.meta new file mode 100644 index 000000000..f50304933 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/Anglelimit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c2f98858052fbe4c89b445bad4c979b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs new file mode 100644 index 000000000..d8c159f86 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs @@ -0,0 +1,33 @@ +using Unity.Mathematics; + +namespace UniGLTF.SpringBoneJobs +{ + public static class AnglelimitCone + { + /// AngleLimit空間の方向ベクトル + /// radius + /// AngleLimit空間の方向ベクトル + public static float3 Apply(in float3 src, float angleLimit) + { + // tailDirのy要素をjointに設定されたangleの余弦と比較する + var cosAngle = math.cos(angleLimit); + if (src.y >= cosAngle) + { + return src; + } + + var tailDir = src; + { + // x・z要素を、tailDirの正弦とjointに設定されたangleの正弦の比を用いてスケールする + var ratio = math.sqrt((1.0f - cosAngle * cosAngle) / (1.0f - tailDir.y * tailDir.y)); + tailDir.x *= ratio; + tailDir.z *= ratio; + + // y要素を、jointに設定されたangleの余弦とする + tailDir.y = cosAngle; + } + + return tailDir; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs.meta new file mode 100644 index 000000000..ce8cc27a8 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 780b79f298faea74ba4a123039a3faeb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs new file mode 100644 index 000000000..571984689 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs @@ -0,0 +1,32 @@ +using Unity.Mathematics; + +namespace UniGLTF.SpringBoneJobs +{ + public static class AnglelimitHinge + { + /// AngleLimit空間の方向ベクトル + /// radius + /// AngleLimit空間の方向ベクトル + public static float3 Apply(in float3 src, float limitAngle) + { + // x要素を0にし、正規化する + float3 tailDir = src; + tailDir.x = 0.0f; + tailDir = math.normalize(tailDir); + + // tailDirのy要素をjointに設定されたangleの余弦と比較する + var cosAngle = math.cos(limitAngle); + if (tailDir.y < cosAngle) + { + // z要素を、tailDirの正弦とjointに設定されたangleの正弦の比を用いてスケールする + var ratio = math.sqrt((1.0f - cosAngle * cosAngle) / (1.0f - tailDir.y * tailDir.y)); + tailDir.z *= ratio; + + // y要素を、jointに設定されたangleの余弦とする + tailDir.y = cosAngle; + } + + return tailDir; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs.meta new file mode 100644 index 000000000..b385eae67 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitHinge.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb1e1bbfc1a339c40b5df4d846f09da4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs new file mode 100644 index 000000000..b15ce10fa --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs @@ -0,0 +1,37 @@ +using Unity.Mathematics; + +namespace UniGLTF.SpringBoneJobs +{ + public static class AnglelimitSpherical + { + /// AngleLimit空間の方向ベクトル + /// radius + /// radius + /// AngleLimit空間の方向ベクトル + public static float3 Apply(in float3 tailDir, float limitAnglePhi, float limitAngleTheta) + { + // tailDirのphi・thetaを計算する + var phi = math.atan2(tailDir.z, tailDir.y); + var theta = math.asin(tailDir.x); + + // phi・thetaをjointに設定されたphi・thetaを用いて制限する + // var isLimited = false; + if (math.abs(phi) > limitAnglePhi) + { + // isLimited = true; + phi = limitAnglePhi * math.sign(phi); + } + + // thetaをjointに設定されたthetaを用いて制限する + if (math.abs(theta) > limitAngleTheta) + { + // isLimited = true; + theta = limitAngleTheta * math.sign(theta); + } + + // tailDirをphi・thetaを用いて再計算する + var cos_theta = math.cos(theta); + return new float3(math.sin(theta), cos_theta * math.cos(phi), cos_theta * math.sin(phi)); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs.meta new file mode 100644 index 000000000..c0439fd3e --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc767b94391a0c44ebd21390c57a869e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs new file mode 100644 index 000000000..656ef327d --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs @@ -0,0 +1,11 @@ + +namespace UniGLTF.SpringBoneJobs +{ + public enum AnglelimitTypes + { + None, + Cone, + Hinge, + Spherical, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs.meta new file mode 100644 index 000000000..839768b66 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitTypes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56836f5a87c46a641a0ffc048c10655f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableCollider.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableCollider.cs index 9bacf616d..119b4712e 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableCollider.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableCollider.cs @@ -1,4 +1,5 @@ using System; +using Unity.Mathematics; using UnityEngine; namespace UniGLTF.SpringBoneJobs.Blittables @@ -7,15 +8,35 @@ namespace UniGLTF.SpringBoneJobs.Blittables /// Blittableなコライダ /// [Serializable] - public struct BlittableCollider + public readonly struct BlittableCollider { - public BlittableColliderType colliderType; - public Vector3 offset; - public float radius; - // capsule tail or plane normal - public Vector3 tailOrNormal; - public int transformIndex; + private readonly float3x3 _data; + public BlittableColliderType colliderType => (BlittableColliderType)(int)_data.c2.y; + public float3 offset => _data.c0; + public float radius => _data.c2.x; + // capsule tail or plane normal + public float3 tailOrNormal => _data.c1; + public int transformIndex => (int)_data.c2.z; + + public BlittableCollider( + float3 offset = default, + float radius = 0, + float3 tailOrNormal = default, + BlittableColliderType colliderType = default, + int colliderTransformIndex = 0) + { + var c0 = offset; + var c1 = tailOrNormal; + var c2 = new float3(radius,(int)colliderType, colliderTransformIndex); + _data = new float3x3(c0, c1, c2); + } + + public BlittableCollider SetTransformIndex(int index) + { + return new BlittableCollider(offset, radius, tailOrNormal, colliderType, index); + } + public void DrawGizmo(BlittableTransform t) { Gizmos.matrix = t.localToWorldMatrix; diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointImmutable.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointImmutable.cs index a4d0b9233..137bb083c 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointImmutable.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointImmutable.cs @@ -1,4 +1,5 @@ using System; +using Unity.Mathematics; using UnityEngine; namespace UniGLTF.SpringBoneJobs.Blittables @@ -9,15 +10,31 @@ namespace UniGLTF.SpringBoneJobs.Blittables /// 変わりにくいスコープ。 /// [Serializable] - public struct BlittableJointImmutable + public readonly struct BlittableJointImmutable { - public int parentTransformIndex; - public int headTransformIndex; - public int tailTransformIndex; - public float length; - public Quaternion localRotation; - public Vector3 boneAxis; + private readonly float4x3 _data; + + public int parentTransformIndex => (int)_data.c2.x; + public int headTransformIndex => (int)_data.c2.y; + public int tailTransformIndex => (int)_data.c2.z; + public float length => _data.c2.w; + public quaternion localRotation => _data.c0; + public float3 boneAxis => _data.c1.xyz; + public BlittableJointImmutable( + int parentTransformIndex = 0, + int headTransformIndex = 0, + int tailTransformIndex = 0, + float length = 0, + quaternion localRotation = default, + float3 boneAxis = default) + { + var c0 = localRotation.value; + var c1 = new float4(boneAxis, 0); + var c2 = new float4(parentTransformIndex, headTransformIndex, tailTransformIndex, length); + _data = new float4x3(c0, c1, c2); + } + public void DrawGizmo(BlittableTransform t, BlittableJointMutable m) { Gizmos.matrix = t.localToWorldMatrix; diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs index bbbd8c3ac..ccc69d2b6 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs @@ -1,5 +1,5 @@ using System; -using UnityEngine; +using Unity.Mathematics; namespace UniGLTF.SpringBoneJobs.Blittables { @@ -10,12 +10,50 @@ namespace UniGLTF.SpringBoneJobs.Blittables /// JointReconfigure を呼ばなければ以前と同じで不変となる。 /// [Serializable] - public struct BlittableJointMutable + public readonly struct BlittableJointMutable { - public float stiffnessForce; - public float gravityPower; - public Vector3 gravityDir; - public float dragForce; - public float radius; + /// + /// |x |y |z |w | + /// |--------|--------|--------|--------| + /// |stiff |g-power |drag |radius | + /// |g-dir.x |g-dir.y |g-dir.z | | + /// |al.type |limit1 |limit2 | + /// |offset.x|offset.y|offset.z|offset.w| + /// + /// g-power = gravityPower + /// g-dir = gravityDir + /// al = anglelimit + /// offset = anglelimitOffset + /// + private readonly float4x4 _data; + + public float stiffnessForce => _data.c0.x; + public float gravityPower => _data.c0.y; + public float3 gravityDir => _data.c1.xyz; + public float dragForce => _data.c0.z; + public float radius => _data.c0.w; + + public AnglelimitTypes anglelimitType => (AnglelimitTypes)_data.c2.x; + public float anglelimit1 => _data.c2.y; + public float anglelimit2 => _data.c2.z; + public quaternion anglelimitOffset => _data.c3.xyzw; + + public BlittableJointMutable(float stiffnessForce = 0, + float gravityPower = 0, + float3 gravityDir = default, + float dragForce = 0, + float radius = 0, + // v0.129.4 anglelimit + float angleLimitType = 0, + float angleLimit1 = 0, + float angleLimit2 = 0, + quaternion angleLimitOffset = default) + { + var c0 = new float4(stiffnessForce, gravityPower, dragForce, radius); + var c1 = new float4(gravityDir, 0); + var c2 = new float4(angleLimitType, angleLimit1, angleLimit2, 0); + var c3 = angleLimitOffset.value; + _data = new float4x4(c0, c1, c2, c3); + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableModelLevel.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableModelLevel.cs index 4b37dc84a..5e93b8f85 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableModelLevel.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableModelLevel.cs @@ -1,23 +1,33 @@ -using UnityEngine; +using Unity.Mathematics; namespace UniGLTF.SpringBoneJobs.Blittables { - public struct BlittableModelLevel + public readonly struct BlittableModelLevel { + private readonly float4 _data; + /// /// World 座標系の追加の力。風など。 /// - public Vector3 ExternalForce; + public float3 ExternalForce => _data.xyz; /// /// 処理結果の Transform への書き戻しを停止する。 /// - public bool StopSpringBoneWriteback; + public bool StopSpringBoneWriteback => ((int)_data.w & 1) != 0; /// /// スケール値に連動して SpringBone のパラメータを自動調整する。 /// (見た目の角速度が同じになるようにする) /// - public bool SupportsScalingAtRuntime; + public bool SupportsScalingAtRuntime => ((int)_data.w & 2) != 0; + + public BlittableModelLevel(float3 externalForce = default, + bool stopSpringBoneWriteback = false, + bool supportsScalingAtRuntime = false) + { + var w = (stopSpringBoneWriteback ? 1 : 0) | ((supportsScalingAtRuntime ? 1 : 0) << 1); + _data = new float4(externalForce, w); + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpan.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpan.cs index 425d2a6be..bf7a400ef 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpan.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpan.cs @@ -3,11 +3,20 @@ using System; namespace UniGLTF.SpringBoneJobs.Blittables { [Serializable] - public struct BlittableSpan + public readonly struct BlittableSpan { - public int startIndex; - public int count; + private readonly int _startIndex; + private readonly int _count; + + public int startIndex => _startIndex; + public int count => _count; public int EndIndex => startIndex + count; + + public BlittableSpan(int startIndex, int count) + { + _startIndex = startIndex; + _count = count; + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpring.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpring.cs index c4de2b291..72fd4163e 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpring.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableSpring.cs @@ -1,4 +1,5 @@ using System; +using Unity.Mathematics; namespace UniGLTF.SpringBoneJobs.Blittables { @@ -7,12 +8,21 @@ namespace UniGLTF.SpringBoneJobs.Blittables /// FastSpringBoneではこれを起点として並列化し、処理を行う /// [Serializable] - public struct BlittableSpring + public readonly struct BlittableSpring { - public BlittableSpan colliderSpan; - public BlittableSpan logicSpan; - public int centerTransformIndex; - public int transformIndexOffset; - public int modelIndex; + private readonly int4x2 _data; + + public BlittableSpan colliderSpan => new(_data.c0.x, _data.c0.y); + public BlittableSpan logicSpan => new(_data.c0.z, _data.c0.w); + public int centerTransformIndex => _data.c1.x; + public int transformIndexOffset => _data.c1.y; + public int modelIndex => _data.c1.z; + + public BlittableSpring(BlittableSpan colliderSpan = default, BlittableSpan logicSpan = default, int centerTransformIndex = 0, int transformIndexOffset = 0, int modelIndex = 0) + { + var c0 = new int4(colliderSpan.startIndex, colliderSpan.count, logicSpan.startIndex, logicSpan.count); + var c1 = new int4(centerTransformIndex, transformIndexOffset, modelIndex, 0); + _data = new int4x2(c0, c1); + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableTransform.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableTransform.cs index 786aa0bb2..16bb8e855 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableTransform.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableTransform.cs @@ -1,5 +1,7 @@ using System; -using UnityEngine; +using System.Runtime.CompilerServices; +using Unity.Mathematics; +using UnityEngine.Jobs; namespace UniGLTF.SpringBoneJobs.Blittables { @@ -7,14 +9,147 @@ namespace UniGLTF.SpringBoneJobs.Blittables /// Transformの必要な機能だけを絞り、Blittableに対応させたクラス /// [Serializable] - public struct BlittableTransform + public readonly struct BlittableTransform { - public Vector3 position; - public Quaternion rotation; - public Vector3 localPosition; - public Quaternion localRotation; - public Vector3 localScale; - public Matrix4x4 localToWorldMatrix; - public Matrix4x4 worldToLocalMatrix; + private readonly float4x3 _localData; + private readonly float4x4 _globalData; + + public float3 position => GetPosition(); + public quaternion rotation => GetRotation(); + public float3 lossyScale => GetLossyScale(); + public float3 localPosition => _localData.c0.xyz; + public quaternion localRotation => _localData.c1; + public float3 localScale => _localData.c2.xyz; + public float4x4 localToWorldMatrix => GetLocalToWorldMatrix(); + public float4x4 worldToLocalMatrix => math.inverse(localToWorldMatrix); + + public static BlittableTransform FromTransformAccess(TransformAccess transform) + { + return new BlittableTransform( + transform.rotation, + transform.localPosition, + transform.localRotation, + transform.localScale, + transform.localToWorldMatrix); + } + + private BlittableTransform( + quaternion rotation, + float3 localPosition, + quaternion localRotation, + float3 localScale, + float4x4 localToWorldMatrix) + { + var c10 = new float4(localPosition, 0); + var c11 = localRotation; + var c12 = new float4(localScale, 0); + _localData = new float4x3(c10, c11.value, c12); + + var c20 = new float4(localToWorldMatrix.c0.xyz, rotation.value.x); + var c21 = new float4(localToWorldMatrix.c1.xyz, rotation.value.y); + var c22 = new float4(localToWorldMatrix.c2.xyz, rotation.value.z); + var c23 = new float4(localToWorldMatrix.c3.xyz, rotation.value.w); + _globalData = new float4x4(c20, c21, c22, c23); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float4x4 GetLocalToWorldMatrix() + { + var c0 = new float4(_globalData.c0.xyz, 0); + var c1 = new float4(_globalData.c1.xyz, 0); + var c2 = new float4(_globalData.c2.xyz, 0); + var c3 = new float4(_globalData.c3.xyz, 1); + return new float4x4(c0, c1, c2, c3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float3 GetPosition() + { + return localToWorldMatrix.c3.xyz; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private quaternion GetRotation() + { + return new quaternion(_globalData.c0.w, _globalData.c1.w, _globalData.c2.w, _globalData.c3.w); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float3 GetLossyScale() + { + float4x4 tr = float4x4.TRS(position, rotation, new float3(1.0f)); + float4x4 m = math.mul(math.inverse(tr), localToWorldMatrix); + return new float3(m.c0.x, m.c1.y, m.c2.z); + } + + /// + /// 親Transformが移動や回転を行った際に、ローカル座標系の値をもとに新しい絶対座標系でのTransformを計算します。 + /// + /// + /// + public BlittableTransform UpdateParentMatrix(BlittableTransform parent) + { + quaternion newRotation = math.mul(parent.rotation, localRotation); + float4x4 newLocalToWorldMatrix = math.mul(parent.localToWorldMatrix, float4x4.TRS(localPosition, localRotation, localScale)); + + return new BlittableTransform(newRotation, localPosition, localRotation, localScale, newLocalToWorldMatrix); + } + + /// + /// グローバル座標系での位置を更新し、それに伴って連動する他の値も更新します。 + /// + /// + /// + /// + public BlittableTransform UpdatePosition(float3 newValue, BlittableTransform? parent = null) + { + quaternion newRotation; + float3 newLocalPosition; + quaternion newLocalRotation; + float4x4 newLocalToWorldMatrix; + + if(parent.HasValue) + { + newLocalPosition = math.transform(parent.Value.worldToLocalMatrix, newValue); + newLocalRotation = math.mul(math.inverse(parent.Value.rotation), rotation); + newRotation = math.mul(parent.Value.rotation, newLocalRotation); + newLocalToWorldMatrix = math.mul(parent.Value.localToWorldMatrix, float4x4.TRS(newLocalPosition, newLocalRotation, localScale)); + } + else + { + newLocalPosition = newValue; + newLocalRotation = rotation; + newRotation = rotation; + newLocalToWorldMatrix = float4x4.TRS(newValue, newRotation, localScale); + } + + return new BlittableTransform(newRotation, newLocalPosition, newLocalRotation, localScale, newLocalToWorldMatrix); + } + + /// + /// グローバル座標系での回転を更新し、それに伴って連動する他の値も更新します。 + /// + /// + /// + /// + public BlittableTransform UpdateRotation(quaternion newValue, BlittableTransform? parent = null) + { + quaternion newRotation = newValue; + quaternion newLocalRotation; + float4x4 newLocalToWorldMatrix; + + if(parent.HasValue) + { + newLocalRotation = math.normalize(math.mul(math.inverse(parent.Value.rotation), newRotation)); + newLocalToWorldMatrix = math.mul(parent.Value.localToWorldMatrix, float4x4.TRS(localPosition, newLocalRotation, localScale)); + } + else + { + newLocalRotation = newValue; + newLocalToWorldMatrix = float4x4.TRS(position, newRotation, localScale); + } + + return new BlittableTransform(newRotation, localPosition, newLocalRotation, localScale, newLocalToWorldMatrix); + } } -} \ No newline at end of file +} diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs index 8e8cc7835..35a2f9dd5 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneConbinedBuffer.cs @@ -5,10 +5,12 @@ using Unity.Burst; using System; using System.Collections.Generic; using System.Linq; +using UniGLTF.Runtime.Utils; using UniGLTF.SpringBoneJobs.Blittables; using UniGLTF.SpringBoneJobs.InputPorts; using Unity.Collections; using Unity.Jobs; +using Unity.Mathematics; using UnityEngine; using UnityEngine.Jobs; using UnityEngine.Profiling; @@ -23,9 +25,9 @@ namespace UniGLTF.SpringBoneJobs // Joint Level private NativeArray _logics; private NativeArray _joints; - private NativeArray _prevTails; - private NativeArray _currentTails; - private NativeArray _nextTails; + private NativeArray _prevTails; + private NativeArray _currentTails; + private NativeArray _nextTails; // Spring Level private NativeArray _springs; // Moodel Level @@ -39,9 +41,9 @@ namespace UniGLTF.SpringBoneJobs // accessor: Joint Level public NativeArray Logics => _logics; public NativeArray Joints => _joints; - public NativeArray PrevTails => _prevTails; - public NativeArray CurrentTails => _currentTails; - public NativeArray NextTails => _nextTails; + public NativeArray PrevTails => _prevTails; + public NativeArray CurrentTails => _currentTails; + public NativeArray NextTails => _nextTails; // accessor: Spring Level public NativeArray Springs => _springs; // accessor: Model LEvel @@ -64,9 +66,9 @@ namespace UniGLTF.SpringBoneJobs // joint level _logics = new NativeArray(logicsCount, Allocator.Persistent); _joints = new NativeArray(logicsCount, Allocator.Persistent); - _prevTails = new NativeArray(logicsCount, Allocator.Persistent); - _currentTails = new NativeArray(logicsCount, Allocator.Persistent); - _nextTails = new NativeArray(logicsCount, Allocator.Persistent); + _prevTails = new NativeArray(logicsCount, Allocator.Persistent); + _currentTails = new NativeArray(logicsCount, Allocator.Persistent); + _nextTails = new NativeArray(logicsCount, Allocator.Persistent); // spring level _springs = new NativeArray(springsCount, Allocator.Persistent); // model level @@ -248,11 +250,12 @@ namespace UniGLTF.SpringBoneJobs public void Execute(int index) { var spring = SrcSprings[index]; - spring.modelIndex = ModelIndex; - spring.colliderSpan.startIndex += CollidersOffset; - spring.logicSpan.startIndex += LogicsOffset; - spring.transformIndexOffset = TransformOffset; - DestSprings[index] = spring; + DestSprings[index] = new BlittableSpring( + modelIndex: ModelIndex, + colliderSpan: new BlittableSpan(spring.colliderSpan.startIndex + CollidersOffset, spring.colliderSpan.count), + logicSpan: new BlittableSpan(spring.logicSpan.startIndex + LogicsOffset, spring.logicSpan.count), + transformIndexOffset: TransformOffset, + centerTransformIndex: spring.centerTransformIndex); } } @@ -296,9 +299,9 @@ namespace UniGLTF.SpringBoneJobs [ReadOnly] public NativeArray Logics; [ReadOnly] public NativeArray Transforms; - [NativeDisableParallelForRestriction] public NativeSlice CurrentTails; - [NativeDisableParallelForRestriction] public NativeSlice PrevTails; - [NativeDisableParallelForRestriction] public NativeSlice NextTails; + [NativeDisableParallelForRestriction] public NativeSlice CurrentTails; + [NativeDisableParallelForRestriction] public NativeSlice PrevTails; + [NativeDisableParallelForRestriction] public NativeSlice NextTails; public void Execute(int springIndex) { @@ -323,7 +326,7 @@ namespace UniGLTF.SpringBoneJobs } var tail = Transforms[tailIndex]; - var tailPos = center.HasValue ? center.Value.worldToLocalMatrix.MultiplyPoint3x4(tail.position) : tail.position; + var tailPos = center.HasValue ? MathHelper.MultiplyPoint3x4(center.Value.worldToLocalMatrix, tail.position) : tail.position; CurrentTails[jointIndex] = tailPos; PrevTails[jointIndex] = tailPos; NextTails[jointIndex] = tailPos; diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneScheduler.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneScheduler.cs index 9a27260d9..637f8b1e5 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneScheduler.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/FastSpringBoneScheduler.cs @@ -18,9 +18,13 @@ namespace UniGLTF.SpringBoneJobs _bufferCombiner.Dispose(); } - public JobHandle Schedule(float deltaTime) + public JobHandle Schedule(float deltaTime, JobHandle? dependency = null) { var handle = _bufferCombiner.ReconstructIfDirty(default); + if(dependency.HasValue) + { + handle = JobHandle.CombineDependencies(handle, dependency.Value); + } if (!_bufferCombiner.HasBuffer) { return handle; diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs index f420ed10e..b507f60d7 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/InputPorts/FastSpringBoneBuffer.cs @@ -2,9 +2,10 @@ using System; using System.Collections.Generic; using System.Linq; using Unity.Collections; -using UnityEngine; using UnityEngine.Profiling; using UniGLTF.SpringBoneJobs.Blittables; +using Unity.Mathematics; +using UnityEngine; namespace UniGLTF.SpringBoneJobs.InputPorts { @@ -22,8 +23,8 @@ namespace UniGLTF.SpringBoneJobs.InputPorts public NativeArray Joints { get; } public NativeArray Colliders { get; } public NativeArray Logics { get; } - private NativeArray _currentTailsBackup; - private NativeArray _nextTailsBackup; + private NativeArray _currentTailsBackup; + private NativeArray _nextTailsBackup; public Transform[] Transforms { get; } /// @@ -67,27 +68,17 @@ namespace UniGLTF.SpringBoneJobs.InputPorts List blittableLogics = new(); foreach (var spring in springs) { - var blittableSpring = new BlittableSpring - { - colliderSpan = new BlittableSpan - { - startIndex = blittableColliders.Count, - count = spring.colliders.Length, - }, - logicSpan = new BlittableSpan - { - startIndex = blittableJoints.Count, - count = spring.joints.Length - 1, - }, - centerTransformIndex = Array.IndexOf(Transforms, spring.center), - }; + var blittableSpring = new BlittableSpring( + centerTransformIndex: Array.IndexOf(Transforms, spring.center), + colliderSpan: new BlittableSpan(blittableColliders.Count, spring.colliders.Length), + logicSpan: new BlittableSpan(blittableJoints.Count, spring.joints.Length - 1)); blittableSprings.Add(blittableSpring); blittableColliders.AddRange(spring.colliders.Select(collider => { var blittable = collider.Collider; - blittable.transformIndex = Array.IndexOf(Transforms, collider.Transform); - return blittable; + var transformIndex = Array.IndexOf(Transforms, collider.Transform); + return blittable.SetTransformIndex(transformIndex); })); blittableJoints.AddRange(spring.joints .Take(spring.joints.Length - 1).Select(joint => @@ -123,25 +114,23 @@ namespace UniGLTF.SpringBoneJobs.InputPorts var localPosition = tailJoint.Transform.localPosition; var scale = tailJoint.Transform.lossyScale; - var localChildPosition = new Vector3( + var localChildPosition = new float3( localPosition.x * scale.x, localPosition.y * scale.y, localPosition.z * scale.z ); - yield return new BlittableJointImmutable - { - headTransformIndex = Array.IndexOf(Transforms, joint.Transform), - parentTransformIndex = Array.IndexOf(Transforms, joint.Transform.parent), - tailTransformIndex = Array.IndexOf(Transforms, tailJoint.Transform), - localRotation = joint.DefaultLocalRotation, - boneAxis = localChildPosition.normalized, - length = localChildPosition.magnitude - }; + yield return new BlittableJointImmutable( + headTransformIndex: Array.IndexOf(Transforms, joint.Transform), + parentTransformIndex: Array.IndexOf(Transforms, joint.Transform.parent), + tailTransformIndex: Array.IndexOf(Transforms, tailJoint.Transform), + localRotation: joint.DefaultLocalRotation, + boneAxis: math.normalize(localChildPosition), + length: math.length(localChildPosition)); } } - public void BackupCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) + public void BackupCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) { if (!Logics.IsCreated || Logics.Length == 0) { @@ -155,16 +144,16 @@ namespace UniGLTF.SpringBoneJobs.InputPorts { _nextTailsBackup = new(Logics.Length, Allocator.Persistent); } - NativeArray.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length); - NativeArray.Copy(nextTails, offset, _nextTailsBackup, 0, Logics.Length); + NativeArray.Copy(currentTails, offset, _currentTailsBackup, 0, Logics.Length); + NativeArray.Copy(nextTails, offset, _nextTailsBackup, 0, Logics.Length); } - public void RestoreCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) + public void RestoreCurrentTails(NativeArray currentTails, NativeArray nextTails, int offset) { if (_currentTailsBackup.IsCreated) { - NativeArray.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length); - NativeArray.Copy(_nextTailsBackup, 0, nextTails, offset, Logics.Length); + NativeArray.Copy(_currentTailsBackup, 0, currentTails, offset, Logics.Length); + NativeArray.Copy(_nextTailsBackup, 0, nextTails, offset, Logics.Length); } else { @@ -173,7 +162,7 @@ namespace UniGLTF.SpringBoneJobs.InputPorts { // mark velocity zero #if UNITY_2022_2_OR_NEWER - currentTails.GetSubArray(offset, Logics.Length).AsSpan().Fill(new Vector3(float.NaN, float.NaN, float.NaN)); + currentTails.GetSubArray(offset, Logics.Length).AsSpan().Fill(new float3(float.NaN, float.NaN, float.NaN)); #else var subArray = currentTails.GetSubArray(offset, Logics.Length); var value = new Vector3(float.NaN, float.NaN, float.NaN); diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/PullTransformJob.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/PullTransformJob.cs index f9074868c..e07e450ca 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/PullTransformJob.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/PullTransformJob.cs @@ -17,16 +17,7 @@ namespace UniGLTF.SpringBoneJobs public void Execute(int index, TransformAccess transform) { - Transforms[index] = new BlittableTransform - { - position = transform.position, - rotation = transform.rotation, - localPosition = transform.localPosition, - localRotation = transform.localRotation, - localScale = transform.localScale, - localToWorldMatrix = transform.localToWorldMatrix, - worldToLocalMatrix = transform.worldToLocalMatrix - }; + Transforms[index] = BlittableTransform.FromTransformAccess(transform); } } } diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs new file mode 100644 index 000000000..a8f5fc3b4 --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs @@ -0,0 +1,206 @@ +using UniGLTF.Runtime.Utils; +using UniGLTF.SpringBoneJobs.Blittables; +using Unity.Mathematics; + +namespace UniGLTF.SpringBoneJobs +{ + public static class SpringBoneCollision + { + public static bool TryCollide( + in BlittableJointImmutable logic, in BlittableJointMutable joint, in BlittableTransform headTransform, + in BlittableCollider collider, in BlittableTransform colliderTransform, float maxColliderScale, + in float3 colliderWorldTail, in float3 colliderWorldPosition, + in float3 nextTail, out float3 newNextTail) + { + switch (collider.colliderType) + { + case BlittableColliderType.Sphere: + return TryResolveSphereCollision(joint, collider, colliderWorldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail); + + case BlittableColliderType.Capsule: + return TryResolveCapsuleCollision(colliderWorldTail, colliderWorldPosition, headTransform, joint, collider, maxColliderScale, logic, nextTail, out newNextTail); + + case BlittableColliderType.Plane: + return TryResolvePlaneCollision(joint, collider, colliderTransform, nextTail, out newNextTail); + + case BlittableColliderType.SphereInside: + return TryResolveSphereCollisionInside(joint, collider, colliderTransform, nextTail, out newNextTail); + + case BlittableColliderType.CapsuleInside: + return TryResolveCapsuleCollisionInside(joint, collider, colliderTransform, nextTail, out newNextTail); + + default: + throw new System.NotImplementedException(); + } + } + + private static bool TryResolveSphereCollision( + in BlittableJointMutable joint, + in BlittableCollider collider, + in float3 worldPosition, + in BlittableTransform headTransform, + in float maxColliderScale, + in BlittableJointImmutable logic, + in float3 nextTail, out float3 newNextTail) + { + var r = joint.radius + collider.radius * maxColliderScale; + if (math.lengthsq(nextTail - worldPosition) <= (r * r)) + { + // ヒット。Colliderの半径方向に押し出す + var normal = math.normalize(nextTail - worldPosition); + var posFromCollider = worldPosition + normal * r; + // 長さをboneLengthに強制 + newNextTail = headTransform.position + math.normalize(posFromCollider - headTransform.position) * logic.length; + return true; + } + else + { + newNextTail = default; + return false; + } + } + + private static bool TryResolveCapsuleCollision( + float3 worldTail, + float3 worldPosition, + BlittableTransform headTransform, + BlittableJointMutable joint, + BlittableCollider collider, + float maxColliderScale, + BlittableJointImmutable logic, + in float3 nextTail, out float3 newNextTail) + { + var direction = worldTail - worldPosition; + if (math.lengthsq(direction) == 0) + { + // head側半球の球判定 + return TryResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail); + } + var P = math.normalize(direction); + var Q = headTransform.position - worldPosition; + var dot = math.dot(P, Q); + if (dot <= 0) + { + // head側半球の球判定 + return TryResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, nextTail, out newNextTail); + } + if (dot >= math.length(direction)) + { + // tail側半球の球判定 + return TryResolveSphereCollision(joint, collider, worldTail, headTransform, maxColliderScale, logic, nextTail, out newNextTail); + } + + // head-tail上の m_transform.position との最近点 + var p = worldPosition + P * dot; + return TryResolveSphereCollision(joint, collider, p, headTransform, maxColliderScale, logic, nextTail, out newNextTail); + } + + /// + /// Collision with SpringJoint and PlaneCollider. + /// If collide update nextTail. + /// + /// joint + /// collider + /// colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset); + /// result of verlet integration + private static bool TryResolvePlaneCollision( + in BlittableJointMutable joint, + in BlittableCollider collider, + in BlittableTransform colliderTransform, + in float3 nextTail, out float3 newNextTail) + { + var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset); + var transformedNormal = math.normalize(MathHelper.MultiplyVector(colliderTransform.localToWorldMatrix, collider.tailOrNormal)); + var delta = nextTail - transformedOffset; + + // ジョイントとコライダーの距離。負の値は衝突していることを示す + var distance = math.dot(delta, transformedNormal) - joint.radius; + + if (distance < 0) + { + // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す + var direction = transformedNormal; + newNextTail = nextTail - direction * distance; + return true; + } + else + { + newNextTail = default; + return false; + } + } + + private static bool TryResolveSphereCollisionInside( + in BlittableJointMutable joint, + in BlittableCollider collider, + in BlittableTransform colliderTransform, + in float3 nextTail, out float3 newNextTail) + { + var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset); + var delta = nextTail - transformedOffset; + + // ジョイントとコライダーの距離。負の値は衝突していることを示す + var distance = collider.radius - joint.radius - math.length(delta); + + // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す + if (distance < 0) + { + var direction = -1 * math.normalize(delta); + newNextTail = nextTail - direction * distance; + return true; + } + else + { + newNextTail = default; + return false; + } + } + + private static bool TryResolveCapsuleCollisionInside( + in BlittableJointMutable joint, + in BlittableCollider collider, + in BlittableTransform colliderTransform, + in float3 nextTail, out float3 newNextTail) + { + var transformedOffset = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.offset); + var transformedTail = MathHelper.MultiplyPoint(colliderTransform.localToWorldMatrix, collider.tailOrNormal); + var offsetToTail = transformedTail - transformedOffset; + var lengthSqCapsule = math.lengthsq(offsetToTail); + + var delta = nextTail - transformedOffset; + var dot = math.dot(offsetToTail, delta); + + if (dot < 0.0) + { + // ジョイントがカプセルの始点側にある場合 + // なにもしない + } + else if (dot > lengthSqCapsule) + { + // ジョイントがカプセルの終点側にある場合 + delta -= offsetToTail; + } + else + { + // ジョイントがカプセルの始点と終点の間にある場合 + delta -= offsetToTail * (dot / lengthSqCapsule); + } + + // ジョイントとコライダーの距離。負の値は衝突していることを示す + var distance = collider.radius - joint.radius - math.length(delta); + + // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す + if (distance < 0) + { + var direction = -1 * math.normalize(delta); + newNextTail = nextTail - direction * distance; + return true; + } + else + { + newNextTail = default; + return false; + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs.meta new file mode 100644 index 000000000..e52fa675b --- /dev/null +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneCollision.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 400f2bc818ed9ed44ac8b852cbd9dcc5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneJobs.asmdef b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneJobs.asmdef index 29d33d7c1..db37c2688 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneJobs.asmdef +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/SpringBoneJobs.asmdef @@ -2,7 +2,10 @@ "name": "SpringBoneJobs", "rootNamespace": "", "references": [ - "GUID:8d76e605759c3f64a957d63ef96ada7c" + "GUID:8d76e605759c3f64a957d63ef96ada7c", + "GUID:1cd941934d098654fa21a13f28346412", + "GUID:2665a8d13d1b3f18800f46e256720795", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [], "excludePlatforms": [], @@ -11,6 +14,12 @@ "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], - "versionDefines": [], + "versionDefines": [ + { + "name": "com.unity.burst", + "expression": "0.01", + "define": "ENABLE_SPRINGBONE_BURST" + } + ], "noEngineReferences": false } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/UpdateFastSpringBoneJob.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/UpdateFastSpringBoneJob.cs index fc1a8983a..2cec59241 100644 --- a/Assets/UniGLTF/Runtime/SpringBoneJobs/UpdateFastSpringBoneJob.cs +++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/UpdateFastSpringBoneJob.cs @@ -1,8 +1,9 @@ using System; +using UniGLTF.Runtime.Utils; using Unity.Collections; using Unity.Jobs; -using UnityEngine; using UniGLTF.SpringBoneJobs.Blittables; +using Unity.Mathematics; #if ENABLE_SPRINGBONE_BURST using Unity.Burst; #endif @@ -26,10 +27,10 @@ namespace UniGLTF.SpringBoneJobs // Joints, Logics, PrevTail, CurrentTail, NextTail は同じ index [ReadOnly] public NativeArray Joints; [ReadOnly] public NativeArray Logics; - [ReadOnly] public NativeArray PrevTail; - [ReadOnly] public NativeArray CurrentTail; + [ReadOnly] public NativeArray PrevTail; + [ReadOnly] public NativeArray CurrentTail; // 処理後の tail 位置(ランダムアクセス) - [NativeDisableParallelForRestriction] public NativeArray NextTail; + [NativeDisableParallelForRestriction] public NativeArray NextTail; // Spring Level [ReadOnly] public NativeArray Springs; // Model Level @@ -67,105 +68,65 @@ namespace UniGLTF.SpringBoneJobs // 親があったら、親に依存するTransformを再計算 if (parentTransform.HasValue) { - headTransform.position = - parentTransform.Value.localToWorldMatrix.MultiplyPoint3x4(headTransform.localPosition); - headTransform.rotation = parentTransform.Value.rotation * headTransform.localRotation; + headTransform = headTransform.UpdateParentMatrix(parentTransform.Value); } var currentTail = centerTransform.HasValue - ? centerTransform.Value.localToWorldMatrix.MultiplyPoint3x4(CurrentTail[logicIndex]) + ? MathHelper.MultiplyPoint3x4(centerTransform.Value.localToWorldMatrix, CurrentTail[logicIndex]) : CurrentTail[logicIndex]; var prevTail = centerTransform.HasValue - ? centerTransform.Value.localToWorldMatrix.MultiplyPoint3x4(PrevTail[logicIndex]) + ? MathHelper.MultiplyPoint3x4(centerTransform.Value.localToWorldMatrix, PrevTail[logicIndex]) : PrevTail[logicIndex]; - var parentRotation = parentTransform?.rotation ?? Quaternion.identity; + var parentRotation = parentTransform?.rotation ?? quaternion.identity; // scaling 対応 - var scalingFactor = model.SupportsScalingAtRuntime ? TransformExtensions.AbsoluteMaxValue(headTransform.localToWorldMatrix.lossyScale) : 1.0f; + var scalingFactor = model.SupportsScalingAtRuntime ? math.cmax(math.abs(headTransform.lossyScale)) : 1.0f; // verlet積分で次の位置を計算 var external = (joint.gravityDir * joint.gravityPower + model.ExternalForce) * DeltaTime; var nextTail = currentTail + (currentTail - prevTail) * (1.0f - joint.dragForce) // 前フレームの移動を継続する(減衰もあるよ) - + parentRotation * logic.localRotation * logic.boneAxis * + + math.mul(math.mul(parentRotation, logic.localRotation), logic.boneAxis) * joint.stiffnessForce * DeltaTime * scalingFactor // 親の回転による子ボーンの移動目標 + external * scalingFactor; // 外力による移動量 // 長さをboneLengthに強制 - nextTail = headTransform.position + (nextTail - headTransform.position).normalized * logic.length; + nextTail = headTransform.position + math.normalize(nextTail - headTransform.position) * logic.length; + + nextTail = Anglelimit.Apply(logic, joint, parentRotation, head: headTransform.position, nextTail: nextTail); // Collisionで移動 for (var colliderIndex = colliderSpan.startIndex; colliderIndex < colliderSpan.startIndex + colliderSpan.count; ++colliderIndex) { var collider = Colliders[colliderIndex]; var colliderTransform = Transforms[collider.transformIndex + transformIndexOffset]; - var colliderScale = colliderTransform.localToWorldMatrix.lossyScale; - var maxColliderScale = Mathf.Max(Mathf.Max(Mathf.Abs(colliderScale.x), Mathf.Abs(colliderScale.y)), Mathf.Abs(colliderScale.z)); - var worldPosition = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset); - var worldTail = colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.tailOrNormal); + var colliderScale = colliderTransform.lossyScale; + var maxColliderScale = math.max(math.max(math.abs(colliderScale.x), math.abs(colliderScale.y)), math.abs(colliderScale.z)); + var worldPosition = MathHelper.MultiplyPoint3x4(colliderTransform.localToWorldMatrix, collider.offset); + var worldTail = MathHelper.MultiplyPoint3x4(colliderTransform.localToWorldMatrix, collider.tailOrNormal); - switch (collider.colliderType) + if (SpringBoneCollision.TryCollide(logic, joint, + headTransform, + collider, colliderTransform, maxColliderScale, + colliderWorldTail: worldTail, colliderWorldPosition: worldPosition, + nextTail: nextTail, + out var newNextTail)) { - case BlittableColliderType.Sphere: - ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); - break; - - case BlittableColliderType.Capsule: - ResolveCapsuleCollision(worldTail, worldPosition, headTransform, joint, collider, maxColliderScale, logic, ref nextTail); - break; - - case BlittableColliderType.Plane: - ResolvePlaneCollision(joint, collider, colliderTransform, ref nextTail); - break; - - case BlittableColliderType.SphereInside: - ResolveSphereCollisionInside(joint, collider, colliderTransform, ref nextTail); - break; - - case BlittableColliderType.CapsuleInside: - ResolveCapsuleCollisionInside(joint, collider, colliderTransform, ref nextTail); - break; - - default: - throw new NotImplementedException(); + // 衝突毎に nextTail を更新する。 + nextTail = Anglelimit.Apply(logic, joint, parentRotation, head: headTransform.position, nextTail: newNextTail); } } NextTail[logicIndex] = centerTransform.HasValue - ? centerTransform.Value.worldToLocalMatrix.MultiplyPoint3x4(nextTail) + ? MathHelper.MultiplyPoint3x4(centerTransform.Value.worldToLocalMatrix, nextTail) : nextTail; //回転を適用 - var rotation = parentRotation * logic.localRotation; - headTransform.rotation = Quaternion.FromToRotation(rotation * logic.boneAxis, - nextTail - headTransform.position) * rotation; - - // Transformを更新 - if (parentTransform.HasValue) - { - var parentLocalToWorldMatrix = parentTransform.Value.localToWorldMatrix; - headTransform.localRotation = Normalize(Quaternion.Inverse(parentTransform.Value.rotation) * headTransform.rotation); - headTransform.localToWorldMatrix = - parentLocalToWorldMatrix * - Matrix4x4.TRS( - headTransform.localPosition, - headTransform.localRotation, - headTransform.localScale - ); - headTransform.worldToLocalMatrix = headTransform.localToWorldMatrix.inverse; - } - else - { - headTransform.localToWorldMatrix = - Matrix4x4.TRS( - headTransform.position, - headTransform.rotation, - headTransform.localScale - ); - headTransform.worldToLocalMatrix = headTransform.localToWorldMatrix.inverse; - headTransform.localRotation = headTransform.rotation; - } + var rotation = math.mul(parentRotation, logic.localRotation); + headTransform = headTransform.UpdateRotation( + math.mul(MathHelper.FromToRotation(math.mul(rotation, logic.boneAxis), nextTail - headTransform.position), rotation), + parentTransform); if (!model.StopSpringBoneWriteback) { @@ -180,161 +141,5 @@ namespace UniGLTF.SpringBoneJobs } } - /// - /// BurstではMathfがエラーを吐くため、内部でMathfを呼ばないNormalizeを自前実装 - /// - private static Quaternion Normalize(Quaternion q) - { - var num = (float)Math.Sqrt(Quaternion.Dot(q, q)); - return num < float.Epsilon ? Quaternion.identity : new Quaternion(q.x / num, q.y / num, q.z / num, q.w / num); - } - - private static void ResolveCapsuleCollision( - Vector3 worldTail, - Vector3 worldPosition, - BlittableTransform headTransform, - BlittableJointMutable joint, - BlittableCollider collider, - float maxColliderScale, - BlittableJointImmutable logic, - ref Vector3 nextTail) - { - var direction = worldTail - worldPosition; - if (direction.sqrMagnitude == 0) - { - // head側半球の球判定 - ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); - return; - } - var P = direction.normalized; - var Q = headTransform.position - worldPosition; - var dot = Vector3.Dot(P, Q); - if (dot <= 0) - { - // head側半球の球判定 - ResolveSphereCollision(joint, collider, worldPosition, headTransform, maxColliderScale, logic, ref nextTail); - return; - } - if (dot >= direction.magnitude) - { - // tail側半球の球判定 - ResolveSphereCollision(joint, collider, worldTail, headTransform, maxColliderScale, logic, ref nextTail); - return; - } - - // head-tail上の m_transform.position との最近点 - var p = worldPosition + P * dot; - ResolveSphereCollision(joint, collider, p, headTransform, maxColliderScale, logic, ref nextTail); - } - - private static void ResolveSphereCollision( - BlittableJointMutable joint, - BlittableCollider collider, - Vector3 worldPosition, - BlittableTransform headTransform, - float maxColliderScale, - BlittableJointImmutable logic, - ref Vector3 nextTail) - { - var r = joint.radius + collider.radius * maxColliderScale; - if (Vector3.SqrMagnitude(nextTail - worldPosition) <= (r * r)) - { - // ヒット。Colliderの半径方向に押し出す - var normal = (nextTail - worldPosition).normalized; - var posFromCollider = worldPosition + normal * r; - // 長さをboneLengthに強制 - nextTail = headTransform.position + (posFromCollider - headTransform.position).normalized * logic.length; - } - } - - private static void ResolveSphereCollisionInside( - BlittableJointMutable joint, - BlittableCollider collider, - BlittableTransform colliderTransform, - ref Vector3 nextTail) - { - var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset); - var delta = nextTail - transformedOffset; - - // ジョイントとコライダーの距離。負の値は衝突していることを示す - var distance = collider.radius - joint.radius - delta.magnitude; - - // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す - if (distance < 0) - { - var direction = -delta.normalized; - nextTail -= direction * distance; - } - } - - private static void ResolveCapsuleCollisionInside( - BlittableJointMutable joint, - BlittableCollider collider, - BlittableTransform colliderTransform, - ref Vector3 nextTail) - { - var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset); - var transformedTail = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.tailOrNormal); - var offsetToTail = transformedTail - transformedOffset; - var lengthSqCapsule = offsetToTail.sqrMagnitude; - - var delta = nextTail - transformedOffset; - var dot = Vector3.Dot(offsetToTail, delta); - - if (dot < 0.0) - { - // ジョイントがカプセルの始点側にある場合 - // なにもしない - } - else if (dot > lengthSqCapsule) - { - // ジョイントがカプセルの終点側にある場合 - delta -= offsetToTail; - } - else - { - // ジョイントがカプセルの始点と終点の間にある場合 - delta -= offsetToTail * (dot / lengthSqCapsule); - } - - // ジョイントとコライダーの距離。負の値は衝突していることを示す - var distance = collider.radius - joint.radius - delta.magnitude; - - // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す - if (distance < 0) - { - var direction = -delta.normalized; - nextTail -= direction * distance; - } - } - - /// - /// Collision with SpringJoint and PlaneCollider. - /// If collide update nextTail. - /// - /// joint - /// collier - /// colliderTransform.localToWorldMatrix.MultiplyPoint3x4(collider.offset); - /// result of verlet integration - private static void ResolvePlaneCollision( - BlittableJointMutable joint, - BlittableCollider collider, - BlittableTransform colliderTransform, - ref Vector3 nextTail) - { - var transformedOffset = colliderTransform.localToWorldMatrix.MultiplyPoint(collider.offset); - var transformedNormal = colliderTransform.localToWorldMatrix.MultiplyVector(collider.tailOrNormal).normalized; - var delta = nextTail - transformedOffset; - - // ジョイントとコライダーの距離。負の値は衝突していることを示す - var distance = Vector3.Dot(delta, transformedNormal) - joint.radius; - - if (distance < 0) - { - // ジョイントとコライダーの距離の方向。衝突している場合、この方向にジョイントを押し出す - var direction = transformedNormal; - nextTail -= direction * distance; - } - } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/Utils/MathHelper.cs b/Assets/UniGLTF/Runtime/Utils/MathHelper.cs new file mode 100644 index 000000000..86cb3646b --- /dev/null +++ b/Assets/UniGLTF/Runtime/Utils/MathHelper.cs @@ -0,0 +1,89 @@ +using System.Runtime.CompilerServices; +using Unity.Mathematics; + +namespace UniGLTF.Runtime.Utils +{ + public static class MathHelper + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 MultiplyPoint3x4(float4x4 matrix, float3 point) + { + return math.mul(matrix, new float4(point, 1)).xyz; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 MultiplyPoint(float4x4 matrix, float3 point) + { + var v = math.mul(matrix, new float4(point, 1.0f)); + return v.xyz / v.w; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float3 MultiplyVector(float4x4 matrix, float3 vector) + { + return math.mul(matrix, new float4(vector, 0)).xyz; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static quaternion FromToRotation(in float3 fromVector, in float3 toVector) + { + if (math.lengthsq(fromVector) == 0 || math.lengthsq(toVector) == 0) + { + return quaternion.identity; + } + + float3 from = math.normalize(fromVector); + float3 to = math.normalize(toVector); + + var dot = math.dot(from, to); + switch(dot) + { + case >= 1.0f: + return quaternion.identity; + case <= -1.0f: + { + var axis = math.cross(from, new float3(1, 0, 0)); + if (math.lengthsq(axis) < 0.0001f) + { + axis = math.cross(from, new float3(0, 1, 0)); + } + return quaternion.AxisAngle(math.normalize(axis), math.PI); + } + default: + { + var angle = math.acos(dot); + var axis = math.cross(from, to); + return quaternion.AxisAngle(math.normalize(axis), angle); + } + } + } + + /// + /// を Unity.Mathematics パッケージ向けに再実装した関数 + /// + /// + /// + /// + public static bool Approximately(float a, float b) + { + return math.abs(b - a) < math.max(1E-06f * math.max(math.abs(a), math.abs(b)), math.EPSILON * 8f); + } + + /// + public static bool Approximately(float3 a, float3 b) + { + return Approximately(a.x, b.x) && + Approximately(a.y, b.y) && + Approximately(a.z, b.z); + } + + /// + public static bool Approximately(quaternion a, quaternion b) + { + return Approximately(a.value.x, b.value.x) && + Approximately(a.value.y, b.value.y) && + Approximately(a.value.z, b.value.z) && + Approximately(a.value.w, b.value.w); + } + } +} diff --git a/Assets/UniGLTF/Runtime/Utils/MathHelper.cs.meta b/Assets/UniGLTF/Runtime/Utils/MathHelper.cs.meta new file mode 100644 index 000000000..4fa53e41b --- /dev/null +++ b/Assets/UniGLTF/Runtime/Utils/MathHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 50ff9ccb88bd4c208ab432127ec7b04d +timeCreated: 1751330089 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/Utils/UniGLTF.Utils.asmdef b/Assets/UniGLTF/Runtime/Utils/UniGLTF.Utils.asmdef index 57d5bdce8..682841075 100644 --- a/Assets/UniGLTF/Runtime/Utils/UniGLTF.Utils.asmdef +++ b/Assets/UniGLTF/Runtime/Utils/UniGLTF.Utils.asmdef @@ -1,7 +1,9 @@ { "name": "UniGLTF.Utils", "rootNamespace": "", - "references": [], + "references": [ + "GUID:d8b63aba1907145bea998dd612889d6b" + ], "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, diff --git a/Assets/UniGLTF/Tests/UniGLTF.Tests.asmdef b/Assets/UniGLTF/Tests/UniGLTF.Tests.asmdef index f3e06d294..d5dfef6ec 100644 --- a/Assets/UniGLTF/Tests/UniGLTF.Tests.asmdef +++ b/Assets/UniGLTF/Tests/UniGLTF.Tests.asmdef @@ -6,7 +6,8 @@ "GUID:5f875fdc81c40184c8333b9d63c6ddd5", "GUID:27619889b8ba8c24980f49ee34dbb44a", "GUID:0acc523941302664db1f4e527237feb3", - "GUID:1cd941934d098654fa21a13f28346412" + "GUID:1cd941934d098654fa21a13f28346412", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [ "Editor" diff --git a/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs b/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs new file mode 100644 index 000000000..5c1395b64 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs @@ -0,0 +1,49 @@ +using NUnit.Framework; +using UniGLTF.Runtime.Utils; +using Unity.Mathematics; +using UnityEngine; +namespace UniGLTF +{ + public class MathTests + { + private readonly float4x4 _matrix = new float4x4( + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + private readonly float3 _vector1 = new float3(1, 2, 3); + private readonly float3 _vector2 = new float3(4, 5, 6); + + [Test] + public void MultiplyPoint3x4Test() + { + var result = MathHelper.MultiplyPoint3x4(_matrix, _vector1); + var expected = ((Matrix4x4)_matrix).MultiplyPoint3x4(_vector1); + Assert.That(MathHelper.Approximately(result, expected), Is.True); + } + + [Test] + public void MultiplyPointTest() + { + var result = MathHelper.MultiplyPoint(_matrix, _vector1); + var expected = ((Matrix4x4)_matrix).MultiplyPoint(_vector1); + Assert.That(MathHelper.Approximately(result, expected), Is.True); + } + + [Test] + public void MultiplyVectorTest() + { + var result = MathHelper.MultiplyVector(_matrix, _vector1); + var expected = ((Matrix4x4)_matrix).MultiplyVector(_vector1); + Assert.That(MathHelper.Approximately(result, expected), Is.True); + } + + [Test] + public void FromToRotationTest() + { + var result = MathHelper.FromToRotation(_vector1, _vector2); + var expected = Quaternion.FromToRotation(_vector1, _vector2); + Assert.That(MathHelper.Approximately(result, expected), Is.True); + } + } +} diff --git a/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs.meta new file mode 100644 index 000000000..33e86dc0f --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/MathTests.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4b920c4a4ea1401085ba8923e4ccaca2 +timeCreated: 1751329860 \ No newline at end of file diff --git a/Assets/VRM/Runtime/SpringBone/Jobs/FastSpringBoneReplacer.cs b/Assets/VRM/Runtime/SpringBone/Jobs/FastSpringBoneReplacer.cs index 58d6192b6..18b06b90f 100644 --- a/Assets/VRM/Runtime/SpringBone/Jobs/FastSpringBoneReplacer.cs +++ b/Assets/VRM/Runtime/SpringBone/Jobs/FastSpringBoneReplacer.cs @@ -40,13 +40,10 @@ namespace VRM.SpringBoneJobs var c = new FastSpringBoneCollider { Transform = group.transform, - Collider = new BlittableCollider - { - offset = collider.Offset, - radius = collider.Radius, - tailOrNormal = default, - colliderType = BlittableColliderType.Sphere - } + Collider = new BlittableCollider( + offset: collider.Offset, + radius: collider.Radius, + colliderType: BlittableColliderType.Sphere) }; colliders.Add(c); } @@ -85,14 +82,12 @@ namespace VRM.SpringBoneJobs joints.Add(new FastSpringBoneJoint { Transform = joint, - Joint = new BlittableJointMutable - { - radius = spring.m_hitRadius, - dragForce = spring.m_dragForce, - gravityDir = spring.m_gravityDir, - gravityPower = spring.m_gravityPower, - stiffnessForce = spring.m_stiffnessForce - }, + Joint = new BlittableJointMutable( + radius: spring.m_hitRadius, + dragForce: spring.m_dragForce, + gravityDir: spring.m_gravityDir, + gravityPower: spring.m_gravityPower, + stiffnessForce: spring.m_stiffnessForce), DefaultLocalRotation = initMap[joint.transform].LocalRotation, }); foreach (Transform child in joint) diff --git a/Assets/VRM/Runtime/VRM.asmdef b/Assets/VRM/Runtime/VRM.asmdef index d7d1718ab..0ced96160 100644 --- a/Assets/VRM/Runtime/VRM.asmdef +++ b/Assets/VRM/Runtime/VRM.asmdef @@ -7,7 +7,8 @@ "GUID:a9bc101fb0471f94a8f99fd242fdd934", "GUID:1cd941934d098654fa21a13f28346412", "GUID:60c8346e00a8ddd4cafc5a02eceeec57", - "GUID:3e5d614bc16b50d41bd94c8d7444ca46" + "GUID:3e5d614bc16b50d41bd94c8d7444ca46", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs index 2bb0fbd61..b5f1e6dc3 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneJointEditor.cs @@ -8,11 +8,17 @@ namespace UniVRM10 class VRM10SpringBoneJointEditor : Editor { private VRM10SpringBoneJoint m_target; + + private SerializedProperty m_script; private SerializedProperty m_stiffnessForceProp; private SerializedProperty m_gravityPowerProp; private SerializedProperty m_gravityDirProp; private SerializedProperty m_dragForceProp; private SerializedProperty m_jointRadiusProp; + private SerializedProperty m_angleLimitType; + private SerializedProperty m_angleLimitRotation; + private SerializedProperty m_angleLimitAngle1; + private SerializedProperty m_angleLimitAngle2; private Vrm10Instance m_root; @@ -24,11 +30,16 @@ namespace UniVRM10 } m_target = (VRM10SpringBoneJoint)target; + m_script = serializedObject.FindProperty("m_Script"); m_stiffnessForceProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_stiffnessForce)); m_gravityPowerProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_gravityPower)); m_gravityDirProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_gravityDir)); m_dragForceProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_dragForce)); m_jointRadiusProp = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_jointRadius)); + m_angleLimitType = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_anglelimitType)); + m_angleLimitRotation = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitRotation)); + m_angleLimitAngle1 = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitAngle1)); + m_angleLimitAngle2 = serializedObject.FindProperty(nameof(VRM10SpringBoneJoint.m_angleLimitAngle2)); m_root = m_target.GetComponentInParent(); } @@ -36,9 +47,15 @@ namespace UniVRM10 static bool m_showJoints; static bool m_showColliders; static bool m_showJointSettings; + static bool m_showAnglelimitSettings; public override void OnInspectorGUI() { + using (new EditorGUI.DisabledScope(true)) + { + EditorGUILayout.PropertyField(m_script); + } + serializedObject.Update(); /// @@ -67,6 +84,36 @@ namespace UniVRM10 Vrm10EditorUtility.LimitBreakSlider(m_jointRadiusProp, 0.0f, 0.5f, 0.0f, Mathf.Infinity); } + // + // angle limit + // + m_showAnglelimitSettings = EditorGUILayout.Foldout(m_showAnglelimitSettings, "AngleLimit Settings(dev)"); + if (m_showAnglelimitSettings) + { + EditorGUILayout.PropertyField(m_angleLimitType); + switch ((UniGLTF.SpringBoneJobs.AnglelimitTypes)m_angleLimitType.enumValueIndex) + { + case UniGLTF.SpringBoneJobs.AnglelimitTypes.None: + break; + + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone: + EditorGUILayout.PropertyField(m_angleLimitRotation); + EditorGUILayout.PropertyField(m_angleLimitAngle1); + break; + + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge: + EditorGUILayout.PropertyField(m_angleLimitRotation); + EditorGUILayout.PropertyField(m_angleLimitAngle1); + break; + + case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical: + EditorGUILayout.PropertyField(m_angleLimitRotation); + EditorGUILayout.PropertyField(m_angleLimitAngle1); + EditorGUILayout.PropertyField(m_angleLimitAngle2); + break; + } + } + if (serializedObject.ApplyModifiedProperties()) { if (Application.isPlaying) diff --git a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs index e178df0c5..dd54cb70d 100644 --- a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs @@ -71,11 +71,6 @@ namespace UniVRM10 m_materialValueBindingMerger.AccumulateValue(clip, value); } - public void RestoreMaterialInitialValues() - { - m_materialValueBindingMerger.RestoreMaterialInitialValues(); - } - public void Dispose() { m_materialValueBindingMerger.Dispose(); diff --git a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs index 665b2b611..a78a088cd 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs @@ -138,17 +138,6 @@ namespace UniVRM10 } } } - - /// - /// m_materialMap に記録した値に Material を復旧する - /// - public void RestoreMaterialInitialValues() - { - foreach (var kv in m_materialMap) - { - kv.Value.Clear(); - } - } #endregion #region Accumulate diff --git a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs index 33a3c75d6..d1e41e39d 100644 --- a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs +++ b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs @@ -26,14 +26,38 @@ namespace UniVRM10 [SerializeField] public float m_jointRadius = 0.02f; - public BlittableJointMutable Blittable => new BlittableJointMutable + [SerializeField] + public UniGLTF.SpringBoneJobs.AnglelimitTypes m_anglelimitType; + + [SerializeField] + public Quaternion m_angleLimitRotation = Quaternion.identity; + + [SerializeField, Range(0, Mathf.PI)] + public float m_angleLimitAngle1 = Mathf.PI; + + [SerializeField, Range(0, Mathf.PI)] + public float m_angleLimitAngle2 = Mathf.PI; + + public BlittableJointMutable Blittable => new BlittableJointMutable( + stiffnessForce: m_stiffnessForce, + gravityPower: m_gravityPower, + gravityDir: m_gravityDir, + dragForce: m_dragForce, + radius: m_jointRadius, + // v0.129.4 + angleLimitType: (float)m_anglelimitType, + angleLimit1: m_angleLimitAngle1, + angleLimit2: m_angleLimitAngle2, + angleLimitOffset: m_angleLimitRotation + ); + + void OnValidate() { - stiffnessForce = m_stiffnessForce, - dragForce = m_dragForce, - gravityDir = m_gravityDir, - gravityPower = m_gravityPower, - radius = m_jointRadius, - }; + if (m_angleLimitRotation == default) + { + m_angleLimitRotation = Quaternion.identity; + } + } void AddJointRecursive(Transform t, VRM10SpringBoneJoint src) { diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone.meta new file mode 100644 index 000000000..5100c627f --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d243bd3237701034a82757f58a0ec3da +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/FastSpringBoneBufferFactory.cs similarity index 81% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/FastSpringBoneBufferFactory.cs index f176a5e19..e0430d6da 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/FastSpringBoneBufferFactory.cs @@ -49,26 +49,17 @@ namespace UniVRM10 .Select(collider => new FastSpringBoneCollider { Transform = collider.transform, - Collider = new BlittableCollider - { - offset = collider.Offset, - radius = collider.Radius, - tailOrNormal = collider.TailOrNormal, - colliderType = TranslateColliderType(collider.ColliderType) - } + Collider = new BlittableCollider( + offset: collider.Offset, + radius: collider.Radius, + tailOrNormal: collider.TailOrNormal, + colliderType: TranslateColliderType(collider.ColliderType)) }).ToArray(), joints = spring.Joints .Select(joint => new FastSpringBoneJoint { Transform = joint.transform, - Joint = new BlittableJointMutable - { - radius = joint.m_jointRadius, - dragForce = joint.m_dragForce, - gravityDir = joint.m_gravityDir, - gravityPower = joint.m_gravityPower, - stiffnessForce = joint.m_stiffnessForce - }, + Joint = joint.Blittable, DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation, }).ToArray(), }).ToArray(); diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/FastSpringBoneBufferFactory.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/FastSpringBoneBufferFactory.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/FastSpringBoneBufferFactory.cs.meta diff --git a/Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntime.cs similarity index 97% rename from Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntime.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntime.cs index 4a962499e..b45f1ae7e 100644 --- a/Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntime.cs @@ -43,7 +43,7 @@ namespace UniVRM10 /// /// 毎フレーム Vrm10Runtime.Process から呼ばれる。 /// - public void Process(); + public void Process(float deltaTime); /// /// from Vrm10Instance.OnDrawGizmosSelected diff --git a/Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntime.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntime.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntime.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntime.cs.meta diff --git a/Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntimeProvider.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntimeProvider.cs similarity index 100% rename from Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntimeProvider.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntimeProvider.cs diff --git a/Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntimeProvider.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntimeProvider.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/IO/IVrm10SpringBoneRuntimeProvider.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/IVrm10SpringBoneRuntimeProvider.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntime.cs similarity index 99% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntime.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntime.cs index 6dc1761e0..51a14b221 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntime.cs @@ -112,7 +112,7 @@ namespace UniVRM10 m_fastSpringBoneService.BufferCombiner.InitializeJointsLocalRotation(m_fastSpringBoneBuffer); } - public void Process() + public void Process(float deltaTime) { // FastSpringBoneService が実行するので何もしない } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntime.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntime.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntime.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntime.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeProvider.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeProvider.cs similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeProvider.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeProvider.cs diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeProvider.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeProvider.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeProvider.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeProvider.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandalone.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandalone.cs similarity index 97% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandalone.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandalone.cs index 12e151e07..c2fa75295 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandalone.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandalone.cs @@ -118,9 +118,9 @@ namespace UniVRM10 m_bufferCombiner.InitializeJointsLocalRotation(m_fastSpringBoneBuffer); } - public void Process() + public void Process(float deltaTime) { - m_fastSpringBoneScheduler.Schedule(Time.deltaTime).Complete(); + m_fastSpringBoneScheduler.Schedule(deltaTime).Complete(); } public void DrawGizmos() diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandalone.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandalone.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandalone.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandalone.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandaloneProvider.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandaloneProvider.cs similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandaloneProvider.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandaloneProvider.cs diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandaloneProvider.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandaloneProvider.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10FastSpringboneRuntimeStandaloneProvider.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10FastSpringboneRuntimeStandaloneProvider.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10NopSpringboneRuntime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10NopSpringboneRuntime.cs similarity index 95% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10NopSpringboneRuntime.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10NopSpringboneRuntime.cs index 040b0b9de..f14e1e41e 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10NopSpringboneRuntime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10NopSpringboneRuntime.cs @@ -20,7 +20,7 @@ namespace UniVRM10 return Task.CompletedTask; } - public void Process() + public void Process(float deltaTime) { } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10NopSpringboneRuntime.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10NopSpringboneRuntime.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10NopSpringboneRuntime.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Springbone/Vrm10NopSpringboneRuntime.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 5a800d2e1..e702496b1 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -156,7 +156,7 @@ namespace UniVRM10 Expression.Process(eyeDirection); // 6. SpringBone - SpringBone.Process(); + SpringBone.Process(Time.deltaTime); } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs index 902654f35..0a38b0481 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs @@ -51,14 +51,11 @@ namespace UniVRM10 public void Dispose() { - _merger?.RestoreMaterialInitialValues(); + _merger?.Dispose(); _merger = null; _eyeDirectionApplicable?.Restore(); _eyeDirectionApplicable = null; - - _merger?.Dispose(); - _merger = null; } internal void Process(LookAtEyeDirection inputEyeDirection) diff --git a/Assets/VRM10/Runtime/FastSpringBone/FastSpringBoneService.cs b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBoneService.cs index 51a76d887..45be4e92d 100644 --- a/Assets/VRM10/Runtime/FastSpringBone/FastSpringBoneService.cs +++ b/Assets/VRM10/Runtime/FastSpringBone/FastSpringBoneService.cs @@ -1,4 +1,5 @@ using UniGLTF.SpringBoneJobs; +using Unity.Jobs; using UnityEngine; namespace UniVRM10.FastSpringBones @@ -95,12 +96,17 @@ namespace UniVRM10.FastSpringBones } public void ManualUpdate(float deltaTime) + { + ManualUpdate(deltaTime, null).Complete(); + } + + public JobHandle ManualUpdate(in float deltaTime, in JobHandle? dependency = null) { if (UpdateType != UpdateTypes.Manual) { throw new global::System.ArgumentException("require UpdateTypes.Manual"); } - _fastSpringBoneScheduler.Schedule(deltaTime).Complete(); + return _fastSpringBoneScheduler.Schedule(deltaTime, dependency); } public void OnDrawGizmosSelected() diff --git a/Assets/VRM10/Runtime/VRM10.asmdef b/Assets/VRM10/Runtime/VRM10.asmdef index decb9b22a..0ce554345 100644 --- a/Assets/VRM10/Runtime/VRM10.asmdef +++ b/Assets/VRM10/Runtime/VRM10.asmdef @@ -8,6 +8,7 @@ "GUID:b7aa47b240b57de44a4b2021c143c9bf", "GUID:f2ca1407928ebdc4bbe7765cc278be44", "GUID:2665a8d13d1b3f18800f46e256720795", + "GUID:d8b63aba1907145bea998dd612889d6b", "GUID:1cd941934d098654fa21a13f28346412", "GUID:3e5d614bc16b50d41bd94c8d7444ca46", "GUID:f06555f75b070af458a003d92f9efb00" diff --git a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarp.asmdef b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarp.asmdef index 6801da68a..93ddd3c01 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarp.asmdef +++ b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarp.asmdef @@ -6,7 +6,8 @@ "GUID:e47c917724578cc43b5506c17a27e9a0", "GUID:8d76e605759c3f64a957d63ef96ada7c", "GUID:1cd941934d098654fa21a13f28346412", - "GUID:5f875fdc81c40184c8333b9d63c6ddd5" + "GUID:5f875fdc81c40184c8333b9d63c6ddd5", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarpRuntime.cs b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarpRuntime.cs index 883af31c2..a36b11498 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarpRuntime.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/ClothWarpRuntime.cs @@ -135,12 +135,7 @@ namespace UniVRM10.ClothWarp // } } - public void Process() - { - Process(Time.deltaTime); - } - - void Process(float deltaTime) + public void Process(float deltaTime) { if (!_initialized) { diff --git a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/ClothWarpJobRuntime.cs b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/ClothWarpJobRuntime.cs index e4461c273..294216ad1 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/ClothWarpJobRuntime.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/ClothWarpJobRuntime.cs @@ -193,14 +193,12 @@ namespace UniVRM10.ClothWarp.Jobs 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, - }); + colliderInfo.Add(new BlittableCollider( + offset: collider.Offset, + radius: collider.Radius, + tailOrNormal: collider.TailOrNormal, + colliderType: TranslateColliderType(collider.ColliderType), + colliderTransformIndex: colliderTransformIndex)); _colliders.Add(collider); } @@ -410,11 +408,6 @@ namespace UniVRM10.ClothWarp.Jobs } } - public void Process() - { - Process(Time.deltaTime); - } - public void Process(float deltaTime) { var frame = new FrameInfo(deltaTime, Vector3.zero); diff --git a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/Particle.cs b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/Particle.cs index 2df9886ab..0da858cd4 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/Particle.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothWarp/Runtime/Jobs/Particle.cs @@ -39,14 +39,12 @@ namespace UniVRM10.ClothWarp.Jobs public BlittableJointMutable ToBlittableJointMutable() { - return new BlittableJointMutable - { - stiffnessForce = Stiffness, - gravityPower = 1.0f, - gravityDir = Gravity, - dragForce = Deceleration, - radius = Radius, - }; + return new BlittableJointMutable( + stiffnessForce: Stiffness, + gravityPower: 1.0f, + gravityDir: Gravity, + dragForce: Deceleration, + radius: Radius); } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/UIToolkit/VRM10MainView.cs b/Assets/VRM10_Samples/VRM10Viewer/UIToolkit/VRM10MainView.cs index 23a5b1495..8e45be6d8 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/UIToolkit/VRM10MainView.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/UIToolkit/VRM10MainView.cs @@ -185,15 +185,14 @@ namespace UniVRM10.VRM10Viewer m_controller.ShowBoxMan(m_showBoxMan.value); if (m_controller.TryUpdate( m_motionMode.value == 0, - new BlittableModelLevel - { - ExternalForce = new Vector3( + new BlittableModelLevel( + externalForce: new Vector3( m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value), - StopSpringBoneWriteback = m_useSpringbonePause.value, - SupportsScalingAtRuntime = m_useSpringboneScaling.value, - }, + stopSpringBoneWriteback: m_useSpringbonePause.value, + supportsScalingAtRuntime: m_useSpringboneScaling.value + ), out var loaded )) { diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10.Samples.VRM10Viewer.asmdef b/Assets/VRM10_Samples/VRM10Viewer/VRM10.Samples.VRM10Viewer.asmdef index b5eb2e01e..705584a0a 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10.Samples.VRM10Viewer.asmdef +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10.Samples.VRM10Viewer.asmdef @@ -7,7 +7,8 @@ "GUID:e47c917724578cc43b5506c17a27e9a0", "GUID:1cd941934d098654fa21a13f28346412", "GUID:3e5d614bc16b50d41bd94c8d7444ca46", - "GUID:f06555f75b070af458a003d92f9efb00" + "GUID:f06555f75b070af458a003d92f9efb00", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/VRM10_Samples/VRM10Viewer/uGui/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/uGui/VRM10ViewerUI.cs index 88332f56c..1610570e6 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/uGui/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/uGui/VRM10ViewerUI.cs @@ -226,12 +226,11 @@ namespace UniVRM10.VRM10Viewer m_controller.ShowBoxMan(m_showBoxMan.isOn); if (m_controller.TryUpdate( m_ui.IsTPose, - new BlittableModelLevel - { - ExternalForce = new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value), - StopSpringBoneWriteback = m_springbonePause.isOn, - SupportsScalingAtRuntime = m_springboneScaling.isOn, - }, + new BlittableModelLevel( + externalForce: new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value), + stopSpringBoneWriteback: m_springbonePause.isOn, + supportsScalingAtRuntime: m_springboneScaling.isOn + ), out var loaded )) { diff --git a/Assets/VRM_Samples/SimpleViewer/VRM.Samples.SimpleViewer.asmdef b/Assets/VRM_Samples/SimpleViewer/VRM.Samples.SimpleViewer.asmdef index b356b2415..afadcbabe 100644 --- a/Assets/VRM_Samples/SimpleViewer/VRM.Samples.SimpleViewer.asmdef +++ b/Assets/VRM_Samples/SimpleViewer/VRM.Samples.SimpleViewer.asmdef @@ -6,7 +6,8 @@ "GUID:1cd941934d098654fa21a13f28346412", "GUID:b7aa47b240b57de44a4b2021c143c9bf", "GUID:05dd262a0c0a2f841b8252c8c3815582", - "GUID:3e5d614bc16b50d41bd94c8d7444ca46" + "GUID:3e5d614bc16b50d41bd94c8d7444ca46", + "GUID:d8b63aba1907145bea998dd612889d6b" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs b/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs index 8f55d7e3a..8f188653c 100644 --- a/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs +++ b/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs @@ -343,15 +343,15 @@ namespace VRM.SimpleViewer m_loaded.EnableLipSyncValue = m_enableLipSync.isOn; m_loaded.EnableBlinkValue = m_enableAutoBlink.isOn; m_loaded.SetSpringboneModelLevel(new UniGLTF.SpringBoneJobs.Blittables.BlittableModelLevel - { - ExternalForce = new Vector3( + ( + externalForce: new Vector3( m_springExternalX.value, m_springExternalY.value, m_springExternalZ.value ), - StopSpringBoneWriteback = m_springBonePause.isOn, - SupportsScalingAtRuntime = m_springBoneScaling.isOn, - }); + stopSpringBoneWriteback: m_springBonePause.isOn, + supportsScalingAtRuntime: m_springBoneScaling.isOn + )); m_loaded.Update(); } }