2
0
Эх сурвалжийг харах

Examples: Added webxr_ar_paint.

Mr.doob 5 жил өмнө
parent
commit
715e7e8aec

+ 1 - 0
examples/files.js

@@ -323,6 +323,7 @@ var files = {
 		"webaudio_visualizer"
 	],
 	"webxr": [
+		"webxr_ar_paint",
 		"webxr_vr_ballshooter",
 		"webxr_vr_cubes",
 		"webxr_vr_dragging",

+ 7 - 0
examples/jsm/webxr/ARButton.d.ts

@@ -0,0 +1,7 @@
+import {
+	WebGLRenderer
+} from '../../../src/Three';
+
+export namespace ARButton {
+	export function createButton( renderer: WebGLRenderer ): HTMLElement;
+}

+ 173 - 0
examples/jsm/webxr/ARButton.js

@@ -0,0 +1,173 @@
+/**
+ * @author mrdoob / http://mrdoob.com
+ * @author Mugen87 / https://github.com/Mugen87
+ */
+
+var ARButton = {
+
+	createButton: function ( renderer ) {
+
+		function showEnterXR( /*device*/ ) {
+
+			var currentSession = null;
+
+			function onSessionStarted( session ) {
+
+				session.addEventListener( 'end', onSessionEnded );
+
+				/*
+				session.updateWorldTrackingState( {
+					'planeDetectionState': { 'enabled': true }
+				} );
+				*/
+
+				renderer.vr.setReferenceSpaceType( 'local' );
+				renderer.vr.setSession( session );
+				button.textContent = 'STOP AR';
+
+				currentSession = session;
+
+			}
+
+			function onSessionEnded( /*event*/ ) {
+
+				currentSession.removeEventListener( 'end', onSessionEnded );
+
+				renderer.vr.setSession( null );
+				button.textContent = 'START AR';
+
+				currentSession = null;
+
+			}
+
+			//
+
+			button.style.display = '';
+
+			button.style.cursor = 'pointer';
+			button.style.left = 'calc(50% - 50px)';
+			button.style.width = '100px';
+
+			button.textContent = 'START AR';
+
+			button.onmouseenter = function () {
+
+				button.style.opacity = '1.0';
+
+			};
+
+			button.onmouseleave = function () {
+
+				button.style.opacity = '0.5';
+
+			};
+
+			button.onclick = function () {
+
+				if ( currentSession === null ) {
+
+					navigator.xr.requestSession( 'immersive-ar' ).then( onSessionStarted );
+
+				} else {
+
+					currentSession.end();
+
+				}
+
+			};
+
+		}
+
+		function disableButton() {
+
+			button.style.display = '';
+
+			button.style.cursor = 'auto';
+			button.style.left = 'calc(50% - 75px)';
+			button.style.width = '150px';
+
+			button.onmouseenter = null;
+			button.onmouseleave = null;
+
+			button.onclick = null;
+
+		}
+
+		function showXRNotFound() {
+
+			disableButton();
+
+			button.textContent = 'XR NOT FOUND';
+
+		}
+
+		function stylizeElement( element ) {
+
+			element.style.position = 'absolute';
+			element.style.bottom = '20px';
+			element.style.padding = '12px 6px';
+			element.style.border = '1px solid #fff';
+			element.style.borderRadius = '4px';
+			element.style.background = 'rgba(0,0,0,0.1)';
+			element.style.color = '#fff';
+			element.style.font = 'normal 13px sans-serif';
+			element.style.textAlign = 'center';
+			element.style.opacity = '0.5';
+			element.style.outline = 'none';
+			element.style.zIndex = '999';
+
+		}
+
+		if ( 'xr' in navigator ) {
+
+			var button = document.createElement( 'button' );
+			button.style.display = 'none';
+
+			stylizeElement( button );
+
+			navigator.xr.isSessionSupported( 'immersive-ar' ).then( function ( supported ) {
+
+				if ( supported ) {
+
+					showEnterXR();
+
+				} else {
+
+					showXRNotFound();
+
+				}
+
+			} );
+
+			return button;
+
+		} else {
+
+			var message = document.createElement( 'a' );
+			message.href = 'https://immersive-web.github.io/webxr/';
+
+			if ( window.isSecureContext === false ) {
+
+				message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message
+
+			} else {
+
+				message.innerHTML = 'WEBXR NOT AVAILABLE';
+
+			}
+
+			message.style.left = 'calc(50% - 90px)';
+			message.style.width = '180px';
+			message.style.textDecoration = 'none';
+
+			stylizeElement( message );
+
+			return message;
+
+		}
+
+	}
+
+};
+
+export { ARButton };

+ 168 - 0
examples/webxr_ar_paint.html

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js ar - paint</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+		<link type="text/css" rel="stylesheet" href="main.css">
+		<!-- WebXR Device API (For Chrome M76+), expires 12/04/2019 -->
+		<meta http-equiv="origin-trial" content="Aq9LklhCLNUveuCr7QTpGpqwCPG817cYHdVyQuJPOZYk47iRB390lUKa5edVmgS1pZSl8HPspElEC/91Fz55dwIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3NTQxNzU5OX0=">
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> ar - paint
+		</div>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+			import { TubePainter } from './jsm/misc/TubePainter.js';
+			import { ARButton } from './jsm/webxr/ARButton.js';
+
+			var container;
+			var camera, scene, renderer;
+			var controller, painter;
+
+			var up = new THREE.Vector3( 0, 1, 0 );
+
+			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="https://threejs.org" target="_blank" rel="noopener">three.js</a> ar - paint<br/>Enable chrome://flags/#webxr-ar-module<br/>(Chrome 80+)';
+				container.appendChild( info );
+
+				scene = new THREE.Scene();
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 );
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.vr.enabled = true;
+				container.appendChild( renderer.domElement );
+
+				//
+
+				document.body.appendChild( ARButton.createButton( renderer ) );
+
+				// model
+
+				var light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 );
+				light.position.set( 0, 1, 0 );
+				scene.add( light );
+
+				//
+
+				painter = new TubePainter();
+				painter.setSize( 0.4 );
+				painter.mesh.material.side = THREE.DoubleSide;
+				scene.add( painter.mesh );
+
+				//
+
+				function onSelectStart() {
+
+					this.userData.isSelecting = true;
+					this.userData.skipFrames = 2;
+
+				}
+
+				function onSelectEnd() {
+
+					this.userData.isSelecting = false;
+
+				}
+
+				controller = renderer.vr.getController( 0 );
+				controller.addEventListener( 'selectstart', onSelectStart );
+				controller.addEventListener( 'selectend', onSelectEnd );
+				controller.userData.points = [ new THREE.Vector3(), new THREE.Vector3() ];
+				controller.userData.matrices = [ new THREE.Matrix4(), new THREE.Matrix4() ];
+				controller.userData.skipFrames = 0;
+				scene.add( controller );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function handleController( controller ) {
+
+				var userData = controller.userData;
+
+				var point1 = userData.points[ 0 ];
+				var point2 = userData.points[ 1 ];
+
+				var matrix1 = userData.matrices[ 0 ];
+				var matrix2 = userData.matrices[ 1 ];
+
+				point1.set( 0, 0, - 0.2 ).applyMatrix4( controller.matrixWorld );
+				matrix1.lookAt( point2, point1, up );
+
+				if ( userData.isSelecting === true ) {
+
+					if ( userData.skipFrames >= 0 ) {
+
+						// TODO(mrdoob) Revisit this
+
+						userData.skipFrames --;
+
+					} else {
+
+						var count = painter.mesh.geometry.drawRange.count;
+
+						painter.stroke( point1, point2, matrix1, matrix2 );
+
+						painter.updateGeometry( count, painter.mesh.geometry.drawRange.count );
+
+					}
+
+				}
+
+				point2.copy( point1 );
+				matrix2.copy( matrix1 );
+
+			}
+
+			function animate() {
+
+				renderer.setAnimationLoop( render );
+
+			}
+
+			function render() {
+
+				handleController( controller );
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>