IntersectObjects doesn't work in VR mode

Hi,

The function intersectedObjects doesn’t work in VR mode.

I can get intersectedObjects in the normal mode. When VR is enabled that’s doesn’t work.

There is the code :

let loaderAnim = document.getElementById("js-loader");

import * as THREE from "/lib/three.module.js";
import { VRButton } from "/lib/VRButton.js";
import { CSS3DRenderer, CSS3DObject } from "/lib/CSS3DRenderer.js";
import { TransformControls } from "/lib/TransformControls.js";

let polyfill = new WebXRPolyfill();

let isUserInteracting = false,
  lon = 0,
  lat = 0,
  phi = 0,
  theta = 0,
  distance = 50,
  onPointerDownPointerX = 0,
  onPointerDownPointerY = 0,
  onPointerDownLon = 0,
  onPointerDownLat = 0;

let camera, scene, renderer, renderer3d, scene2, control, orbit;
//
let soundStatus = true;
let contenerImgAsset;
let video = document.getElementById("video");
let playContenerButton;
let SceneObjects = [];
let dragging = false;
let object;
let pickHelper;
let time = 0;

//

let raycaster, arrow, x, y;

if (video.readyState === 4) {
  console.log("------- video loaded --------");
  init();
}

function init() {
  let container = document.getElementById("container");

  camera = new THREE.PerspectiveCamera(
    70,
    window.innerWidth / window.innerHeight,
    1,
    2000
  );

  //

  camera.target = new THREE.Vector3(0, 0, 0);
  camera.layers.enable(1); // render left view when no stereo available

  //

  // video

  //  video.play();

  var texture = new THREE.Texture(video);
  texture.generateMipmaps = false;
  texture.minFilter = THREE.NearestFilter;
  texture.magFilter = THREE.NearestFilter;
  texture.format = THREE.RGBFormat;

  setInterval(function () {
    if (video.readyState >= video.HAVE_CURRENT_DATA) {
      texture.needsUpdate = true;
    }
  }, 1000 / 24);

  scene = new THREE.Scene();
  //
  scene.background = new THREE.Color(0x101010);
  ///
  scene2 = new THREE.Scene();

  // left

  var geometry = new THREE.SphereBufferGeometry(500, 60, 40);
  // invert the geometry on the x-axis so that all of the faces point inward
  geometry.scale(-1, 1, 1);

  var material = new THREE.MeshBasicMaterial({ map: texture });

  var mesh = new THREE.Mesh(geometry, material);

  scene.add(mesh);

  // right

  var geometry = new THREE.SphereBufferGeometry(500, 60, 40);
  geometry.scale(-1, 1, 1);

  var material = new THREE.MeshBasicMaterial({ map: texture });

  var mesh = new THREE.Mesh(geometry, material);

  scene.add(mesh);

  //

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.xr.enabled = true;
  renderer.xr.setReferenceSpaceType("local");
  container.appendChild(renderer.domElement);

  //

  renderer3d = new CSS3DRenderer();
  renderer3d.setSize(window.innerWidth, window.innerHeight);
  renderer3d.domElement.style.position = "absolute";
  renderer3d.domElement.style.top = 0;
  document.body.appendChild(renderer3d.domElement);

  //

  window.addEventListener("resize", onWindowResize, false);

  //

  document.addEventListener("pointerdown", onPointerDown, false);
  document.addEventListener("pointermove", onPointerMove, false);
  document.addEventListener("pointerup", onPointerUp, false);

  // VR BUTTON
  let vrContenerButton = document.createElement("DIV");
  vrContenerButton.className = "bottomBarButton";

  let assetsBar = document.getElementById("assets-store");
  let CustomVRButton = VRButton.createButton(renderer);
  CustomVRButton.removeAttribute("style");
  CustomVRButton.remove("hover");

  //

  // Play Button
  playContenerButton = document.createElement("DIV");
  playContenerButton.className = "bottomBarButtonAudio";

  let contenerImgAssetA = document.createElement("A");
  contenerImgAsset = document.createElement("IMG");

  contenerImgAsset.addEventListener("click", muteOrUmuteVideoButton, false);

  contenerImgAsset.src = "/assets/Son Off.svg";
  contenerImgAsset.style.marginTop = "4px";
  contenerImgAsset.style.width = "30px";
  contenerImgAsset.id = "soundPicto";
  contenerImgAsset.style.verticalAlign = "middle";
  contenerImgAsset.style.position = "relative";

  contenerImgAssetA.appendChild(contenerImgAsset);
  playContenerButton.appendChild(contenerImgAssetA);

  //

  CustomVRButton.style.background = "white";
  CustomVRButton.style.border = "0px solid black";
  CustomVRButton.style.color = "black";
  CustomVRButton.style.borderRadius = "0px";
  CustomVRButton.style.fontFamily = "Josefin Sans";
  CustomVRButton.style.textTransform = "lowercase";
  CustomVRButton.style.fontSize = "18px";
  CustomVRButton.style.paddingLeft = "50px";
  CustomVRButton.style.verticalAlign = "middle";
  CustomVRButton.style.backgroundImage = "url('/assets/vr_headset.svg')";
  CustomVRButton.style.backgroundRepeat = "no-repeat";
  CustomVRButton.style.backgroundPosition = "left";
  CustomVRButton.style.backgroundSize = "40px 40px";

  //

  let contenerDIV = document.createElement("DIV");
  contenerDIV.style.position = "relative";

  //

  //vrContenerButton.appendChild(contenerA);
  vrContenerButton.appendChild(CustomVRButton);

  //

  contenerDIV.appendChild(vrContenerButton);
  contenerDIV.appendChild(playContenerButton);
  assetsBar.appendChild(contenerDIV);

  //

  document.addEventListener("keydown", onKeyDown, false); // switch between orthographic and perspective camera

  //

  document.body.appendChild(assetsBar);

  let VRbutton = document.getElementById("VRButton");

  VRbutton.addEventListener(
    "click",
    function () {
      playVideo();
    },
    false
  );

  //

  control = new TransformControls(camera, renderer3d.domElement);

  control.addEventListener("dragging-changed", function (event) {
    //
    dragging = !dragging;
    console.log(object);
    //
  });

  // google street view button

  // --------- button 1

  let streetButton = document.createElement("A");
  streetButton.className = "d3DButton";
  streetButton.href = "/01/01.html";

  //

  let arrowA = document.createElement("A");
  arrowA.className = "arrowA";
  arrowA.text = "⬆︎";

  //

  let textContenerButton = document.createElement("A");
  //textContenerButton.text = "Go there";

  streetButton.appendChild(arrowA);
  streetButton.appendChild(textContenerButton);

  //SceneObjects.push(object);

  object = new CSS3DObject(streetButton);
  object.position.copy(
    new THREE.Vector3(901.1090075962194, -269.071755544908, -153.90012663859025)
  );
  object.rotation.copy(new THREE.Euler(0, 90 * THREE.MathUtils.DEG2RAD, 0));

  //
  scene2.add(object);
  //
  let meshGeo = new THREE.CylinderBufferGeometry(50, 50, 10);

  let meshMaterial = new THREE.MeshBasicMaterial({
    color: 0x03fbb3,
    opacity: 1,
    transparent: false
  });

  let meshLamberMaterial = new THREE.MeshLambertMaterial({
    color: 0x03fbb3,
    opacity: 1,
    transparent: false
  });

  let mesh3 = new THREE.Mesh(meshGeo, meshLamberMaterial);
  mesh3.castShadow = true; //default is false
  mesh3.receiveShadow = true; //default
  mesh3.position.x = 300;
  mesh3.position.y = -100;
  mesh3.position.y = -160;

  /* 
  control.attach(mesh3);
  scene.add(control); */
  //
  scene.add(mesh3);
  //

  SceneObjects.push(mesh3);

  //
  raycaster = new THREE.Raycaster();

  video.play();
  loaderAnim.remove();
}

