fix dot fallback

This commit is contained in:
ousttrue
2026-08-20 14:15:09 +09:00
parent 52e1250813
commit 75ef36b076

View File

@@ -6,9 +6,19 @@ 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)
in BlittableJointImmutable logic,
in BlittableJointMutable joint,
in quaternion parentRotation,
in float3 head,
in float3 nextTail
)
{
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
var tailDir = math.mul(
math.inverse(angleSpaceToWorld),
math.normalizesafe(nextTail - head)
);
switch (joint.anglelimitType)
{
case AnglelimitTypes.None:
@@ -16,51 +26,48 @@ namespace UniGLTF.SpringBoneJobs
return nextTail;
case AnglelimitTypes.Cone:
{
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalizesafe(nextTail - head));
tailDir = AnglelimitCone.Apply(tailDir, joint.anglelimit1);
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
}
tailDir = AnglelimitCone.Apply(tailDir, joint.anglelimit1);
break;
case AnglelimitTypes.Hinge:
{
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalizesafe(nextTail - head));
tailDir = AnglelimitHinge.Apply(tailDir, joint.anglelimit1);
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
}
tailDir = AnglelimitHinge.Apply(tailDir, joint.anglelimit1);
break;
case AnglelimitTypes.Spherical:
{
var angleSpaceToWorld = anglelimitSpaceToWorld(logic, joint, parentRotation);
var tailDir = math.mul(math.inverse(angleSpaceToWorld), math.normalizesafe(nextTail - head));
tailDir = AnglelimitSpherical.Apply(tailDir, joint.anglelimit1, joint.anglelimit2);
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
}
tailDir = AnglelimitSpherical.Apply(
tailDir,
joint.anglelimit1,
joint.anglelimit2
);
break;
default:
throw new System.ArgumentException($"unknown joint.anglelimitType: {joint.anglelimitType}");
throw new System.ArgumentException(
$"unknown joint.anglelimitType: {joint.anglelimitType}"
);
}
return head + math.mul(angleSpaceToWorld, tailDir) * logic.length;
}
/// <param name="nextTail">nextTail(position vector in world space)</param>
/// <returns>tailDir(directionay vector in angle space)</returns>
/// <exception cref="System.NotImplementedException"></exception>
public static quaternion anglelimitSpaceToWorld(in BlittableJointImmutable logic, in BlittableJointMutable joint,
in quaternion parentRotation)
public static quaternion anglelimitSpaceToWorld(
in BlittableJointImmutable logic,
in BlittableJointMutable joint,
in quaternion parentRotation
)
{
// Y+方向からjointのheadからtailに向かうベクトルへの最小回転
var axisRotation = getAxisRotation(logic.boneAxis);
// limitのローカル空間をワールド空間に写像する回転
return
math.mul(parentRotation,
math.mul(logic.localRotation,
math.mul(axisRotation,
joint.anglelimitOffset)))
;
return math.mul(
parentRotation,
math.mul(logic.localRotation, math.mul(axisRotation, joint.anglelimitOffset))
);
}
/// <summary>
@@ -71,20 +78,22 @@ namespace UniGLTF.SpringBoneJobs
///
/// TODO: Replace with the appropriate link to the specification later
/// </summary>
public static quaternion getAxisRotation(in float3 to)
public static quaternion getAxisRotation(in float3 boneAxis)
{
// dot(from, to) + 1
var dot1 = to.y + 1f;
// headからtailに向かうベクトルとY+方向との内積
var dot = boneAxis.y;
// Handle the case where from and to are parallel and opposite
if (dot1 < 1e-8f) // dot is approximately -1
if (dot == -1.0)
{
return new quaternion(1f, 0f, 0f, 0f);
// headからtailに向かうベクトルがY-方向の場合、X軸周りに180度回転させた回転を設定する
return new quaternion(1, 0, 0, 0);
}
else
{
// それ以外の場合、Y+方向からjointのheadからtailに向かうベクトルへの最小回転を設定する
// quaternion(cross(from, to); dot(from, to) + 1).normalized
return math.normalizesafe(new quaternion(boneAxis.z, 0, -boneAxis.x, dot + 1));
}
// General case
// quaternion(cross(from, to); dot(from, to) + 1).normalized
return math.normalizesafe(new quaternion(to.z, 0f, -to.x, dot1));
}
}
}
}