20 Minutes into the Future with

Google Cardboard

and JavaScript

Hello

I'm Max Glenister

@omgmog on the Internet

SusHack

2013 — 2015

Pretty cool.

The Future

2015 — ?

In your pocket is a VR device.

Most phones contain a lot of sensors...

Camera

Touch Screen

GPS

WiFi

Microphone

Ambient Light Sensor

Accelerometer

Magnetometer

Gyroscope

...

How can we use this for VR?

Geolocation

navigator.geolocation.getCurrentPosition(function (pos) {
  console.log(pos.coords.latitude);
  console.log(pos.coords.longitude);
});

Device Orientation

Rotation on X-axis

Pitch or Beta (β) range of -180° to 180°

Rotation on Y-axis

Roll or Gamma (γ) range of -90° to 90°

Rotation on Z-axis

Yaw or Alpha (α) range of 0° to 360°

window.addEventListener('deviceorientation',
  function (e) {
    console.log(e.gamma);
    console.log(e.beta);
    console.log(e.alpha);
  },
  false
);

Fullscreen

var button = document.querySelector('button');

button.addEventListener('click',
  function (e) {
    document.body.requestFullScreen();
  }
);

getUserMedia

navigator.getUserMedia(
  // Constraints
  { video: true, audio: false },

  // Success function
  function (stream) {
    var video = document.querySelector('video');
    video.src = window.URL.createObjectURL(stream);
    video.onloadedmetadata = function(e) {
      // Stream loaded, do some stuff
    };
  },

  // Error function
  function (err) {
    console.log(err);
  }
);

Web Audio

// Set up the audio context
var context = new AudioContext();
// Create an oscillator
var oscillator = context.createOscillator();
// Connect the oscillator to our playback device
oscillator.connect(context.destination);
// Start the sound output
oscillator.start();
var context = new AudioContext();
var file = 'demo.wav';
var request = new XMLHttpRequest();
var source;
request.open('GET', file, true);
request.responseType = 'arraybuffer';
request.onload = function () {
  source = context.createBufferSource();
  context.decodeAudioData(request.response, function (buffer) {
    source.buffer = buffer;
    source.connect(context.destination);
    source.start(context.currentTime);
  });
};
request.send();

WebGL

WebGL

WebGL (with three.js)

This bit is really simple!

// Set it all up...
var width = 600, height = 300, aspect = width/height;
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer({
  alpha: true, antialias: true, logarithmicDepthBuffer: true
});
renderer.setSize( width, height );
document.body.appendChild(renderer.domElement);

// ... Continued
// Create a cube...
var cubeGeometry = new THREE.BoxGeometry(10, 10, 10);
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0x000000});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);

// Add some edges...
var cubeEdges = new THREE.EdgesHelper(cube, 0xff0000);
cubeEdges.material.linewidth = 5;
scene.add(cubeEdges);

// ... Continued
// Lights...
var ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
var pointLight = new THREE.PointLight(0xffffff, 6, 40);
pointLight.lookAt(cube.position);
scene.add(pointLight);

// Camera...
var camera = new T.PerspectiveCamera(35, aspect, 1, 1000);
camera.position.set(20, 20, 20);
camera.lookAt(scene.position);

// ... Continued
// Action!
function render() {
  cube.rotation.x += 0.04;
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();

Making it work in 3D

// Include the StereoEffect.js file

// After setting up your renderer
effect = new THREE.StereoEffect(renderer);
effect.eyeSeparation = 1; // Set the IPD
effect.setSize( width, height );

// Instead of calling renderer.render(scene, camera)
effect.render(scene, camera)

INFORMATION
OVERLOAD

Google Cardboard

Some demos

These are all available online

blog.omgmog.net/jscard.xyz

Lastly...

Consider UX

I've made a list of resources...

github.com/omgmog/ui-ux-vr

I've been Max Glenister

Thanks