1

I'm trying to make a cube mesh to be always positioned in front of the XR camera.

No matter how I move my phone camera, the cube should appear right in front of the camera showing only one side of the cube.

Firstly, I added a cube mesh to the scene in the beginning:

material = new THREE.MeshLambertMaterial({ color: 0x9797CE });
box = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), material);
box.position.set(0, 0, -3);
scene.add(box);

And then tried to draw the box in front of the XR camera:

function animate() {
    let xrCamera = renderer.xr.getCamera(camera);
    box.position.set(xrCamera.position.x, xrCamera.position.y, xrCamera.position.z - 3);
    box.rotation.set(xrCamera.rotation.x, xrCamera.rotation.y, xrCamera.rotation.z);
    renderer.render(scene, camera);
}

When I run the code, the cube appears in front of my phone camera.

But when I rotate my phone, the cube rotates itself in the same position not following the camera.

I also tried xrCamera.add(box) but it doesn't seem to work.

How can I correctly make the cube always appear still in front of the XR camera?

2 Answers 2

1

It's important to know that currently (r115) the transformation properties position, rotation and scale as well as the local matrix of the XR camera are not updated.

So instead of adding the box to xrCamera, add it to camera. Besides, keep in mind that WebXRManager.getCamera() is intended for internal use only and no part of the public API.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for your answer. But if I console.log the camera position and rotation, it just outputs {x: 0, y: 0, z: 0}. whereas the xrCamera seems to output the current phone camera's position and rotation in the AR world.
Nevermind, If I add the box to the camera, then it works as expected! But I still don't understand how it can work.
There is currently an issue in the lib that prevents that position, rotation and scale are correctly set, see github.com/mrdoob/three.js/issues/18448. IMO, adding box as a child to camera is the best approach for now.
I hope we can fix this issue soon so it's possible to work with position, rotation and scale instead. However, always work with the camera that you create in your scene. Please do no use WebXRManager.getCamera()^^.
You can extract the world position, quaternion and scale by using Matrix4.decompose(). So camera.matrixWorld.decompose( position, quaternion, scale );. In this code snippet, camera is your normal scene camera.
|
0

I have been solving a similar problem. I needed to get a point in front of camera using aframe API. But the challege was when the experience were on VR mode(fullscreen) and playing on movile or headset. In this context the management of the current camera is absolutely controlled by WebXR. With WebXR THREE applies headset pose to the object3D internally.

You only can use the matrixWorld of the three camera to access the camera world reference data, other properties or methods are not correct. In the case of aframe you must access to the object3D of the aframe camera entity and manage its matrixWorld. It is the only method to get correct information of the position/rotation/scale of the camera that it is move by the sensors of a movile or of a AR/VR goggles when the play is on VR/AR mode.

I use to get the in front of Camera Position With WebXR Headset Pose:

const distanceFromCamera = 250;  // the depth in the screen, what ever you need
const inFrontOfCameraPosition = new AFRAME.THREE.Vector3( 0, 0, -distanceFromCamera );

const threeSceneCamera = <THREE.PerspectiveCamera>AFRAME.scenes[0].camera;
inFrontOfCameraPosition.applyMatrix4( threeSceneCamera.matrixWorld );

return { x: inFrontOfCameraPosition.x, y: inFrontOfCameraPosition.y, z: inFrontOfCameraPosition.z };

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.