GetHMDWornState stops working when used to toggle stereo rendering

Build type: Binary from the Unreal Launcher

Build version: 4.13.0 - 3106830

Detailed description of the issue: I tried to replicate the new editor feature “VR Mode Auto-Entry” by using GEngine->HMDDevice->GetHMDWornState() in a custom actor. It works once when putting the HMD on and taking it off, then it stops working if it is used to toggle stereo rendering. Disabling stereo rendering seems to break the worn state.

Repro Steps:

  1. Create a new blank C++ project called “HmdTest”, no starter content.
  2. Save the untitled level and set it as a start up level in the project settings.
  3. Add “HeadMountedDisplay” to the dependencies in the build script.
  4. Add a new C++ class called “HmdWornTestActor” derived from StaticMeshActor.
  5. Implement the class as shown in the attachment “HmdWornTestActor_Source.zip” (HmdWornTestActor.cpp and .h).
  6. Add a new material called “IndicatorMtl”, add a vector parameter called “Color”, set it to white and wire it to the base color input.
  7. Add a blueprint class called “HmdWornIndicatorActor” derived from this C++ class. In its StaticMeshComponent, set the actor to being mobile, set the mesh to a cube and its material to the new IndicatorMtl.
  8. Implement the event graph of the actor as shown in “HmdWornIndicatorActor_BP_JustIndicate.jpg” (see attachments).
  9. Place an instance of the actor in the level so that it can be seen from the player start.
  10. Package the project and run it on a machine with an attached Oculus Rift CV1. Test with a thumb on the CV1 worn sensor to see how the mesh changes color accordingly.
  11. Alter the event graph as shown in “HmdWornIndicatorActor_BP_ToggleHmd.jpg” (see attachments).
  12. Package the project again and test on the same machine. Entering VR mode by putting the headset on works once, exiting VR mode by taking it off works once as well, then it stops working. VR mode will not toggle a second time and the indicator mesh stays red as well.

With this I can reproduce the problem 100% of the time on my test machine (no second Rift capable machine available for testing). You can find the completed project files (zipped from within the editor) in the attachments.

System Specs: Windows 7 Ultimate x64, Intel Core i7 4930K, 32 GB RAM, AMD Radeon R290X, Oculus Rift CV1 (version 1.7.0 runtime installed).

Attachments:
[HmdWornTestActor_Source.zip (.cpp and .h for the C++ actor)][1]

[HmdTest.zip (project files)][4]

Hey Neomi-

What’s happening is that when you remove the headset and call EnableHMD(false) node in the blueprint, this disables input to the headset and prevents it from being registered when put back on. Adding GEngine->HMDDevice->EnableHMD(true); inside your if (GEngine->HMDDevice.IsValid()) statement will first re-enable the headset before calling OnHmdWorn().

Cheers

But EnableHMD(true) is for enabling stereo rendering as far as my understanding goes, something I wouldn’t want to do unless I register that the HMD is worn. The worn state initially works with the HMD disabled (before enabling it for the first time). So what I would need to do is to re-enable the headset (right after disabling it) without re-enabling stereo rendering as well or disable stereo rendering only without disabling the headset. Is there a way to do this?

The EnableHMD node calls the function bool UHeadMountedDisplayFunctionLibrary::EnableHMD(bool bEnable) which does the same “IsValid” check you have in your if statement. If this succeeds it then does two things; first it calls GEngine->HMDDevice->EnableHMD(bEnable); to enable the headset. The second task makes a call to either GEngine->HMDDevice->EnableStereo(true); / GEngine->HMDDevice->EnableStereo(false); based on the checkbox of the node which enables / disables stereo rendering respectively. Adding only the line GEngine->HMDDevice->EnableHMD(true); to your code does in fact re-enable the headset without re-enabling stereo rendering. Stereo Rendering is enabled when your HmdWorn function calls the EnableHMD blueprint node, which allows for seamless switching of visual input to/from the HMD device when it is worn/removed.

Sorry for the late answer, I was very busy with work and just got around to testing. With your explanation I now understand how it works (still pretty new to the Unreal engine) and your solution works like a charm. Thank you very much for the help.

Can we have HDM controls ON without Stereo??? on 4.18+ (4.17 used to work) :frowning:

Yep, they broke it in 4.18+, now vr.benablestereo is the same as vr.enablehmd. Why have 2 commands that do the same thing.

I second that. When stereo rendering is turned off, theres no way to catch HMD events like put on, because the hmd worn state does not update anymore. Is there any engine modification which keeps the oculus updating its state, even when stereo rendering is turned off?

Hi! Did you find any solution to get access to HMD events when stereo is OFF?

Still waiting for this.
It’s awful how little i can manange my VR Devices. I have to have 2 screens for my project and when i disable stereo, i have to get worn state to know that user has VR headset on his head or not. But when disable stereo then worn state is always not worn. Ok, then i can use VR Spectator screen right and have both screens at once? NO! When i remove headset then UE4 loses focus (thx Oculus).

I just ran into this problem too. I just want to be able to detect whether or not the HMD is worn or not and determine whether or not to throw up a pause menu but, you can’t interact with it unless you disable stereo rendering… What is the point of being able to determine the worn state if you can’t even access it when you really need it.

There doesn’t seem to be any difference between GEngine->StereoRenderingDevice->EnableStereo() and GEngine->XRSystem->GetHMDDevice()->EnableHMD(). In other words, disabling Stereo disables the HMD, along with its inputs. This is a pseudocode of what I am trying to implement, but it doesn’t work.

void BeginPlay(){
    //Enable HMD
    GEngine->XRSystem->GetHMDDevice()->EnableHMD(true);
}

void Tick(){
    //Toggle Stereo Mode according to HMD Worn State
    GEngine->StereoRenderingDevice->EnableStereo(bIsHMDWorn);
}

Is there a workaround for this?