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();
}
}