function muteOrUmuteVideoButton(e) {
  e.preventDefault();

  console.log("function muteOrUmuteVideoButton");

  //

  let item = e.target;

  //
  if (soundStatus === true) {
    item.src = "/assets/Son On.svg";
    video.muted = false;
    soundStatus = false;
    playContenerButton.className = "bottomBarButtonAudioOn";
  } else if (soundStatus === false) {
    item.src = "/assets/Son Off.svg";
    video.muted = true;
    soundStatus = true;
    playContenerButton.className = "bottomBarButtonAudio ";
  }
}

function playVideo() {
  video.play();
  let item = document.getElementById("soundPicto");
  item.src = "/assets/Son Off.svg";
  video.muted = false;
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer3d.setSize(window.innerWidth, window.innerHeight);
}
console.log(SceneObjects);

renderer.setAnimationLoop(function () {
  time *= 0.001;

  renderer.setSize(window.innerWidth, window.innerHeight);

  lat = Math.max(-85, Math.min(85, lat));
  phi = THREE.MathUtils.degToRad(90 - lat);
  theta = THREE.MathUtils.degToRad(lon);

  camera.position.x = distance * Math.sin(phi) * Math.cos(theta);
  camera.position.y = distance * Math.cos(phi);
  camera.position.z = distance * Math.sin(phi) * Math.sin(theta);

  camera.lookAt(camera.target);
  raycaster.setFromCamera({ x: 0, y: 0 }, camera);

  const intersectedObjects = raycaster.intersectObjects(SceneObjects);

  if (intersectedObjects.length) {
    console.log(intersectedObjects);
    console.log("get one object");
  }

  renderer.render(scene, camera);
  renderer3d.render(scene2, camera);
});

