add angle limit data BlittableJointMutable

This commit is contained in:
ousttrue
2025-07-17 22:16:36 +09:00
parent 3b06615340
commit d08e239541
12 changed files with 241 additions and 5 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b09ae318bccbfce4993fafb418e1e8c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using Unity.Mathematics;
namespace UniGLTF.SpringBoneJobs
{
public static class AnglelimitCone
{
/// <param name="src">AngleLimit空間の方向ベクトル</param>
/// <param name="angleLimit">radius</param>
/// <returns>AngleLimit空間の方向ベクトル</returns>
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 780b79f298faea74ba4a123039a3faeb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using Unity.Mathematics;
namespace UniGLTF.SpringBoneJobs
{
public static class AnglelimitHinge
{
/// <param name="src">AngleLimit空間の方向ベクトル</param>
/// <param name="angleLimit">radius</param>
/// <returns>AngleLimit空間の方向ベクトル</returns>
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb1e1bbfc1a339c40b5df4d846f09da4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e38e2998df511664cb0d6e582e6a05a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using Unity.Mathematics;
namespace UniGLTF.SpringBoneJobs
{
public static class AnglelimitSpherical
{
/// <param name="tailDir">AngleLimit空間の方向ベクトル</param>
/// <param name="limitAnglePhi">radius</param>
/// <param name="limitAngleTheta">radius</param>
/// <returns>AngleLimit空間の方向ベクトル</returns>
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));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc767b94391a0c44ebd21390c57a869e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
namespace UniGLTF.SpringBoneJobs
{
public enum AnglelimitTypes
{
None,
Cone,
Hinge,
Spherical,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56836f5a87c46a641a0ffc048c10655f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,23 +12,48 @@ namespace UniGLTF.SpringBoneJobs.Blittables
[Serializable]
public readonly struct BlittableJointMutable
{
private readonly float4x2 _data;
/// <summary>
/// |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
/// </summary>
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);
}
}
}