-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Description
Description
We’re having an issue with using the lookAt() function to try to direct the camera position in WebXR. We are not sure if this is a bug in ThreeJS code or that we are not doing this properly or misunderstanding what the expected behavior should be, but it seems like a bug so we figured we’d file it here and see what the response is.
The goal is to position the viewing direction for the user when they are in XR mode. Our understanding of how to do this now is to create a parent object of the camera (which we are calling cameraRig) as a THREE.Group and then add() the camera to it. Then when we want to move the XR camera in the scene, we change the position of the cameraRig, which essentially moves the camera as well without conflicting with the user’s own movement of the headset. This has mostly been working well for us to this point.
There have been some complications with the fact that the scene seems to be oriented by default where the origin is the current location of the user’s headset. That is, if the user enters the scene, then moves the headset 1 meter in the x direction, and we want to move the cameraRig back to the original spot they started, we cannot move it to (0, 0, 0) (the absolute coordinates of the spot we want them to be at), as that will keep the positioning the same. Instead we have to move it to (-1, 0, 0) since relative to the new position of the headset, that is now how to get it back to the origin of the scene. We have accounted for this by adding offsets into our code for the positional movements of the headset when this occurs, which fixes the issue, though it does make for more complicated code.
However, we have encountered a problem when doing this and then using the lookAt() function on the cameraRig. If a user enters XR mode, moves the headset, and then we try to lookAt() a specific point, the user’s view seems to come from a different position. We were under the impression that lookAt() should only change the orientation of the camera, not the positioning of it, but it seems to in this case. We have even tried to set the quaternion directly and avoid the lookAt() function to achieve similar functionality, but this also has the same effect (assuming we are doing this correctly, as that code/math is more complicated and so we could easily have errors in how we’re doing it).
Reproduction steps
We have produced a minimal reproduction of this (linked below). If you run it with a WebXR emulator extension in a browser, you should see the following behavior:
- Click Enter VR. You are placed inside a green cube.
- Type the letter B. It should position you in such a way that you can see red and blue boxes.
- Type the letter L. It should then have you look toward the pink box.
- Reload the page
- Click Enter VR
- Use the emulator to move the headset a significant amount in any direction.
- Type the letter B. It should once again position you in such a way that you can see red and blue boxes as before, since we are accounting for the headset movement as an offset here when we reposition the
cameraRig. - Type the letter L. It is running the exact same code as before, but this time the view is entirely different from before, not just the direction but also the positioning of where the camera is viewing things from.
Again, in our experimentation with the full code we’re working on, this happens any way we try to set the orientation of the cameraRig after the headset has moved. It is entirely possible we are misunderstanding something, but think it might be an issue with how the orientation transform is being applied when the coordinates are relative to the headset and not relative to a stable world origin. But after a fair amount of experimentation, we cannot figure out another way to orient the camera in the direction we want (toward a specific set of coordinates) that doesn’t also change the location of where the camera seems to be looking from.
Code
The relevant portion of the code that is performing this change:
const targetPoint = new THREE.Vector3(5, 1.6, -1);
cameraRig.lookAt(targetPoint);
cameraRig.updateMatrixWorld(true);Live example
https://codepen.io/bencf/pen/ZYzbxQe
Screenshots
No response
Version
r171
Device
Desktop
Browser
Chrome
OS
MacOS