Closed brianchirls closed 6 years ago
I need to have a look at the new WebVR API... However, you should be able to achieve this by parenting the camera with an object that position.y = userHeight
, no?
I've looked into this a little further, and there's an additional challenge right now, which is that the standingMatrix is only applied when rendering stereo to the VR display. So that makes it tricky and confusing if you want to render the HMD's view to the screen.
So let's say the camera's parent is at (0, 0, 0) and the user's head is at 1.6m. You do a VR stereo render pass, and WebVRManager
applies the standing matrix (i.e. moves 1.6m up) putting the view in the right place. Then you draw to the screen, but the standing matrix is no longer applied, so the view is rendered from the floor.
Sure, it's possible to write a workaround by transforming the camera for the render pass and then transforming it back. But that's extremely difficult to reason about, easy to get wrong and probably not very efficient.
In my case I try to change the camera position around the scene (for teleport it purposes, for example) but always is rendered on 0,0,0, and you need to add the camera as a child of an object3D in the scene with your desired height to works as expected. But in this case, if you are using https://github.com/borismus/ray-input doesn't work correctly on Daydream/GearVR (and I supposed on Vive/Rift neither) because is imposible to say to the navigator.getGamepads pose that isn't on a different position than 0,0,0.
I'm trying to say with this, that if is related, maybe we need to find a more complex solution in which we could move the camera wherever we want it, not only to solve the userHeight problem.
I've done some more testing and research, and I think I have a handle on this issue.
WebVRManager
is currently setting the camera pose at the last possible moment, presumably to minimize latency. But there are a few reasons why we might need the pose set earlier. As I mentioned above, there's the need to render another view. We also need to know where the head is for ray casting in case of gaze interactions, detecting visibility of objects, etc.
For the sake of correctness and simplicity, I propose an added option that allows rendering with ArrayCamera but disables setting the pose so it can be set with VRControls
as the developer sees fit.
For the time being, this is how you can work around it: https://github.com/mrdoob/three.js/commit/e3cbd3052b20a9235f343446cc23b0211782d3d4#diff-eb152a516883cb17690e595058479f49
But now that I think about it, maybe I broke it because the controllers should also be a child of that object? I'll check it later...
Okay. Fixed, I think... https://github.com/mrdoob/three.js/commit/3cb51d868ee279be373815de592fc072deffc82c
@mrdoob Is that the correct solution? Why use a fixed height in vive examples when you could use standingTransform to get the best accuracy?
I also believe we should the standingMatrix
to fix this issue. If the device doesn't have a stageParameters
we could just set the height as described, but if it has, we should use it.
Otherwise we're forcing the same height for everyone, in my case for example I feel the floor is 20cms or so above my feet.
With R90
, standingMatrix
is available again.
VRControls
has auserHeight
property that places the camera a given height (usually) above the origin in "standing" mode when theVRDisplay
doesn't provide a standing matrix.WebVRManager
doesn't appear to have an equivalent adjustment, so headsets that do not have roomscale (i.e. anything other than Vive) place the head at or near the floor. SinceWebVRManager.getCamera()
sets the position of the camera inside ofWebGLRenderer.render()
it's difficult if not impossible to make that adjustment another way.