diff --git a/examples/files.json b/examples/files.json index 62cd99178c3e83..e9672f03d8eefd 100644 --- a/examples/files.json +++ b/examples/files.json @@ -356,6 +356,7 @@ "webxr_ar_hittest", "webxr_ar_lighting", "webxr_ar_paint", + "webxr_ar_plane_detection", "webxr_vr_ballshooter", "webxr_vr_cubes", "webxr_vr_dragging", diff --git a/examples/screenshots/webxr_ar_plane_detection.jpg b/examples/screenshots/webxr_ar_plane_detection.jpg new file mode 100644 index 00000000000000..001fe203e0b94e Binary files /dev/null and b/examples/screenshots/webxr_ar_plane_detection.jpg differ diff --git a/examples/webxr_ar_plane_detection.html b/examples/webxr_ar_plane_detection.html new file mode 100644 index 00000000000000..053284e6f1efce --- /dev/null +++ b/examples/webxr_ar_plane_detection.html @@ -0,0 +1,167 @@ + + + + three.js ar - plane detection + + + + + + +
+ three.js ar - plane detection
(Chrome Android 81+) +
+ + + + + + + + + + diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js index ebbdff44eaa24a..89b1df0e564f96 100644 --- a/src/renderers/webxr/WebXRManager.js +++ b/src/renderers/webxr/WebXRManager.js @@ -43,6 +43,9 @@ class WebXRManager extends EventDispatcher { const controllers = []; const controllerInputSources = []; + const planes = new Set(); + const planesLastChangedTimes = new Map(); + // const cameraL = new PerspectiveCamera(); @@ -600,6 +603,12 @@ class WebXRManager extends EventDispatcher { }; + this.getPlanes = function () { + + return planes; + + }; + // Animation Loop let onAnimationFrameCallback = null; @@ -708,6 +717,65 @@ class WebXRManager extends EventDispatcher { if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); + 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 } ); + + } + + } + + } + + } + xrFrame = null; }