function onPointerDown(event) {
  if (dragging === false) {
    isUserInteracting = true;

    onPointerDownPointerX = event.clientX;
    onPointerDownPointerY = event.clientY;

    onPointerDownLon = lon;
    onPointerDownLat = lat;
  }
}

function onPointerMove(event) {
  if (dragging === false) {
    if (isUserInteracting === true) {
      lon = (onPointerDownPointerX - event.clientX) * 0.1 + onPointerDownLon;
      lat = (onPointerDownPointerY - event.clientY) * 0.1 + onPointerDownLat;
    }
  }
}

function onPointerUp() {
  if (dragging === false) {
    isUserInteracting = false;
  }
}

function onKeyDown(event) {
  switch (event.keyCode) {
    case 81: // Q
      control.setSpace(control.space === "local" ? "world" : "local");
      break;
    case 16: // Shift
      control.setTranslationSnap(100);
      control.setRotationSnap(THREE.MathUtils.degToRad(15));
      control.setScaleSnap(0.25);
      break;
    case 87: // W
      control.setMode("translate");
      break;
    case 69: // E
      control.setMode("rotate");
      break;
    case 82: // R
      control.setMode("scale");
      break;
    case 67: // C
      const position = currentCamera.position.clone();
      currentCamera = currentCamera.isPerspectiveCamera
        ? cameraOrtho
        : cameraPersp;
      currentCamera.position.copy(position);
      orbit.object = currentCamera;
      control.camera = currentCamera;
      currentCamera.lookAt(orbit.target.x, orbit.target.y, orbit.target.z);
      onWindowResize();
      break;
    case 86: // V
      const randomFoV = Math.random() + 0.1;
      const randomZoom = Math.random() + 0.1;
      cameraPersp.fov = randomFoV * 160;
      cameraOrtho.bottom = -randomFoV * 500;
      cameraOrtho.top = randomFoV * 500;
      cameraPersp.zoom = randomZoom * 5;
      cameraOrtho.zoom = randomZoom * 5;
      onWindowResize();
      break;
    case 187:
    case 107: // +, =, num+
      control.setSize(control.size + 0.1);
      break;
    case 189:
    case 109: // -, _, num-
      control.setSize(Math.max(control.size - 0.1, 0.1));
      break;
    case 88: // X
      control.showX = !control.showX;
      break;
    case 89: // Y
      control.showY = !control.showY;
      break;
    case 90: // Z
      control.showZ = !control.showZ;
      break;
    case 32: // Spacebar
      control.enabled = !control.enabled;
      break;
  }
}

