diff --git a/Assets/VRM10/Runtime/Components/Constraint/ConstraintAxes.cs b/Assets/VRM10/Runtime/Components/Constraint/ConstraintAxes.cs
index f2e1165a1..ab3fd2ce3 100644
--- a/Assets/VRM10/Runtime/Components/Constraint/ConstraintAxes.cs
+++ b/Assets/VRM10/Runtime/Components/Constraint/ConstraintAxes.cs
@@ -14,6 +14,13 @@ namespace UniVRM10
Z = 4,
}
+ [Flags]
+ public enum YawPitchMask
+ {
+ Yaw = 1,
+ Pitch = 2,
+ }
+
public static class AxesMaskExtensions
{
public static Vector3 Freeze(this AxisMask mask, Vector3 src)
diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs
index 9acb759cf..9c7874d1a 100644
--- a/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs
+++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs
@@ -8,6 +8,18 @@ namespace UniVRM10
[DisallowMultipleComponent]
public class VRM10AimConstraint : VRM10Constraint
{
+ ///
+ /// Yaw(Y), Pitch(X) の2軸だけ
+ ///
+ [SerializeField]
+ [EnumFlags]
+ YawPitchMask m_freezeAxes = default;
+ public YawPitchMask FreezeAxes
+ {
+ get => m_freezeAxes;
+ set => m_freezeAxes = value;
+ }
+
[Header("Source")]
[SerializeField]
Transform m_source = default;
@@ -21,6 +33,10 @@ namespace UniVRM10
[SerializeField]
ObjectSpace m_destinationCoordinate = default;
+ ///
+ /// シリアライズは、Aim と Up で記録。
+ /// UniVRM の Editor では Aim と Up が直交しないことを許可しない。
+ ///
[SerializeField]
public Quaternion DestinationOffset = Quaternion.identity;
@@ -59,6 +75,13 @@ namespace UniVRM10
var m = new Matrix4x4(xAxis, yAxis, zAxis, new Vector4(0, 0, 0, 1));
var parent = TR.FromParent(transform);
m_delta = Quaternion.Inverse(parent.Rotation * m_src.LocalInitial.Rotation * DestinationOffset) * m.rotation;
+
+ var (yaw, pitch) = Matrix4x4.Rotate(Quaternion.Inverse(m_delta)).CalcYawPitch(Vector3.forward);
+ if (m_freezeAxes.HasFlag(YawPitchMask.Yaw)) yaw = 0;
+ if (m_freezeAxes.HasFlag(YawPitchMask.Pitch)) pitch = 0;
+
+ m_delta = Quaternion.Euler(pitch, yaw, 0);
+
transform.rotation = parent.Rotation * m_src.LocalInitial.Rotation * Delta;
}
}