Created
June 28, 2016 00:51
-
-
Save drGrove/a71759cf7c5bea973145d7cb75aa6f2c to your computer and use it in GitHub Desktop.
A fork of three.js examples for webvr and vive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <title>three.js webvr - cubes</title> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | |
| <style> | |
| body { | |
| font-family: Monospace; | |
| background-color: #101010; | |
| color: #fff; | |
| margin: 0px; | |
| overflow: hidden; | |
| } | |
| a { | |
| color: #f00; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <script src="../build/three.js"></script> | |
| <script src="js/WebVR.js"></script> | |
| <script src="js/effects/VREffect.js"></script> | |
| <script src="js/controls/VRControls.js"></script> | |
| <script src="js/ViveController.js"></script> | |
| <script src="js/loaders/OBJLoader.js"></script> | |
| <script> | |
| // A dev logger tool that overrides console.log | |
| var logger = {}; | |
| logger.log = []; | |
| var originalLog = console.log; | |
| console.log = function(txt) { | |
| logger.log.append(arguments); | |
| originallog.apply(console, arguments); | |
| } | |
| </script> | |
| <script> | |
| if ( WEBVR.isLatestAvailable() === false ) { | |
| document.body.appendChild( WEBVR.getMessage() ); | |
| } | |
| // | |
| var container; | |
| var camera, scene, renderer; | |
| var effect, controls; | |
| var controller1, controller2; | |
| var pointer, menu; | |
| var room; | |
| init(); | |
| animate(); | |
| function init() { | |
| container = document.createElement( 'div' ); | |
| document.body.appendChild( container ); | |
| var info = document.createElement( 'div' ); | |
| info.style.position = 'absolute'; | |
| info.style.top = '10px'; | |
| info.style.width = '100%'; | |
| info.style.textAlign = 'center'; | |
| info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> webgl - htc vive'; | |
| container.appendChild( info ); | |
| scene = new THREE.Scene(); | |
| camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 ); | |
| scene.add( camera ); | |
| /* | |
| room = new THREE.Mesh( | |
| new THREE.BoxGeometry( 6, 6, 6, 10, 10, 10 ), | |
| new THREE.MeshBasicMaterial( { color: 0x202020, wireframe: true } ) | |
| ); | |
| */ | |
| room = new THREE.Object3D(); | |
| room.position.y = 3; | |
| //scene.add( room ); | |
| scene.add( new THREE.HemisphereLight( 0x404020, 0x202040, 0.5 ) ); | |
| var light = new THREE.DirectionalLight( 0xffffff ); | |
| light.position.set( 1, 1, 1 ).normalize(); | |
| scene.add( light ); | |
| var geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 ); | |
| for ( var i = 0; i < 200; i ++ ) { | |
| var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) ); | |
| object.position.x = Math.random() * 4 - 2; | |
| object.position.y = Math.random() * 4 - 2; | |
| object.position.z = Math.random() * 4 - 2; | |
| object.rotation.x = Math.random() * 2 * Math.PI; | |
| object.rotation.y = Math.random() * 2 * Math.PI; | |
| object.rotation.z = Math.random() * 2 * Math.PI; | |
| object.scale.x = Math.random() + 0.5; | |
| object.scale.y = Math.random() + 0.5; | |
| object.scale.z = Math.random() + 0.5; | |
| object.userData.velocity = new THREE.Vector3(); | |
| object.userData.velocity.x = Math.random() * 0.01 - 0.005; | |
| object.userData.velocity.y = Math.random() * 0.01 - 0.005; | |
| object.userData.velocity.z = Math.random() * 0.01 - 0.005; | |
| object.interactable = true; | |
| //scene.add( object ); | |
| } | |
| var material = new THREE.MeshStandardMaterial(); | |
| var path = 'models/obj/cerberus/'; | |
| var loader = new THREE.OBJLoader(); | |
| loader.load( path + 'Cerberus.obj', function ( group ) { | |
| // var material = new THREE.MeshBasicMaterial( { wireframe: true } ); | |
| var loader = new THREE.TextureLoader(); | |
| material.roughness = 1; | |
| material.metalness = 1; | |
| material.map = loader.load( path + 'Cerberus_A.jpg' ); | |
| material.roughnessMap = loader.load( path + 'Cerberus_R.jpg' ); | |
| material.metalnessMap = loader.load( path + 'Cerberus_M.jpg' ); | |
| material.normalMap = loader.load( path + 'Cerberus_N.jpg' ); | |
| material.map.wrapS = THREE.RepeatWrapping; | |
| material.roughnessMap.wrapS = THREE.RepeatWrapping; | |
| material.metalnessMap.wrapS = THREE.RepeatWrapping; | |
| material.normalMap.wrapS = THREE.RepeatWrapping; | |
| group.traverse( function ( child ) { | |
| if ( child instanceof THREE.Mesh ) { | |
| child.material = material; | |
| } | |
| } ); | |
| group.position.y = - 2; | |
| group.rotation.y = - Math.PI / 2; | |
| //room.add( group ); | |
| } ); | |
| var loader = new THREE.CubeTextureLoader(); | |
| loader.setPath( 'textures/cube/pisa/' ); | |
| material.envMap = loader.load( [ | |
| "px.png", "nx.png", | |
| "py.png", "ny.png", | |
| "pz.png", "nz.png" | |
| ] ); | |
| // | |
| renderer = new THREE.WebGLRenderer( { antialias: true } ); | |
| renderer.setClearColor( 0x101010 ); | |
| renderer.setPixelRatio( window.devicePixelRatio ); | |
| renderer.setSize( window.innerWidth, window.innerHeight ); | |
| renderer.sortObjects = false; | |
| container.appendChild( renderer.domElement ); | |
| controls = new THREE.VRControls( camera ); | |
| controls.standing = true; | |
| // controllers | |
| controller1 = new THREE.ViveController( 0 ); | |
| controller1.standingMatrix = controls.getStandingMatrix(); | |
| scene.add( controller1 ); | |
| controller2 = new THREE.ViveController( 1 ); | |
| controller2.standingMatrix = controls.getStandingMatrix(); | |
| scene.add( controller2 ); | |
| var vivePath = 'models/obj/vive-controller/'; | |
| var loader = new THREE.OBJLoader(); | |
| loader.load( vivePath + 'vr_controller_vive_1_5.obj', function ( object ) { | |
| var loader = new THREE.TextureLoader(); | |
| var controller = object.children[0]; | |
| controller.material.map = loader.load( vivePath + 'onepointfive_texture.png' ); | |
| controller.material.specularMap = loader.load( vivePath + 'onepointfive_spec.png' ); | |
| controller.name = "ignore"; | |
| controller1.add( object.clone() ); | |
| controller2.add( object.clone() ); | |
| } ); | |
| var len = 10; | |
| var log_tex | |
| //create image | |
| var bitmap = document.createElement('canvas'); | |
| var g = bitmap.getContext('2d'); | |
| bitmap.width = 100; | |
| bitmap.height = 100; | |
| g.font = 'Bold 20px Arial'; | |
| g.fillStyle = 'white'; | |
| g.fillText("swagswagswagswagswag", 0, 20); | |
| g.strokeStyle = 'black'; | |
| g.strokeText("swagswagswagswagswag", 0, 20); | |
| // canvas contents will be used for a texture | |
| var texture = new THREE.Texture(bitmap) | |
| texture.needsUpdate = true; | |
| var log_out = new THREE.Mesh( | |
| new THREE.BoxGeometry(.2,.002,.2), | |
| new THREE.MeshBasicMaterial({color: 0x666666, map: texture}) | |
| ); | |
| log_out.position.setY(-.03) | |
| controller1.add(log_out); | |
| // visual raycast | |
| pointer = new THREE.Mesh( | |
| new THREE.BoxGeometry(.002,.002,len), | |
| new THREE.MeshBasicMaterial({color: 0x00BCD4}) | |
| ); | |
| pointer.name = "ignore"; | |
| pointer.position.setZ(-len/2) | |
| controller1.add(pointer); | |
| // Object menu | |
| menu = new THREE.Object3D(); | |
| background = new THREE.Mesh( | |
| new THREE.BoxGeometry(.2,.002,.2), | |
| new THREE.MeshBasicMaterial({color: 0x666666}) | |
| ); | |
| background.position.setY(.03); | |
| background.name = "ignore"; | |
| menu.add(background); | |
| cube = new THREE.Mesh( | |
| new THREE.BoxGeometry(.02,.02,.02), | |
| new THREE.MeshBasicMaterial({color: 0x999999}) | |
| ); | |
| cube.position.set(-.06, .06, -.06); | |
| cube.name = "obj_menu_item"; | |
| cube.isMenuItem = true; | |
| menu.add(cube); | |
| cylinder = new THREE.Mesh( new THREE.CylinderGeometry(.015,.015,.02), new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); | |
| cylinder.position.set(-.06, .06, .04); | |
| cylinder.isMenuItem = true; | |
| cylinder.name = "obj_menu_item"; | |
| menu.add(cylinder); | |
| sphere = new THREE.Mesh( new THREE.SphereGeometry(.01, 8, 8), new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); | |
| sphere.position.set(0, .06, 0); | |
| sphere.isMenuItem = true; | |
| sphere.name = "obj_menu_item"; | |
| menu.add(sphere); | |
| controller2.add(menu); | |
| //controller1.add(selector); | |
| /* | |
| var length = 100; | |
| var hex = 0xffff00; | |
| arrowHelper = new THREE.ArrowHelper( controller1.forward(), controller1.position, length, hex ); | |
| scene.add( arrowHelper ); | |
| */ | |
| effect = new THREE.VREffect( renderer ); | |
| if ( WEBVR.isAvailable() === true ) { | |
| document.body.appendChild( WEBVR.getButton( effect ) ); | |
| } | |
| // | |
| window.addEventListener( 'resize', onWindowResize, false ); | |
| } | |
| function onWindowResize() { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| effect.setSize( window.innerWidth, window.innerHeight ); | |
| } | |
| // | |
| function animate() { | |
| requestAnimationFrame( animate ); | |
| render(); | |
| } | |
| /** | |
| * TODO: scale left right | |
| * pull push up down | |
| */ | |
| /** | |
| * Clones an object from the menu | |
| * @param {object:Mesh||Object3D} object | |
| * @returns {object} n the cloned object | |
| */ | |
| function cloneObjectFromMenu(object) { | |
| var n = object.clone(); | |
| n.name = ""; | |
| n.applyMatrix(object.matrixWorld); | |
| var vector = new THREE.Vector3(); | |
| vector.setFromMatrixPosition(object.matrixWorld); | |
| n.position.set(vector.x, vector.y, vector.z); | |
| n.updateMatrixWorld(); | |
| scene.add(n); | |
| THREE.SceneUtils.detach(n, n.parent, scene); | |
| THREE.SceneUtils.attach(n, scene, controller1); | |
| return n; | |
| } | |
| // button events | |
| window.addEventListener('gamepadButtonClicked', function(e) { | |
| console.log('Button Event: ', e); | |
| switch (e.detail.controller_id) { | |
| case controller1.id: | |
| switch (e.detail.button_id) { | |
| case 1: | |
| var cast = new THREE.Raycaster(); | |
| cast.set(controller1.getPosition(), controller1.forward()); | |
| var intersects = cast.intersectObjects(scene.children, true); | |
| for (var i = 0; i < intersects.length; i++) { | |
| var curr = intersects[i]; | |
| if (curr && curr.object.name !== "ignore") { | |
| if (curr.object.name === "obj_menu_item") { | |
| controller1.heldObject = cloneObjectFromMenu(curr.object); | |
| break; | |
| } | |
| controller1.heldObject = curr.object; | |
| THREE.SceneUtils.detach(controller1.heldObject, controller1.heldObject.parent, scene); | |
| THREE.SceneUtils.attach(controller1.heldObject, scene, controller1); | |
| break; | |
| } | |
| } | |
| break; | |
| case 2: | |
| break; | |
| case 3: | |
| break; | |
| } | |
| break; | |
| case controller2.id: | |
| switch (e.detail.button_id) { | |
| case 1: | |
| break; | |
| case 2: | |
| break; | |
| case 3: | |
| menu.visible = !menu.visible; | |
| break; | |
| } | |
| break; | |
| } | |
| }) | |
| window.addEventListener('gamepadButtonReleased', function(e) { | |
| console.log('Button released: ', e); | |
| switch (e.detail.controller_id) { | |
| case controller1.id: | |
| if (controller1.heldObject) { | |
| THREE.SceneUtils.detach(controller1.heldObject, controller1, scene); | |
| THREE.SceneUtils.attach(controller1.heldObject, scene, scene); | |
| controller1.heldObject = undefined; | |
| } | |
| case controller2.id: | |
| } | |
| }) | |
| var arrowHelper; | |
| function render() { | |
| controls.update(); | |
| // todo make function | |
| var cast = new THREE.Raycaster(); | |
| cast.set(controller1.getPosition(), controller1.forward()); | |
| if (arrowHelper) | |
| scene.remove(arrowHelper); | |
| arrowHelper = new THREE.ArrowHelper( controller1.forward(), controller1.getPosition(), 100, 0xff0000 ); | |
| //scene.add(arrowHelper); | |
| var intersects = cast.intersectObjects(scene.children, true); | |
| for (var i = 0; i < intersects.length; i++) { | |
| if (intersects[i] && intersects[i].object.interactable) { | |
| controller1.remove(pointer); | |
| pointer = new THREE.Mesh( new THREE.BoxGeometry(.002,.002,intersects[0].distance), new THREE.MeshBasicMaterial( { color: 0x00BCD4 } ) ); | |
| pointer.position.setZ(-intersects[0].distance/2) | |
| controller1.add(pointer); | |
| break; | |
| } | |
| } | |
| for ( var i = 0; i < room.children.length; i ++ ) { | |
| var cube = room.children[ i ]; | |
| if ( cube.geometry instanceof THREE.BoxGeometry === false ) continue; | |
| // cube.position.add( cube.userData.velocity ); | |
| if ( cube.position.x < - 3 || cube.position.x > 3 ) { | |
| cube.position.x = THREE.Math.clamp( cube.position.x, - 3, 3 ); | |
| cube.userData.velocity.x = - cube.userData.velocity.x; | |
| } | |
| if ( cube.position.y < - 3 || cube.position.y > 3 ) { | |
| cube.position.y = THREE.Math.clamp( cube.position.y, - 3, 3 ); | |
| cube.userData.velocity.y = - cube.userData.velocity.y; | |
| } | |
| if ( cube.position.z < - 3 || cube.position.z > 3 ) { | |
| cube.position.z = THREE.Math.clamp( cube.position.z, - 3, 3 ); | |
| cube.userData.velocity.z = - cube.userData.velocity.z; | |
| } | |
| cube.rotation.x += 0.01; | |
| } | |
| effect.render( scene, camera ); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment