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/AnglelimitCone.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitCone.cs
new file mode 100644
index 000000000..d335044e3
--- /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 src;
+ }
+ }
+}
\ 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/AnglelimitSpace.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpace.cs
new file mode 100644
index 000000000..1d9e06008
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpace.cs
@@ -0,0 +1,36 @@
+using Unity.Mathematics;
+
+namespace UniGLTF.SpringBoneJobs
+{
+ public static class AnglelimitSpace
+ {
+ public static float3 ToTailDir(in quaternion src)
+ {
+ // // Y+方向からjointのheadからtailに向かうベクトルへの最小回転
+ // let axisRotation = fromToQuaternion(vec3(0, 1, 0), boneAxis);
+
+ // // limitのローカル空間をワールド空間に写像する回転
+ // let rotation =
+ // joint.parent.worldRotation *
+ // joint.localSpaceInitialRotation *
+ // axisRotation *
+ // joint.limit.rotation;
+
+ // // tailの向きをlimitのローカル空間に写像する
+ // tailDir = tailDir.applyQuaternion(rotation.inverse);
+
+ // // limitを適用する
+ // joint.limit.apply(tailDir);
+
+ // // tailの向きをワールド空間に戻す
+ // tailDir = tailDir.applyQuaternion(rotation);
+
+ throw new System.NotImplementedException();
+ }
+
+ public static quaternion FromTailDir(in float3 src)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpace.cs.meta b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpace.cs.meta
new file mode 100644
index 000000000..99e27a255
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpace.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e38e2998df511664cb0d6e582e6a05a3
+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..e6d07be63
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Anglelimit/AnglelimitSpherical.cs
@@ -0,0 +1,36 @@
+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を用いて再計算する
+ return new float3(math.sin(theta), math.cos(theta) * math.cos(phi), math.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/BlittableJointMutable.cs b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs
index 96b48fa3a..d6566a659 100644
--- a/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs
+++ b/Assets/UniGLTF/Runtime/SpringBoneJobs/Blittables/BlittableJointMutable.cs
@@ -12,23 +12,48 @@ namespace UniGLTF.SpringBoneJobs.Blittables
[Serializable]
public readonly struct BlittableJointMutable
{
- private readonly float4x2 _data;
-
+ ///
+ /// |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)
+ float radius = 0,
+ // anglelimit
+ float alType = 0,
+ float limit1 = 0,
+ float limit2 = 0,
+ quaternion offset = default)
{
var c0 = new float4(stiffnessForce, gravityPower, dragForce, radius);
var c1 = new float4(gravityDir, 0);
- _data = new float4x2(c0, c1);
+ var c2 = new float4(alType, limit1, limit2, 0);
+ var c3 = offset.value;
+ _data = new float4x4(c0, c1, c2, c3);
}
}
}
\ No newline at end of file