VR Mode but without head movement

For my application, I need to present a fixed visual stimulus to the user (ie. when user moves their head, the stimulus remains at the same position in the field of view). In other words, I need my phone to be like a 3D display rather than a headset.

Any ideas on how to achieve this? I found something similar for Unity but can’t find three.js help (https://forum.unity.com/threads/completely-disable-position-tracking.450644/).

Here’s my code

import * as THREE from "./three/build/three.module.js";
import {VRButton} from "./three/examples/jsm/webxr/VRButton.js";

  //GLOBALS
  const distance = 0.3;
  const height = 1.6;

  //Canvas and Renderer
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});
  renderer.xr.enabled = true;
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );
  document.body.appendChild(VRButton.createButton(renderer));

  //Scene setup
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000);

  //Camera
  const fov = 50;
  const aspect = window.innerWidth / window.innerHeight;
  const near = 0.1;
  const far = 10;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, height, 0);

  //Make plane
  const screen_height = 2*distance*Math.tan(fov/2*Math.PI/180);
  const plane_geometry = new THREE.PlaneGeometry(screen_height, screen_height);
  const plane_material = new THREE.MeshStandardMaterial({color:0xffffff})
  const plane = new THREE.Mesh(plane_geometry, plane_material);
  scene.add(plane);
  plane.position.set(0, height, -distance);
  plane.layers.set(2)

  //Initialise light
  function make_light(s, i, xangle, yangle, layer=0) {
    const size = s;
    const intensity = i;
    const x = distance*Math.tan(xangle*Math.PI/180);
    const y = distance*Math.tan(yangle*Math.PI/180);
    const light = new THREE.SpotLight(0xffffff);
    light.physicallyCorrectLights = true;
    light.intensity = intensity;
    light.angle = 2*Math.atan(size/(2*distance));
    scene.add(light);
    light.position.set(x,height+y,0);
    scene.add(light.target);
    light.target.position.set(x, height+y, -distance);
    light.layers.set(2);
    return light
  }

  const test = make_light(0.1, 100, 0, 0, 1);

@abc_22413

as an example the little pink cube (mesh) in the center of screen is fixed realtive to the cameras rotation and position,
probably the most hacky way but it was done like this…

 mesh = new THREE.Mesh( geometry, material );
 mesh.position.set( 0, 0, -4);
 meshhold = new THREE.Object3D();
 scene.add(meshhold);
 meshhold.add(mesh);

and in update loop

meshhold.position.set(camera.position.x, camera.position.y, camera.position.z) ;
meshhold.rotation.set(camera.rotation.x, camera.rotation.y, camera.rotation.z) ;

so there’s a holder (meshholder) for the mesh that has it’s position and rotation set in update loop to the camera’s rotation and postition, then the pink cube (mesh) is added to the holder (meshholder) so that the mesh is always in the feild of view…

really hacky but can work till you find a better solution?

safe