Search code examples
cameraaframeraycastingcursors

How to switch from mouse to gaze or gaze to mouse cursor when going respectively inside or outside VR mode?


What will I have?

I'll easily toggle the mouse events from the mouse cursor when not in VR mode to gaze cursors in VR mode. See also pseudo code below:

Example 1
scene.addEventListener('enter-vr', function() {
    // use gaze cursors to toggle mouse events
});

scene.addEventListener('exit-vr', function() {
    // use mouse cursor to toggle mouse events
});

Why?

By research I've seen by people that uses VR for the first time, preferences the mouse cursors. Entering VR mode, this cursor isn't available and by further research, the gaze cursor is the best option. With controllers from the HTC, Oculus, GearVR and Daydream aren't users not conversant to use it.

Conclusion:

  • Inside VR mode: the gaze cursors is the best option.
  • Outside VR mode: the mouse cursors is the best option.

What I've made

Research

I've found inside the documentation to change the camera:

Changing the Active Camera

When the active property gets toggled, the component will notify the camera system to change the current camera used by the renderer:

var secondCameraEl = document.querySelector('#second-camera');
secondCameraEl.setAttribute('camera', 'active', true);

My code

Here is my code I've made

Example 2

var scene = document.getElementById('scene');

scene.addEventListener('enter-vr', function() {
  var secondCameraEl = document.querySelector('#vr-camera');
  secondCameraEl.setAttribute('camera', 'active', true);
});

scene.addEventListener('exit-vr', function() {
  var fistCameraEl = document.querySelector('#pc-camera');
  fistCameraEl.setAttribute('camera', 'active', true);
});

var box = document.getElementById('box');

box.addEventListener('click', function() {
  alert('click');
});
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>

<a-scene id="scene">
  <a-box id="box" class="clickable" position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>

  <a-entity id="camera">
    <a-camera id="vr-camera">
      <a-entity position="0 0 -1" geometry="primitive: ring; radiusOuter: 0.07;radiusInner: 0.05;" material="color: red; shader: flat" cursor="maxDistance: 1; fuse: true" raycaster="objects: .clickable">
        <a-animation begin="click" easing="ease-in" attribute="scale" fill="backwards" from="0.1 0.1 0.1" to="1 1 1" dur="150"></a-animation>
        <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="forwards" from="1 1 1" to="0.1 0.1 0.1" dur="1500"></a-animation>
      </a-entity>
    </a-camera>

    <a-camera id="pc-camera" active="true"></a-camera>
  </a-entity>
</a-scene>

Click on cardboard icon to enter VR, pers Escape to exit VR.

Problems and working things

So you can see there are several errors inside my code:

  1. The fist camera that's active is #vr-camera. This must be #pc-camera
  2. When you exit VR, the #pc-camera doesn't trigger mouse events from the mouse pointer.
  3. The cursor of #vr-camera stays visible when going outside VR mode.
  4. See point 7.

This is working:

  1. Change the camera back to #pc-camera when exit VR.
  2. Gaze cursor of the #vr-camera.

Question

Is it possible to switch the cursors (gaze ↔ mouse) dependent if you're in VR mode or not?

Update

Take @Piotr answer using just one camera and change the property fuse to true when enter VR and change to false when exit VR. From his anwser I've made code below.

Example 3

var scene = document.getElementById('scene');
var camera = document.querySelector('#camera')[0];

scene.addEventListener('enter-vr', function() {
  camera.setAttribute('cursor', 'maxDistance: 1; fuse: true');
});

scene.addEventListener('exit-vr', function() {
  camera.setAttribute('cursor', 'maxDistance: 1; fuse: false');
});

var box = document.getElementById('box');

box.addEventListener('click', function() {
  alert('click');
});
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>

<a-scene id="scene">
  <a-box id="box" class="clickable" position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>

  <a-camera id="camera">
    <a-entity position="0 0 -1" geometry="primitive: ring; radiusOuter: 0.07;radiusInner: 0.05;" material="color: red; shader: flat" cursor="maxDistance: 1; fuse: false" raycaster="objects: .clickable">
      <a-animation begin="click" easing="ease-in" attribute="scale" fill="backwards" from="0.1 0.1 0.1" to="1 1 1" dur="150"></a-animation>
      <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="forwards" from="1 1 1" to="0.1 0.1 0.1" dur="1500"></a-animation>
    </a-entity>
  </a-camera>

</a-scene>

The bug are here:

  1. When the cursor is standing on the yellow cilinder, the click event of the blue cube doesn't trigger. You must set the cursor to the blue cube to trigger the click event (happens also by the second example).
  2. Continuing on 7, when you replace the cursor and place it back the click event is triggered directly.
  3. On VR mode there is no fuseTimeout by default it must be 1500 milliseconds.

Solution

  • I would make one camera with a component which would listen for the enterVR event on the scene

    • When enterVR create your cursor in the camera (or set fuse to true or scale it to
      1 1 1).
    • When exitVR remove your cursor (or set fuse to false or scale it to 0 0 0).

    The mouse-cursor component doesn't need to be removed, as its not relevant when in VR mode.

    For mouse clicks, use this: https://github.com/mayognaise/aframe-mouse-cursor-component