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