I don’t think you can get this to work. When using setFromCamera(), the method expects a projection matrix which is actually used for rendering. This is not true during a XR session. WebXRManager ensure to copy the tracked camera’s transformation (its world matrix) to the scene’s camera. However, this is not possible with the view frustum (projection matrix) since in VR the total frustum is a combination of two separate projection matrices (left and right eye). Hence, the call of unproject() which happens inside setFromCamera() will not properly work.

If you just want to shoot a ray from the viewing direction of the user’s headset, consider to do this instead of using setFromCamera():

raycaster.ray.origin.setFromMatrixPosition( camera.matrixWorld );
raycaster.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
1 Like

Thank you for your feedback.

I changed the

setFromCamera()

to what you said but it doesn’t work anyway. I’m not able to find the problem…
Your code is working when the VR is not enabled. But in VR I get nothing from the web console (browser).

you go there if needed :

there is the updated code :

let loaderAnim = document.getElementById("js-loader");

import * as THREE from "/lib/three.module.js";
import { VRButton } from "/lib/VRButton.js";
import { CSS3DRenderer, CSS3DObject } from "/lib/CSS3DRenderer.js";
import { TransformControls } from "/lib/TransformControls.js";

let polyfill = new WebXRPolyfill();

let isUserInteracting = false,
  lon = 0,
  lat = 0,
  phi = 0,
  theta = 0,
  distance = 50,
  onPointerDownPointerX = 0,
  onPointerDownPointerY = 0,
  onPointerDownLon = 0,
  onPointerDownLat = 0;

let camera, scene, renderer, renderer3d, scene2, control, orbit;
//
let soundStatus = true;
let contenerImgAsset;
let video = document.getElementById("video");
let playContenerButton;
let SceneObjects = [];
let dragging = false;
let object;
let pickHelper;
let time = 0;

//

let raycaster, arrow, x, y;

if (video.readyState === 4) {
  console.log("------- video loaded --------");
  init();
}

