BuzzteeBear / OpenXR-MotionCompensation

OpenXR API layer for motion compensation
GNU Lesser General Public License v2.1
45 stars 7 forks source link

Fails `QuadHands` OpenXR conformance test #16

Closed fredemmott closed 2 days ago

fredemmott commented 1 month ago

Conformance tests: https://github.com/KhronosGroup/OpenXR-CTS/releases/latest

Using the x64 zip, to repro:

  1. Install OpenXRMC
  2. Run the test: conformance_cli.exe -G D3D11 --apiVersion 1.0 "QuadHands" ; you should see passing behavior, but do not yet mark as accepted
  3. Activate OpenXRMC, e.g. ctrl+ins
  4. Move your tracker
  5. move (other) controller; test no longer has passing behavior: quad layer is no longer attached to the controller cube

This is the most relevant part of the interactive composition tests; all should pass (as should the CTS as a whole). To run all:

conformance_cli.exe -G D3D11 --apiVersion 1.0 "[composition][interactive]"

I am using Oculus Link/AirLink, with no other layers enabled. For interactive tests, the CTS prompts you to press 'menu' and 'select' buttons - on a quest controller via link, 'select' is A, 'menu' is B; bindings on other controllers will vary, but are rarely what are actually labelled as 'menu' and 'select'.

fredemmott commented 1 month ago

The non-interactive XrCompositionLayerQuad test is also relevant, but passes :)

BuzzteeBear commented 1 month ago

Thanks a lot for bringing this to my attention. There's an option enable_physical = 0 in oxrmc's config file to prevent it from capturing the left controller by default. I might consider to turn this opt-out into an opt-in to pass the conformance test out of the box. It's just that using a handheld motion controller for motion compensation was the first use case that had been implemented, so it seemed natural to keep it as default setting. And having an incomplete/non-functional default configuration isn't an ideal option either.

BuzzteeBear commented 1 month ago

Sorry didn't mean to close that issue :)

fredemmott commented 1 month ago

Sorry for being unclear: the problematic behavior isn't that the left controller is intercepted; when the left controller is being used for OXRMC tracking, the issue is that the quad layer for the right controller isn't lined up with its' cube once OXRMC is adding an offset:

image

The quad layer should always be aligned with (but not touching) the front face of the controller cube, e.g.:

image

The fact that it's not lined up when OXRMC is active indicates that the poses for quad layers are not being transformed in a consistent way as the headset-tracked poses that are used to generate the projection layer.

Edit: for reference, the official definition of the correct behavior is:

10x10cm Quads labeled 'L' and 'R' should appear 10cm along the grip positive Z in front of the center of 10cm cubes rendered at the controller grip poses, or at the origin if that controller isn't being tested. The quads should face you and be upright when the controllers are in a thumbs-up pointing-into-screen pose. Check that the quads are properly backface-culled, that 'R' is always rendered atop 'L', and both are atop the cubes when visible.

From https://github.com/KhronosGroup/OpenXR-CTS/blob/477fae49580b11132a57587b452159f26b0b0240/src/conformance/conformance_test/test_LayerComposition.cpp#L474-L481

fredemmott commented 1 month ago

I am intentionally using left controller tracking as I do not own any motion hardware, or additional trackers; I'm just doing this for testing, as I believe this conformance test is representative of the requirements for correct handling of OpenKneeboard, and the mismatch between the projected right-controller-cube and the right-controller-quadlayer seem representative of issues reported when using them in combination.

fredemmott commented 1 month ago

To put it another way, whenever I move the right controller, the right cube and the right quad layer should both move, but as a single rigid unit - the relation between them never changes.

When OXRMC is active with left controller tracking, moving the left controller should visually move the right controller's projected cube and quad layer as if I'd moved my head, but the relation between the cube and quad layer should still never change - they should still act as a single rigid system. What's actually happening is that when I move the left controller, the quad layer moves relative to the cube, which seems incorrect.

BuzzteeBear commented 1 month ago

I can see your point now. There seems to be something off here indeed. I'll have a closer look at it asap. Thanks again for taking the time to look into that matter!

fredemmott commented 1 month ago

On a tangent, does this seem like correct advice (for the OpenKneeboard FAQ) for pose-manipulation layers in general, not just OXRMC?

[...] if the other tool provides instructions for OpenKneeboard, follow those instructions [... otherwise:]

  • If you want OpenKneeboard to be anchored to the ‘game world’ (for example, fixed relative to your in-game rendered cockpit), put OpenKneeboard above the other tool
  • If you want OpenKneeboard to be anchored to the ‘real world’ (for example, fixed relative to your physical steering wheel, HOTAS, or literally on your knee), put OpenKneeboard below the other tool
  • If you’re unsure, try both ways and see which you prefer

... where 'above' means 'closer to the game', and 'below' means 'closer to the runtime'.

BuzzteeBear commented 1 month ago

Well I can see the intent and that'll work for something like XRNeckSafer (and make it easier to understand). But unfortunately, for the motion compensation use case in particular, this description might be a bit misleading. That's because your peripherals usually are mounted onto the motion rig so they'll move in relation to a kneeboard thats fixed in vr space when okb is below. Maybe it'll be clearer to talk about modified/unmodified position and orientation or 'fixed vs unfixed to the real world vr playspace'. I know that that'd be more abstract and not as easy to grasp for mew users, but I'm not sure how to go about to achieve a graphic description without losing some correctness for either use case. Maybe you could do an abstract description first and mention motion compensation and additional head turning as use case respectively.

fredemmott commented 1 month ago

thanks, yeah, replacing my real world examples with “your VR play space (room)” or simile seems like the clearest-while-correct way to go. I could also alternatively just say “above is recommended for the game to feel consistent; below may be better for some specialized use cases.” + keeping “try both if unsure”, skipping the details entirely

BuzzteeBear commented 1 month ago

On another note, I found the issue that was causing wrong compensation of the quad layer in iRacing. It was totally my fault. When I implemented that part it was targeted at in-game hud elements and alike, which are usually located against a reference space matching (or even identical to) the one the view is located against. So just applying the inverse of the pose manipulation that's used on the view worked just fine and I thought I'd be done with it. But it's strictly not correct when the ref spaces are different, as we've seen with iRacing, which is using a local space rotated upside down for whatever reason. I really appreciate your input and time spent on this, so thank you very much for caring. P.S.: the use case of 'QuadHands' kinda made it click in my head as to gow to get the pose transformation that I needed to fix that issue, so thanks for that, too Might not be the baddest idea to spend some time looking at the entire conformance suite once I find the time...

BuzzteeBear commented 2 days ago

Fixed in latest release (0.3.7)