Переглянути джерело

WebXRManager: Refactored planes code. (#26098)

mrdoob 2 роки тому
батько
коміт
419bfc2061

+ 0 - 3
docs/api/en/renderers/webxr/WebXRManager.html

@@ -92,9 +92,6 @@
 			no physical controllers are used.
 		</p>
 
-		<h3>[method:Set getPlanes]()</h3>
-		<p>Returns the set of planes detected by WebXR's plane detection API.</p>
-
 		<h3>[method:String getReferenceSpace]()</h3>
 		<p>Returns the reference space.</p>
 

+ 0 - 5
docs/api/zh/renderers/webxr/WebXRManager.html

@@ -74,11 +74,6 @@
 			返回代表XR控制器所谓的*手或关节*空间的[page:Group 组]。在不使用物理控制器时,使用此空间可视化用户的手。
 		</p>
 
-		<h3>[method:Set getPlanes]()</h3>
-		<p>
-		返回由 WebXR 的平面检测 API 检测到的平面集。
-		</p>
-
 		<h3>[method:String getReferenceSpace]()</h3>
 		<p>
 		返回参考空间。

+ 88 - 0
examples/jsm/webxr/XRPlanes.js

@@ -0,0 +1,88 @@
+import {
+	BoxGeometry,
+	Matrix4,
+	Mesh,
+	MeshBasicMaterial,
+	Object3D
+} from 'three';
+
+class XRPlanes extends Object3D {
+
+	constructor( renderer ) {
+
+		super();
+
+		const geometry = new BoxGeometry();
+		const matrix = new Matrix4();
+
+		const currentPlanes = new Map();
+
+		const xr = renderer.xr;
+
+		xr.addEventListener( 'planesdetected', event => {
+
+			const frame = event.data;
+			const planes = frame.detectedPlanes;
+
+			const referenceSpace = xr.getReferenceSpace();
+
+			for ( const [ plane, mesh ] of currentPlanes ) {
+
+				if ( planes.has( plane ) === false ) {
+
+					mesh.material.dispose();
+					this.remove( mesh );
+
+					currentPlanes.delete( plane );
+
+				}
+
+			}
+
+			for ( const plane of planes ) {
+
+				if ( currentPlanes.has( plane ) === false ) {
+
+					const pose = frame.getPose( plane.planeSpace, referenceSpace );
+					matrix.fromArray( pose.transform.matrix );
+
+					const polygon = plane.polygon;
+
+					let minX = Number.MAX_SAFE_INTEGER;
+					let maxX = Number.MIN_SAFE_INTEGER;
+					let minZ = Number.MAX_SAFE_INTEGER;
+					let maxZ = Number.MIN_SAFE_INTEGER;
+
+					for ( const point of polygon ) {
+
+						minX = Math.min( minX, point.x );
+						maxX = Math.max( maxX, point.x );
+						minZ = Math.min( minZ, point.z );
+						maxZ = Math.max( maxZ, point.z );
+
+					}
+
+					const width = maxX - minX;
+					const height = maxZ - minZ;
+
+					const material = new MeshBasicMaterial( { color: 0xffffff * Math.random() } );
+
+					const mesh = new Mesh( geometry, material );
+					mesh.position.setFromMatrixPosition( matrix );
+					mesh.quaternion.setFromRotationMatrix( matrix );
+					mesh.scale.set( width, 0.01, height );
+					this.add( mesh );
+
+					currentPlanes.set( plane, mesh );
+
+				}
+
+			}
+
+		} );
+
+	}
+
+}
+
+export { XRPlanes };

+ 21 - 107
examples/webxr_ar_plane_detection.html

@@ -29,115 +29,37 @@
 
 			import * as THREE from 'three';
 			import { ARButton } from 'three/addons/webxr/ARButton.js';
+			import { XRPlanes } from 'three/addons/webxr/XRPlanes.js';
 
-			let camera, scene, renderer;
-
-			init();
-			animate();
-
-			const planesAdded = new Set();
-
-			function init() {
-
-				const container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				scene = new THREE.Scene();
-
-				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 );
-
-				const light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 );
-				light.position.set( 0.5, 1, 0.25 );
-				scene.add( light );
-
-				//
-
-				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.xr.enabled = true;
-				container.appendChild( renderer.domElement );
-
-				//
-
-				document.body.appendChild( ARButton.createButton( renderer, {
-					requiredFeatures: [ 'plane-detection' ]
-				} ) );
-
-				//
-
-				window.addEventListener( 'resize', onWindowResize );
-
-				renderer.xr.addEventListener( 'sessionstart', function () {
-
-					camera.position.set( 0, 0, 0 );
-
-				} );
-
-				renderer.xr.addEventListener( 'planeadded', function ( e ) {
-
-					console.log( 'plane added', e.data );
-
-				} );
-
-				renderer.xr.addEventListener( 'planeremoved', function ( e ) {
-
-					console.log( 'plane removed', e.data );
-
-				} );
-
-				renderer.xr.addEventListener( 'planechanged', function ( e ) {
-
-					console.log( 'plane changed', e.data );
-
-				} );
-
-				renderer.xr.addEventListener( 'planesdetected', function ( e ) {
-
-					const detectedPlanes = e.data;
-					const referenceSpace = renderer.xr.getReferenceSpace();
-
-					console.log( `Detected ${detectedPlanes.size} planes` );
-
-					detectedPlanes.forEach( plane => {
-
-						if ( planesAdded.has( plane ) ) return;
-
-						planesAdded.add( plane );
-						const frame = renderer.xr.getFrame();
-						const planePose = frame.getPose( plane.planeSpace, referenceSpace );
-						const polygon = plane.polygon;
+			//
 
-						let minX = Number.MAX_SAFE_INTEGER;
-						let maxX = Number.MIN_SAFE_INTEGER;
-						let minZ = Number.MAX_SAFE_INTEGER;
-						let maxZ = Number.MIN_SAFE_INTEGER;
+			const renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			renderer.setAnimationLoop( render );
+			renderer.xr.enabled = true;
+			document.body.appendChild( renderer.domElement );
 
-						polygon.forEach( point => {
+			document.body.appendChild( ARButton.createButton( renderer, {
+				requiredFeatures: [ 'plane-detection' ]
+			} ) );
 
-							minX = Math.min( minX, point.x );
-							maxX = Math.max( maxX, point.x );
-							minZ = Math.min( minZ, point.z );
-							maxZ = Math.max( maxZ, point.z );
+			window.addEventListener( 'resize', onWindowResize );
 
-						} );
+			//
 
-						const width = maxX - minX;
-						const height = maxZ - minZ;
+			const scene = new THREE.Scene();
 
-						const boxMesh = new THREE.Mesh(
-							new THREE.BoxGeometry( width, 0.01, height ),
-							new THREE.MeshBasicMaterial( { color: 0xffffff * Math.random() } )
-						);
-						boxMesh.matrixAutoUpdate = false;
-						boxMesh.matrix.fromArray( planePose.transform.matrix );
-						scene.add( boxMesh );
+			const planes = new XRPlanes( renderer );
+			scene.add( planes );
 
-					} );
+			const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 );
 
-				} );
+			const light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 );
+			light.position.set( 0.5, 1, 0.25 );
+			scene.add( light );
 