function init() {
  let container = document.getElementById("container");

  camera = new THREE.PerspectiveCamera(
    70,
    window.innerWidth / window.innerHeight,
    1,
    2000
  );

  //

  camera.target = new THREE.Vector3(0, 0, 0);
  camera.layers.enable(1); // render left view when no stereo available

  //

  // video

  //  video.play();

  var texture = new THREE.Texture(video);
  texture.generateMipmaps = false;
  texture.minFilter = THREE.NearestFilter;
  texture.magFilter = THREE.NearestFilter;
  texture.format = THREE.RGBFormat;

  setInterval(function () {
    if (video.readyState >= video.HAVE_CURRENT_DATA) {
      texture.needsUpdate = true;
    }
  }, 1000 / 24);

  scene = new THREE.Scene();
  //
  scene.background = new THREE.Color(0x101010);
  ///
  scene2 = new THREE.Scene();

  // left

  var geometry = new THREE.SphereBufferGeometry(500, 60, 40);
  // invert the geometry on the x-axis so that all of the faces point inward
  geometry.scale(-1, 1, 1);

  var material = new THREE.MeshBasicMaterial({ map: texture });

  var mesh = new THREE.Mesh(geometry, material);

  scene.add(mesh);

  // right

  var geometry = new THREE.SphereBufferGeometry(500, 60, 40);
  geometry.scale(-1, 1, 1);

  var material = new THREE.MeshBasicMaterial({ map: texture });

  var mesh = new THREE.Mesh(geometry, material);

  scene.add(mesh);

  //

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.xr.enabled = true;
  renderer.xr.setReferenceSpaceType("local");
  container.appendChild(renderer.domElement);

  //

  renderer3d = new CSS3DRenderer();
  renderer3d.setSize(window.innerWidth, window.innerHeight);
  renderer3d.domElement.style.position = "absolute";
  renderer3d.domElement.style.top = 0;
  document.body.appendChild(renderer3d.domElement);

  //

  window.addEventListener("resize", onWindowResize, false);

  //

  document.addEventListener("pointerdown", onPointerDown, false);
  document.addEventListener("pointermove", onPointerMove, false);
  document.addEventListener("pointerup", onPointerUp, false);

  // VR BUTTON
  let vrContenerButton = document.createElement("DIV");
  vrContenerButton.className = "bottomBarButton";

  let assetsBar = document.getElementById("assets-store");
  let CustomVRButton = VRButton.createButton(renderer);
  CustomVRButton.removeAttribute("style");
  CustomVRButton.remove("hover");

  //

  // Play Button
  playContenerButton = document.createElement("DIV");
  playContenerButton.className = "bottomBarButtonAudio";

  let contenerImgAssetA = document.createElement("A");
  contenerImgAsset = document.createElement("IMG");

  contenerImgAsset.addEventListener("click", muteOrUmuteVideoButton, false);

  contenerImgAsset.src = "/assets/Son Off.svg";
  contenerImgAsset.style.marginTop = "4px";
  contenerImgAsset.style.width = "30px";
  contenerImgAsset.id = "soundPicto";
  contenerImgAsset.style.verticalAlign = "middle";
  contenerImgAsset.style.position = "relative";

  contenerImgAssetA.appendChild(contenerImgAsset);
  playContenerButton.appendChild(contenerImgAssetA);

  //

  CustomVRButton.style.background = "white";
  CustomVRButton.style.border = "0px solid black";
  CustomVRButton.style.color = "black";
  CustomVRButton.style.borderRadius = "0px";
  CustomVRButton.style.fontFamily = "Josefin Sans";
  CustomVRButton.style.textTransform = "lowercase";
  CustomVRButton.style.fontSize = "18px";
  CustomVRButton.style.paddingLeft = "50px";
  CustomVRButton.style.verticalAlign = "middle";
  CustomVRButton.style.backgroundImage = "url('/assets/vr_headset.svg')";
  CustomVRButton.style.backgroundRepeat = "no-repeat";
  CustomVRButton.style.backgroundPosition = "left";
  CustomVRButton.style.backgroundSize = "40px 40px";

  //

  let contenerDIV = document.createElement("DIV");
  contenerDIV.style.position = "relative";

  //

  //vrContenerButton.appendChild(contenerA);
  vrContenerButton.appendChild(CustomVRButton);

  //

  contenerDIV.appendChild(vrContenerButton);
  contenerDIV.appendChild(playContenerButton);
  assetsBar.appendChild(contenerDIV);

  //

  document.addEventListener("keydown", onKeyDown, false); // switch between orthographic and perspective camera

  //

  document.body.appendChild(assetsBar);

  let VRbutton = document.getElementById("VRButton");

  VRbutton.addEventListener(
    "click",
    function () {
      playVideo();
    },
    false
  );

  //

  control = new TransformControls(camera, renderer3d.domElement);

  control.addEventListener("dragging-changed", function (event) {
    //
    dragging = !dragging;
    console.log(object);
    //
  });

  // google street view button

  // --------- button 1

  let streetButton = document.createElement("A");
  streetButton.className = "d3DButton";
  streetButton.href = "/01/01.html";

  //

  let arrowA = document.createElement("A");
  arrowA.className = "arrowA";
  arrowA.text = "⬆︎";

  //

  let textContenerButton = document.createElement("A");
  //textContenerButton.text = "Go there";

  streetButton.appendChild(arrowA);
  streetButton.appendChild(textContenerButton);

  //SceneObjects.push(object);

  object = new CSS3DObject(streetButton);
  object.position.copy(
    new THREE.Vector3(901.1090075962194, -269.071755544908, -153.90012663859025)
  );
  object.rotation.copy(new THREE.Euler(0, 90 * THREE.MathUtils.DEG2RAD, 0));

  //
  scene2.add(object);
  //
  let meshGeo = new THREE.CylinderBufferGeometry(50, 50, 10);

  let meshMaterial = new THREE.MeshBasicMaterial({
    color: 0x03fbb3,
    opacity: 1,
    transparent: false
  });

  let meshLamberMaterial = new THREE.MeshLambertMaterial({
    color: 0x03fbb3,
    opacity: 1,
    transparent: false
  });

  let mesh3 = new THREE.Mesh(meshGeo, meshLamberMaterial);
  mesh3.castShadow = true; //default is false
  mesh3.receiveShadow = true; //default
  mesh3.position.x = 300;
  mesh3.position.y = -100;
  mesh3.position.y = -160;

  /* 
  control.attach(mesh3);
  scene.add(control); */
  //
  scene.add(mesh3);
  //

  SceneObjects.push(mesh3);

  //
  raycaster = new THREE.Raycaster();

  video.play();
  loaderAnim.remove();
}

