Skip to content

Instantly share code, notes, and snippets.

@visnup
Last active September 18, 2017 02:25
Show Gist options
  • Save visnup/e651059b091537fd257eb215035ca7df to your computer and use it in GitHub Desktop.
Save visnup/e651059b091537fd257eb215035ca7df to your computer and use it in GitHub Desktop.
RICOH THETA S live 360º video stream rendering in Chrome via WebGL and a <video> texture

To get this working, you'll need the live-streaming software from RICOH. Install that and follow the live video instructions to connect your camera to your computer and have it show up as a video source.

If you're on a Mac, you can open up the FaceTime app and test it by picking "THETA UVC Blender" from the Video menu.

Once all of that is working, open up index.html and you should see the video rendered on the inside of a sphere that you can rotate around. Use the mouse to click and drag to move the camera around and the mouse wheel to zoom in and out.

<style>
body { margin: 0 }
video { display: none }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/r75/examples/js/controls/OrbitControls.js"></script>
<script>
'use strict'
navigator.mediaDevices.enumerateDevices().then((devices) => {
// find the theta uvc blender device
let theta = devices.find(device => device.label.match(/THETA UVC Blender/))
return theta ? { optional: [{ sourceId: theta.deviceId }] } : true
}).then((video) => {
// get the camera
return navigator.mediaDevices.getUserMedia({ video })
}).then((stream) => {
// create the video tag
let video = document.body.appendChild(document.createElement('video'))
video.src = window.URL.createObjectURL(stream)
// create a scene
let scene = new THREE.Scene()
// attach the video to a texture
let videoTexture = new THREE.Texture(video)
videoTexture.minFilter = THREE.NearestFilter
// create a sphere at the origin textured on the inside by the video
let sphere = new THREE.SphereGeometry(50, 16, 16),
material = new THREE.MeshBasicMaterial({ map: videoTexture })
material.side = THREE.BackSide
scene.add(new THREE.Mesh(sphere, material))
// setup a light and camera inside the sphere
let { width, height } = document.body.getBoundingClientRect()
let light = new THREE.AmbientLight(0xFFFFFF),
camera = new THREE.PerspectiveCamera(85, width / height, 1, 1000)
scene.add(light)
scene.add(camera)
// controls for rotating around the origin
let controls = new THREE.OrbitControls(camera)
controls.autoRotate = true
// invert rotation because we're inside the sphere
controls.rotateSpeed = -1.0
// camera needs to move off origin to see panning effect
camera.position.z = 1
// render
let renderer = new THREE.WebGLRenderer()
renderer.setSize(width, height, true)
document.body.appendChild(renderer.domElement)
;(function render() {
requestAnimationFrame(render)
controls.update()
// update the video texture
if (video.readyState === video.HAVE_ENOUGH_DATA)
videoTexture.needsUpdate = true
renderer.render(scene, camera)
})()
}).catch((err) => {
console.error(err)
})
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment