Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] ObjectManipulator rotation is inverted in some cases with constraint on two axes #952

Open
NoTuxNoBux opened this issue Oct 31, 2024 · 0 comments
Labels
Needs: Triage Needs to be triaged. Type: Bug A problem with an existing feature that can be fixed with the next patched release.

Comments

@NoTuxNoBux
Copy link

Describe the bug

This is basically microsoft/MixedRealityToolkit-Unity#8947 from the MRTK2, but for the MRTK3 - the original issue was closed because of the MRTK2 being retired, but I also seem to be experiencing a similar issue in the MRTK3 with a similar setup.

To reproduce

See also the original issue's reproduction steps, my setup is very similar:

  1. Have a 3D object such as a cube with the necessary collider on it.
  2. Set an ObjectManipulator on it.
  3. Configure an AxisRotationConstraint to restrict the X and Z axes (so you can only rotate from 'left to right' or over the Y axis). Keep Hand Type and Proximity Type on Everything, don't enable Use Local Space For Constraint.
  4. When using a single hand to move the object left and right in play mode, moving your hand left after grabbing rotates the object right and the other way around.

In my case I have an object that was rotated 180º so I first suspected that was causing it, but it wasn't.

Expected behavior

The inverse happens; moving hand left rotates the object left as well.

Your setup (please complete the following information)

  • Unity Version: 6000.0.11f1
  • MRTK Version or Commit: 3.2.0.

Target platform (please complete the following information)

  • Meta Quest 3
  • Meta XR

Additional context

I was able to create my own RotateLogic and attach it to the ObjectManipulator to fix the issue:

public sealed class ObjectManipulatorReversedRotateLogic : ManipulationLogic<Quaternion>
{
    private Vector3 startHandlebar;
    private Quaternion startInputRotation;
    private Quaternion startRotation;

    /// <inheritdoc />
    public override void Setup(List<UnityEngine.XR.Interaction.Toolkit.Interactors.IXRSelectInteractor> interactors, UnityEngine.XR.Interaction.Toolkit.Interactables.IXRSelectInteractable interactable, MixedRealityTransform currentTarget)
    {
        base.Setup(interactors, interactable, currentTarget);

        if (NumInteractors >= 2)
        {
            startHandlebar = GetHandlebarDirection(interactors, interactable);
        }

        startInputRotation = interactors[0].GetAttachTransform(interactable).rotation;
        startRotation = currentTarget.Rotation;
    }

    /// <inheritdoc />
    public override Quaternion Update(
        List<UnityEngine.XR.Interaction.Toolkit.Interactors.IXRSelectInteractor> interactors,
        UnityEngine.XR.Interaction.Toolkit.Interactables.IXRSelectInteractable interactable,
        MixedRealityTransform currentTarget,
        bool centeredAnchor)
    {
        base.Update(interactors, interactable, currentTarget, centeredAnchor);

        if (NumInteractors == 1)
        {
            // NOTE: Only this line changed as opposed to the original MRTK RotateLogic.
            return Quaternion.Inverse(interactors[0].GetAttachTransform(interactable).rotation) * startInputRotation * startRotation;
        }
        else
        {
            // TODO: This gimbal locks if you hold an object with two hands and then rotate your body a full 180 degrees.
            return Quaternion.FromToRotation(startHandlebar, GetHandlebarDirection(interactors, interactable)) * startRotation;
        }
    }

    private static Vector3 GetHandlebarDirection(List<UnityEngine.XR.Interaction.Toolkit.Interactors.IXRSelectInteractor> interactors, UnityEngine.XR.Interaction.Toolkit.Interactables.IXRSelectInteractable interactable)
    {
        Debug.Assert(interactors.Count >= 2, $"GetHandlebarDirection called with less than 2 interactors ({interactors.Count}).");
        return interactors[1].GetAttachTransform(interactable).position - interactors[0].GetAttachTransform(interactable).position;
    }
}
@NoTuxNoBux NoTuxNoBux added Needs: Triage Needs to be triaged. Type: Bug A problem with an existing feature that can be fixed with the next patched release. labels Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Triage Needs to be triaged. Type: Bug A problem with an existing feature that can be fixed with the next patched release.
Projects
None yet
Development

No branches or pull requests

1 participant