ValveSoftware / steamvr_unreal_plugin

SteamVR Input Unreal Plugin - Documentation at: https://github.com/ValveSoftware/steamvr_unreal_plugin/wiki Sample project (UE4.15-4.23): https://github.com/ValveSoftware/steamvr_unreal_plugin/wiki/sample/SteamVRInputPlugin.zip Sample Project (UE.424+): https://github.com/ValveSoftware/steamvr_unreal_plugin/wiki/sample/SteamVRInputPlugin_UEIntegrated.7z
Other
168 stars 29 forks source link

FSteamVRInputDevice::GetControllerOrientationAndPosition doesn't take into account XRSystem's BaseOrientation/BasePosition #2

Closed brendanwalker closed 5 years ago

brendanwalker commented 5 years ago

Apologies if I should have posted about this in the Discord channel first. Since this is a bit long winded I figured posting an issue made more sense:

If you use the XRSystem's ResetOrientationAndPosition call the BaseOrientation and BasePosition state are set. This call is used in "Moss" every time we transition to a new room and want to recenter on the room's camera. The FSteamVRHMD::PoseToOrientationAndPosition function is used to apply the inverse of the BaseOrientation and BasePosition to the controller pose.

I was expecting to see the same application here: https://github.com/ValveSoftware/steamvr_unreal_plugin/blob/4.21/SteamVRInput/Source/SteamVRInputDevice/Private/SteamVRInputDevice.cpp#L664-L669

I was able to work around this by adding the following state to FSteamVRInputDevice:

    // @POLYARC BEGIN
    /** Base Orientation defined by the XRTrackingSystem */
    FQuat CachedBaseOrientation;

    /** Base Position defined by the XRTrackingSystem */
    FVector CachedBasePosition;
    // @POLYARC END

Then caching those values in Tick:

void FSteamVRInputDevice::Tick(float DeltaTime)
{
    // @POLYARC BEGIN
    if (GEngine->XRSystem.IsValid())
    {
        CachedBaseOrientation = GEngine->XRSystem->GetBaseOrientation();
        CachedBasePosition = GEngine->XRSystem->GetBasePosition();
    }
    else
    {
        CachedBaseOrientation = FQuat::Identity;
        CachedBasePosition = FVector::ZeroVector;
    }
    // @POLYARC END
}

And then finally using those values in FSteamVRInputDevice::GetControllerOrientationAndPosition():

            // @POLYARC BEGIN
            //FVector Position = ((FVector(-Pose.M[3][2], Pose.M[3][0], Pose.M[3][1])) * GWorld->GetWorldSettings()->WorldToMeters);
            //OutPosition = Position;
            FVector Position = ((FVector(-Pose.M[3][2], Pose.M[3][0], Pose.M[3][1])) * GWorld->GetWorldSettings()->WorldToMeters - CachedBasePosition);
            OutPosition = CachedBaseOrientation.Inverse().RotateVector(Position);

            //OutOrientation.Normalize();
            //OutOrientation = OrientationQuat.Rotator();
            OrientationQuat = CachedBaseOrientation.Inverse() * OrientationQuat;
            OrientationQuat.Normalize();
            OutOrientation = OrientationQuat.Rotator();
            // @POLYARC END

If I'm not mistaken, we need to cache the values in Tick since GetControllerOrientationAndPosition() can be called in the render thread as part of the MotionControllers LateUpdate.

1runeberg commented 5 years ago

Thanks @brendanwalker, have reviewed, and this was overlooked during the re-implementation of the Motion Controller features - are you happy for me to integrate these to the code base similar to a Pull Request?

brendanwalker commented 5 years ago

Yeah totally happy! Thanks for taking a look.

1runeberg commented 5 years ago

Thanks Brendan! I've published develop-4.21 with your revisions included, comment link to this GitHub issue at Tick().

Can you check from your end please before I start propagating to other branches (min ver for this is 4.18 as far as I can tell)

1runeberg commented 5 years ago

@brendanwalker - quick nudge :) If you can do a finally verification please on your end before I propagate PR to main branches.

Cheers

1runeberg commented 5 years ago

Added in internal branches. Will be in 0.6 release.