282 lines
9.0 KiB
HTML
282 lines
9.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<!-- Fathom - simple website analytics - https://github.com/usefathom/fathom -->
|
|
<script>
|
|
(function(f, a, t, h, o, m){
|
|
a[h]=a[h]||function(){
|
|
(a[h].q=a[h].q||[]).push(arguments)
|
|
};
|
|
o=f.createElement('script'),
|
|
m=f.getElementsByTagName('script')[0];
|
|
o.async=1; o.src=t; o.id='fathom-script';
|
|
m.parentNode.insertBefore(o,m)
|
|
})(document, window, '//stats.josh.earth/tracker.js', 'fathom');
|
|
fathom('set', 'siteId', 'GISNV');
|
|
fathom('trackPageview');
|
|
</script>
|
|
<!-- / Fathom --> <meta charset="UTF-8">
|
|
<title>WebVR + ThreeJS Application</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
|
|
<!-- required for everything -->
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.96.0/build/three.min.js"></script>
|
|
<!-- needed for loading GLTF files -->
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.96.0/examples/js/loaders/GLTFLoader.js"></script>
|
|
|
|
<style type="text/css">
|
|
html, body {
|
|
margin:0;
|
|
padding:0;
|
|
overflow: hidden;
|
|
}
|
|
button {
|
|
color: black;
|
|
background-color: white;
|
|
border: 1px solid black;
|
|
font-size: 100%;
|
|
padding: 0.25em;
|
|
margin: 0.25em;
|
|
}
|
|
button:disabled {
|
|
color: darkgray;
|
|
background-color: gray;
|
|
}
|
|
#overlay {
|
|
position: fixed;
|
|
font-size: 5vh;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background-color: rgba(255,255,255,0.5);
|
|
text-align: center;
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
align-content: center;
|
|
}
|
|
#overlay #inner {
|
|
border: 1px solid black;
|
|
background-color: white;
|
|
width: 70vw;
|
|
height: 40vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
#loading-indicator {
|
|
display: block;
|
|
}
|
|
|
|
#start-button {
|
|
display: none;
|
|
}
|
|
</style>
|
|
|
|
</head>
|
|
<body>
|
|
|
|
|
|
<div id="overlay">
|
|
<div id="inner">
|
|
<h1>Application Name</h1>
|
|
<div id="loading-indicator">
|
|
<label>loading</label>
|
|
<progress max="100" value="0" id="progress"></progress>
|
|
</div>
|
|
<button id="enter-button" disabled>VR not supported, play anyway</button>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script type="module">
|
|
// for pointer (mouse, controller, touch) support
|
|
import {POINTER_CLICK, POINTER_ENTER, POINTER_EXIT, Pointer} from './static/js/pointer.js'
|
|
// calculate FPS and other stats
|
|
import VRStats from "./static/js/vrstats.js"
|
|
// enter and exit VR
|
|
import VRManager, {VR_DETECTED} from "./static/js/vrmanager.js"
|
|
|
|
//JQuery-like selector
|
|
const $ = (sel) => document.querySelector(sel)
|
|
const on = (elem, type, cb) => elem.addEventListener(type,cb)
|
|
|
|
// global constants and variables for your app go here
|
|
let camera, scene, renderer, pointer, stats, vrmanager;
|
|
|
|
let cube
|
|
|
|
const WAIT_FOR_LOAD = false
|
|
//called on setup. Customize this
|
|
function initContent(scene,camera,renderer) {
|
|
//set the background color of the scene
|
|
scene.background = new THREE.Color( 0xcccccc );
|
|
|
|
//load a cat texture
|
|
const texture_loader = new THREE.TextureLoader()
|
|
//cat from http://creative-commons-cats.tumblr.com/page/3
|
|
const texture = texture_loader.load('./static/img/cat.jpg')
|
|
|
|
//create a cube
|
|
cube = new THREE.Mesh(
|
|
new THREE.BoxGeometry(1,1,1),
|
|
new THREE.MeshLambertMaterial({color:'white', map:texture})
|
|
)
|
|
//camera is at z=0, so move the cube back so we can see it
|
|
cube.position.z = -5
|
|
//move cube up to camera height (~1.5m)
|
|
cube.position.y = 1.5
|
|
//make it clickable
|
|
cube.userData.clickable = true
|
|
scene.add(cube)
|
|
|
|
//a standard light
|
|
const light = new THREE.DirectionalLight( 0xffffff, 1.0 );
|
|
light.position.set( 1, 1, 1 ).normalize();
|
|
scene.add( light );
|
|
|
|
|
|
|
|
|
|
|
|
// enable stats visible inside VR
|
|
stats = new VRStats(renderer)
|
|
camera.add(stats)
|
|
scene.add(camera)
|
|
|
|
//class which handles mouse and VR controller
|
|
pointer = new Pointer(scene,renderer,camera, {
|
|
|
|
//Pointer searches everything in the scene by default
|
|
//override this to match just certain things
|
|
intersectionFilter: ((o) => o.userData.clickable),
|
|
|
|
//make the camera pan when moving the mouse. good for simulating head turning on desktop
|
|
cameraFollowMouse:false,
|
|
|
|
// set to true to move the controller node forward and tilt with the mouse.
|
|
// good for testing VR controls on desktop
|
|
mouseSimulatesController:false,
|
|
|
|
//turn this off if you provide your own pointer model
|
|
enableLaser: true,
|
|
})
|
|
|
|
|
|
const STICK_HEIGHT = 1.0
|
|
const stick = new THREE.Mesh(
|
|
new THREE.CylinderBufferGeometry(0.1,0.1,STICK_HEIGHT),
|
|
new THREE.MeshLambertMaterial({color:'aqua'})
|
|
)
|
|
const toRad = (degrees) => degrees*Math.PI/180
|
|
stick.position.z = -STICK_HEIGHT/2;
|
|
stick.rotation.x = toRad(-90)
|
|
pointer.controller1.add(stick)
|
|
|
|
|
|
//change cube to red BG when clicking
|
|
on(cube,POINTER_CLICK,()=>{
|
|
console.log("clicking on the cube")
|
|
cube.material.color.set(0xff0000)
|
|
})
|
|
//change cube to green BG when hovering over it
|
|
on(cube,POINTER_ENTER,()=>{
|
|
// console.log("entering the cube")
|
|
cube.material.color.set(0x00ff00)
|
|
})
|
|
on(cube,POINTER_EXIT,()=>{
|
|
// console.log('exiting the cube')
|
|
cube.material.color.set(0xffffff)
|
|
})
|
|
|
|
|
|
|
|
on($("#enter-button"),'click',()=>{
|
|
$("#overlay").style.display = 'none'
|
|
//we can start playing sound now
|
|
})
|
|
|
|
|
|
// this will fire if VR is supported on the device
|
|
// and a VR headset is detected
|
|
// if it never fires assume VR is not supported at all.
|
|
on(vrmanager,VR_DETECTED,()=>{
|
|
console.log("VR detected")
|
|
$("#enter-button").removeAttribute('disabled',false)
|
|
$("#enter-button").innerText = "enter vr"
|
|
on($("#enter-button"),'click',()=> vrmanager.enterVR())
|
|
})
|
|
|
|
}
|
|
|
|
//called on every frame. customize this
|
|
function render(time) {
|
|
//update the pointer and stats, if configured
|
|
if(pointer) pointer.tick(time)
|
|
if(stats) stats.update(time)
|
|
//rotate the cube on every tick
|
|
if(cube) cube.rotation.y += 0.002
|
|
renderer.render( scene, camera );
|
|
}
|
|
|
|
|
|
// you shouldn't need to modify much below here
|
|
|
|
function initScene() {
|
|
//create DIV for the canvas
|
|
const container = document.createElement( 'div' );
|
|
document.body.appendChild( container );
|
|
scene = new THREE.Scene();
|
|
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 50 );
|
|
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
renderer.setPixelRatio( window.devicePixelRatio );
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
renderer.gammaOutput = true
|
|
renderer.vr.enabled = true;
|
|
container.appendChild( renderer.domElement );
|
|
vrmanager = new VRManager(renderer)
|
|
// document.body.appendChild( WEBVR.createButton( renderer ) );
|
|
|
|
initContent(scene,camera,renderer)
|
|
|
|
window.addEventListener( 'resize', ()=>{
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
camera.updateProjectionMatrix();
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
}, false );
|
|
|
|
THREE.DefaultLoadingManager.onStart = (url, loaded, total) => {
|
|
console.log(`loading ${url}. loaded ${loaded} of ${total}`)
|
|
}
|
|
THREE.DefaultLoadingManager.onLoad = () => {
|
|
console.log(`loading complete`)
|
|
$("#loading-indicator").style.display = 'none'
|
|
$("#enter-button").style.display = 'block'
|
|
$("#enter-button").removeAttribute('disabled')
|
|
}
|
|
THREE.DefaultLoadingManager.onProgress = (url, loaded, total) => {
|
|
console.log(`prog ${url}. loaded ${loaded} of ${total}`)
|
|
$("#progress").setAttribute('value',100*(loaded/total))
|
|
}
|
|
THREE.DefaultLoadingManager.onError = (url) => {
|
|
console.log(`error loading ${url}`)
|
|
}
|
|
|
|
if(!WAIT_FOR_LOAD) {
|
|
$("#loading-indicator").style.display = 'none'
|
|
$("#enter-button").style.display = 'block'
|
|
$("#enter-button").removeAttribute('disabled')
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// initPage()
|
|
initScene()
|
|
renderer.setAnimationLoop(render)
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|