-			}
+			//
 
 			function onWindowResize() {
 
@@ -148,14 +70,6 @@
 
 			}
 
-			//
-
-			function animate() {
-
-				renderer.setAnimationLoop( render );
-
-			}
-
 			function render() {
 
 				renderer.render( scene, camera );

+ 1 - 63
src/renderers/webxr/WebXRManager.js

@@ -40,9 +40,6 @@ class WebXRManager extends EventDispatcher {
 		const controllers = [];
 		const controllerInputSources = [];
 
-		const planes = new Set();
-		const planesLastChangedTimes = new Map();
-
 		//
 
 		let userCamera = null;
@@ -651,12 +648,6 @@ class WebXRManager extends EventDispatcher {
 
 		};
 
-		this.getPlanes = function () {
-
-			return planes;
-
-		};
-
 		// Animation Loop
 
 		let onAnimationFrameCallback = null;
@@ -770,60 +761,7 @@ class WebXRManager extends EventDispatcher {
 
 			if ( frame.detectedPlanes ) {
 
-				scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } );
-
-				let planesToRemove = null;
-
-				for ( const plane of planes ) {
-
-					if ( ! frame.detectedPlanes.has( plane ) ) {
-
-						if ( planesToRemove === null ) {
-
-							planesToRemove = [];
-
-						}
-
-						planesToRemove.push( plane );
-
-					}
-
-				}
-
-				if ( planesToRemove !== null ) {
-
-					for ( const plane of planesToRemove ) {
-
-						planes.delete( plane );
-						planesLastChangedTimes.delete( plane );
-						scope.dispatchEvent( { type: 'planeremoved', data: plane } );
-
-					}
-
-				}
-
-				for ( const plane of frame.detectedPlanes ) {
-
-					if ( ! planes.has( plane ) ) {
-
-						planes.add( plane );
-						planesLastChangedTimes.set( plane, frame.lastChangedTime );
-						scope.dispatchEvent( { type: 'planeadded', data: plane } );
-
-					} else {
-
-						const lastKnownTime = planesLastChangedTimes.get( plane );
-
-						if ( plane.lastChangedTime > lastKnownTime ) {
-
-							planesLastChangedTimes.set( plane, plane.lastChangedTime );
-							scope.dispatchEvent( { type: 'planechanged', data: plane } );
-
-						}
-
-					}
-
-				}
+				scope.dispatchEvent( { type: 'planesdetected', data: frame } );
 
 			}