Skip to content

Commit 419bfc2

Browse files
authored
WebXRManager: Refactored planes code. (#26098)
1 parent 2b09a2c commit 419bfc2

File tree

5 files changed

+110
-178
lines changed

5 files changed

+110
-178
lines changed

docs/api/en/renderers/webxr/WebXRManager.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@ <h3>[method:Group getHand]( [param:Integer index] )</h3>
9292
no physical controllers are used.
9393
</p>
9494

95-
<h3>[method:Set getPlanes]()</h3>
96-
<p>Returns the set of planes detected by WebXR's plane detection API.</p>
97-
9895
<h3>[method:String getReferenceSpace]()</h3>
9996
<p>Returns the reference space.</p>
10097

docs/api/zh/renderers/webxr/WebXRManager.html

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,6 @@ <h3>[method:Group getHand]( [param:Integer index] )</h3>
7474
返回代表XR控制器所谓的*手或关节*空间的[page:Group 组]。在不使用物理控制器时,使用此空间可视化用户的手。
7575
</p>
7676

77-
<h3>[method:Set getPlanes]()</h3>
78-
<p>
79-
返回由 WebXR 的平面检测 API 检测到的平面集。
80-
</p>
81-
8277
<h3>[method:String getReferenceSpace]()</h3>
8378
<p>
8479
返回参考空间。

examples/jsm/webxr/XRPlanes.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import {
2+
BoxGeometry,
3+
Matrix4,
4+
Mesh,
5+
MeshBasicMaterial,
6+
Object3D
7+
} from 'three';
8+
9+
class XRPlanes extends Object3D {
10+
11+
constructor( renderer ) {
12+
13+
super();
14+
15+
const geometry = new BoxGeometry();
16+
const matrix = new Matrix4();
17+
18+
const currentPlanes = new Map();
19+
20+
const xr = renderer.xr;
21+
22+
xr.addEventListener( 'planesdetected', event => {
23+
24+
const frame = event.data;
25+
const planes = frame.detectedPlanes;
26+
27+
const referenceSpace = xr.getReferenceSpace();
28+
29+
for ( const [ plane, mesh ] of currentPlanes ) {
30+
31+
if ( planes.has( plane ) === false ) {
32+
33+
mesh.material.dispose();
34+
this.remove( mesh );
35+
36+
currentPlanes.delete( plane );
37+
38+
}
39+
40+
}
41+
42+
for ( const plane of planes ) {
43+
44+
if ( currentPlanes.has( plane ) === false ) {
45+
46+
const pose = frame.getPose( plane.planeSpace, referenceSpace );
47+
matrix.fromArray( pose.transform.matrix );
48+
49+
const polygon = plane.polygon;
50+
51+
let minX = Number.MAX_SAFE_INTEGER;
52+
let maxX = Number.MIN_SAFE_INTEGER;
53+
let minZ = Number.MAX_SAFE_INTEGER;
54+
let maxZ = Number.MIN_SAFE_INTEGER;
55+
56+
for ( const point of polygon ) {
57+
58+
minX = Math.min( minX, point.x );
59+
maxX = Math.max( maxX, point.x );
60+
minZ = Math.min( minZ, point.z );
61+
maxZ = Math.max( maxZ, point.z );
62+
63+
}
64+
65+
const width = maxX - minX;
66+
const height = maxZ - minZ;
67+
68+
const material = new MeshBasicMaterial( { color: 0xffffff * Math.random() } );
69+
70+
const mesh = new Mesh( geometry, material );
71+
mesh.position.setFromMatrixPosition( matrix );
72+
mesh.quaternion.setFromRotationMatrix( matrix );
73+
mesh.scale.set( width, 0.01, height );
74+
this.add( mesh );
75+
76+
currentPlanes.set( plane, mesh );
77+
78+
}
79+
80+
}
81+
82+
} );
83+
84+
}
85+
86+
}
87+
88+
export { XRPlanes };

examples/webxr_ar_plane_detection.html

Lines changed: 21 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -29,115 +29,37 @@
2929

3030
import * as THREE from 'three';
3131
import { ARButton } from 'three/addons/webxr/ARButton.js';
32+
import { XRPlanes } from 'three/addons/webxr/XRPlanes.js';
3233

33-
let camera, scene, renderer;
34-
35-
init();
36-
animate();
37-
38-
const planesAdded = new Set();
39-
40-
function init() {
41-
42-
const container = document.createElement( 'div' );
43-
document.body.appendChild( container );
44-
45-
scene = new THREE.Scene();
46-
47-
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 );
48-
49-
const light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 );
50-
light.position.set( 0.5, 1, 0.25 );
51-
scene.add( light );
52-
53-
//
54-
55-
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
56-
renderer.setPixelRatio( window.devicePixelRatio );
57-
renderer.setSize( window.innerWidth, window.innerHeight );
58-
renderer.xr.enabled = true;
59-
container.appendChild( renderer.domElement );
60-
61-
//
62-
63-
document.body.appendChild( ARButton.createButton( renderer, {
64-
requiredFeatures: [ 'plane-detection' ]
65-
} ) );
66-
67-
//
68-
69-
window.addEventListener( 'resize', onWindowResize );
70-
71-
renderer.xr.addEventListener( 'sessionstart', function () {
72-
73-
camera.position.set( 0, 0, 0 );
74-
75-
} );
76-
77-
renderer.xr.addEventListener( 'planeadded', function ( e ) {
78-
79-
console.log( 'plane added', e.data );
80-
81-
} );
82-
83-
renderer.xr.addEventListener( 'planeremoved', function ( e ) {
84-
85-
console.log( 'plane removed', e.data );
86-
87-
} );
88-
89-
renderer.xr.addEventListener( 'planechanged', function ( e ) {
90-
91-
console.log( 'plane changed', e.data );
92-
93-
} );
94-
95-
renderer.xr.addEventListener( 'planesdetected', function ( e ) {
96-
97-
const detectedPlanes = e.data;
98-
const referenceSpace = renderer.xr.getReferenceSpace();
99-
100-
console.log( `Detected ${detectedPlanes.size} planes` );
101-
102-
detectedPlanes.forEach( plane => {
103-
104-
if ( planesAdded.has( plane ) ) return;
105-
106-
planesAdded.add( plane );
107-
const frame = renderer.xr.getFrame();
108-
const planePose = frame.getPose( plane.planeSpace, referenceSpace );
109-
const polygon = plane.polygon;
34+
//
11035

111-
let minX = Number.MAX_SAFE_INTEGER;
112-
let maxX = Number.MIN_SAFE_INTEGER;
113-
let minZ = Number.MAX_SAFE_INTEGER;
114-
let maxZ = Number.MIN_SAFE_INTEGER;
36+
const renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
37+
renderer.setPixelRatio( window.devicePixelRatio );
38+
renderer.setSize( window.innerWidth, window.innerHeight );
39+
renderer.setAnimationLoop( render );
40+
renderer.xr.enabled = true;
41+
document.body.appendChild( renderer.domElement );
11542

116-
polygon.forEach( point => {
43+
document.body.appendChild( ARButton.createButton( renderer, {
44+
requiredFeatures: [ 'plane-detection' ]
45+
} ) );
11746

118-
minX = Math.min( minX, point.x );
119-
maxX = Math.max( maxX, point.x );
120-
minZ = Math.min( minZ, point.z );
121-
maxZ = Math.max( maxZ, point.z );
47+
window.addEventListener( 'resize', onWindowResize );
12248

123-
} );
49+
//
12450

125-
const width = maxX - minX;
126-
const height = maxZ - minZ;
51+
const scene = new THREE.Scene();
12752

128-
const boxMesh = new THREE.Mesh(
129-
new THREE.BoxGeometry( width, 0.01, height ),
130-
new THREE.MeshBasicMaterial( { color: 0xffffff * Math.random() } )
131-
);
132-
boxMesh.matrixAutoUpdate = false;
133-
boxMesh.matrix.fromArray( planePose.transform.matrix );
134-
scene.add( boxMesh );
53+
const planes = new XRPlanes( renderer );
54+
scene.add( planes );
13555

136-
} );
56+
const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 );
13757

138-
} );
58+
const light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 );
59+
light.position.set( 0.5, 1, 0.25 );
60+
scene.add( light );
13961

