The neck model code assumes it is given an orientation that transforms coordinates from a reference "head space" into world coordinates. However the code path that provides the result for CardboardHeadTracker_getPose passes an inverted orientation ("view sense", ie a from-world-to-view transform) into the neck model.
The result is the translation part of the result of getPose is incorrect - the neck model is correct, but applied to the inverted orientation just does the wrong thing; it doesn't just return a fully inverted "view sense" pose.
This came up when I discovered the neck model was doing weird things in Chrome's immersive-vr mode. There's a full write up of that, and some test pages for logging and visualising the poses, in a repo here:
https://github.com/tangobravo/chrome-cardboard-neck-model-bug?tab=readme-ov-file
In the Chrome bug, the Chromium team tried properly inverting the result from the getPose, but that is still incorrect - I added some options to the visualizer to demo the effect of this too.
As it is a Cardboard SDK bug, this seems the right place to fix it. I'm happy to contribute something, but would be good to discuss the way forward, as this inverted orientation, broken position, has been present in the Cardboard SDK since the original open-source release. The Unity plugin has it's own utilities to compute the pose (which re-apply the neck model themselves on the correct orientation by the looks of it; I haven't verified). The native samples treat the matrix from getPose as a "view" matrix in their shader setup.
There's also comments mentioning "row major" in the Unity wrapper which is incorrect, but was probably someone struggling for an explanation as to why they had to invert the orientation part.
Three options I can see:
- Make getPose report the "view matrix" sense of the pose correctly - any callers that assumed they needed to invert it would suddenly start working properly without code changes from them. But the function name still feels wrong
- Make getPose return the usual sense of "pose of head in the world" - ie transform from head to world - that's the sense both Unity and WebXR require and matches the docs better in my view. Would need users to update their code though.
- Add a new
getHeadPose that does 2, existing users of getPose would retain previous behaviour with incorrect position. Ask Chromium to migrate to the new function.
The neck model code assumes it is given an orientation that transforms coordinates from a reference "head space" into world coordinates. However the code path that provides the result for
CardboardHeadTracker_getPosepasses an inverted orientation ("view sense", ie a from-world-to-view transform) into the neck model.The result is the translation part of the result of getPose is incorrect - the neck model is correct, but applied to the inverted orientation just does the wrong thing; it doesn't just return a fully inverted "view sense" pose.
This came up when I discovered the neck model was doing weird things in Chrome's
immersive-vrmode. There's a full write up of that, and some test pages for logging and visualising the poses, in a repo here:https://github.com/tangobravo/chrome-cardboard-neck-model-bug?tab=readme-ov-file
In the Chrome bug, the Chromium team tried properly inverting the result from the getPose, but that is still incorrect - I added some options to the visualizer to demo the effect of this too.
As it is a Cardboard SDK bug, this seems the right place to fix it. I'm happy to contribute something, but would be good to discuss the way forward, as this inverted orientation, broken position, has been present in the Cardboard SDK since the original open-source release. The Unity plugin has it's own utilities to compute the pose (which re-apply the neck model themselves on the correct orientation by the looks of it; I haven't verified). The native samples treat the matrix from getPose as a "view" matrix in their shader setup.
There's also comments mentioning "row major" in the Unity wrapper which is incorrect, but was probably someone struggling for an explanation as to why they had to invert the orientation part.
Three options I can see:
getHeadPosethat does 2, existing users of getPose would retain previous behaviour with incorrect position. Ask Chromium to migrate to the new function.