function muteOrUmuteVideoButton(e) {
  e.preventDefault();

  console.log("function muteOrUmuteVideoButton");

  //

  let item = e.target;

  //
  if (soundStatus === true) {
    item.src = "/assets/Son On.svg";
    video.muted = false;
    soundStatus = false;
    playContenerButton.className = "bottomBarButtonAudioOn";
  } else if (soundStatus === false) {
    item.src = "/assets/Son Off.svg";
    video.muted = true;
    soundStatus = true;
    playContenerButton.className = "bottomBarButtonAudio ";
  }
}

function playVideo() {
  video.play();
  let item = document.getElementById("soundPicto");
  item.src = "/assets/Son Off.svg";
  video.muted = false;
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer3d.setSize(window.innerWidth, window.innerHeight);
}
console.log(SceneObjects);

renderer.setAnimationLoop(function () {
  time *= 0.001;

  renderer.setSize(window.innerWidth, window.innerHeight);

  lat = Math.max(-85, Math.min(85, lat));
  phi = THREE.MathUtils.degToRad(90 - lat);
  theta = THREE.MathUtils.degToRad(lon);

  camera.position.x = distance * Math.sin(phi) * Math.cos(theta);
  camera.position.y = distance * Math.cos(phi);
  camera.position.z = distance * Math.sin(phi) * Math.sin(theta);

  camera.lookAt(camera.target);

  raycaster.ray.origin.setFromMatrixPosition(camera.matrixWorld);
  raycaster.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);

  const intersectedObjects = raycaster.intersectObjects(SceneObjects);

  if (intersectedObjects.length) {
    console.log(intersectedObjects);
    console.log("get one object");
  }

  renderer.render(scene, camera);
  renderer3d.render(scene2, camera);
});

function onPointerDown(event) {
  if (dragging === false) {
    isUserInteracting = true;

    onPointerDownPointerX = event.clientX;
    onPointerDownPointerY = event.clientY;

    onPointerDownLon = lon;
    onPointerDownLat = lat;
  }
}

function onPointerMove(event) {
  if (dragging === false) {
    if (isUserInteracting === true) {
      lon = (onPointerDownPointerX - event.clientX) * 0.1 + onPointerDownLon;
      lat = (onPointerDownPointerY - event.clientY) * 0.1 + onPointerDownLat;
    }
  }
}