140-
}
62+
//
14163

14264
function onWindowResize() {
14365

@@ -148,14 +70,6 @@
14870

14971
}
15072

151-
//
152-
153-
function animate() {
154-
155-
renderer.setAnimationLoop( render );
156-
157-
}
158-
15973
function render() {
16074

16175
renderer.render( scene, camera );

src/renderers/webxr/WebXRManager.js

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ class WebXRManager extends EventDispatcher {
4040
const controllers = [];
4141
const controllerInputSources = [];
4242

43-
const planes = new Set();
44-
const planesLastChangedTimes = new Map();
45-
4643
//
4744

4845
let userCamera = null;
@@ -651,12 +648,6 @@ class WebXRManager extends EventDispatcher {
651648

652649
};
653650

654-
this.getPlanes = function () {
655-
656-
return planes;
657-
658-
};
659-
660651
// Animation Loop
661652

662653
let onAnimationFrameCallback = null;
@@ -770,60 +761,7 @@ class WebXRManager extends EventDispatcher {
770761

771762
if ( frame.detectedPlanes ) {
772763

773-
scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } );
774-
775-
let planesToRemove = null;
776-
777-
for ( const plane of planes ) {
778-
779-
if ( ! frame.detectedPlanes.has( plane ) ) {
780-
781-
if ( planesToRemove === null ) {
782-
783-
planesToRemove = [];
784-
785-
}
786-
787-
planesToRemove.push( plane );
788-
789-
}
790-
791-
}
792-
793-
if ( planesToRemove !== null ) {
794-
795-
for ( const plane of planesToRemove ) {
796-
797-
planes.delete( plane );
798-
planesLastChangedTimes.delete( plane );
799-
scope.dispatchEvent( { type: 'planeremoved', data: plane } );
800-
801-
}
802-
803-
}
804-
805-
for ( const plane of frame.detectedPlanes ) {
806-
807-
if ( ! planes.has( plane ) ) {
808-
809-
planes.add( plane );
810-
planesLastChangedTimes.set( plane, frame.lastChangedTime );
811-
scope.dispatchEvent( { type: 'planeadded', data: plane } );
812-
813-
} else {
814-
815-
const lastKnownTime = planesLastChangedTimes.get( plane );
816-
817-
if ( plane.lastChangedTime > lastKnownTime ) {
818-
819-
planesLastChangedTimes.set( plane, plane.lastChangedTime );
820-
scope.dispatchEvent( { type: 'planechanged', data: plane } );
821-
822-
}
823-
824-
}
825-
826-
}
764+
scope.dispatchEvent( { type: 'planesdetected', data: frame } );
827765

828766
}
829767

0 commit comments

Comments
 (0)