function onPointerUp() {
  if (dragging === false) {
    isUserInteracting = false;
  }
}

function onKeyDown(event) {
  switch (event.keyCode) {
    case 81: // Q
      control.setSpace(control.space === "local" ? "world" : "local");
      break;
    case 16: // Shift
      control.setTranslationSnap(100);
      control.setRotationSnap(THREE.MathUtils.degToRad(15));
      control.setScaleSnap(0.25);
      break;
    case 87: // W
      control.setMode("translate");
      break;
    case 69: // E
      control.setMode("rotate");
      break;
    case 82: // R
      control.setMode("scale");
      break;
    case 67: // C
      const position = currentCamera.position.clone();
      currentCamera = currentCamera.isPerspectiveCamera
        ? cameraOrtho
        : cameraPersp;
      currentCamera.position.copy(position);
      orbit.object = currentCamera;
      control.camera = currentCamera;
      currentCamera.lookAt(orbit.target.x, orbit.target.y, orbit.target.z);
      onWindowResize();
      break;
    case 86: // V
      const randomFoV = Math.random() + 0.1;
      const randomZoom = Math.random() + 0.1;
      cameraPersp.fov = randomFoV * 160;
      cameraOrtho.bottom = -randomFoV * 500;
      cameraOrtho.top = randomFoV * 500;
      cameraPersp.zoom = randomZoom * 5;
      cameraOrtho.zoom = randomZoom * 5;
      onWindowResize();
      break;
    case 187:
    case 107: // +, =, num+
      control.setSize(control.size + 0.1);
      break;
    case 189:
    case 109: // -, _, num-
      control.setSize(Math.max(control.size - 0.1, 0.1));
      break;
    case 88: // X
      control.showX = !control.showX;
      break;
    case 89: // Y
      control.showY = !control.showY;
      break;
    case 90: // Z
      control.showZ = !control.showZ;
      break;
    case 32: // Spacebar
      control.enabled = !control.enabled;
      break;
  }
}

I have added a ArrowHelper in the

init()

function but it doesn’t work also

  arrow = new THREE.ArrowHelper(
    raycaster.ray.direction
      .set(0, 0, -1)
      .transformDirection(camera.matrixWorld),
    raycaster.ray.origin.setFromMatrixPosition(camera.matrixWorld),
    100,
    Math.random() * 0xffffff
  );

It seems you have changed your code to something that does not make sense. When using XR, it’s not valid to change the transformation of the camera. You are doing this right now in your render loop.

Besides, using CSS3DRenderer is also not valid in XR since it’s not possible to render HTML/CSS elements in a VR session.

First, I have added this to

init() function

:

  raycaster.ray.origin.setFromMatrixPosition(camera.matrixWorld);
  raycaster.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);

But it doesn’t work.

Secondly, I have moved this code to the render function. But it doesn’t work also.

Thirdly, I have added a ArrowHelper() to help me to see the raycast. But anyway It doesn’t work.
The ArrowHelper doesn’t moved during the VR session… I don’t understand this behaviour…

Thank you for you reply.

I’ve reduced your codesandbox a bit to easier debug the issue. With this version, I can successfully print intersection points on the console.

BTW: It seems you have many elements in your scene which are confusing right now. For example you add two spheres with the video although this has no effect in context of WebXR. Or you define a target property which does not exists for a camera object. It does also not make sense to use nearest texture filtering for video textures (since they are all color textures and filtering won’t break the texel’s value).

Thank you. That’s kind of you to help me out.

I started the project from an example of the documentation.

There is the link :

The nearest filtering is probably used for better performance. However, I don’t get the usage of two spheres :thinking:.

Answer right here: Examples: Remove obsolete code in webxr_vr_video. by Mugen87 · Pull Request #20571 · mrdoob/three.js · GitHub