-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebXR Plane Detection #3068
Merged
willeastcott
merged 17 commits into
playcanvas:master
from
Maksims:webxr-plane-detection
Jun 15, 2021
Merged
WebXR Plane Detection #3068
Changes from 6 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
b17be69
webxr plane detection
Maksims 025aa9c
webxr plane detection imrpoved docs
Maksims 6a23b19
fix
Maksims b539c60
fix typescript-issues
Maksims 952fc46
comments to clarify behaviour
Maksims ed973bf
Merge branch 'master' of github.com:playcanvas/engine into webxr-plan…
Maksims 1b4060a
Merge branch 'master' into webxr-plane-detection
Maksims cd69a99
Update src/xr/xr-plane-detection.js
willeastcott 62d0ad5
Update src/xr/xr-plane-detection.js
willeastcott 10da775
Update src/xr/xr-plane-detection.js
willeastcott edb1087
Update src/xr/xr-plane.js
willeastcott a834faa
Update src/xr/xr-plane-detection.js
willeastcott 3965e96
Update src/xr/xr-plane.js
willeastcott 939b3b9
Update src/xr/xr-plane.js
willeastcott 4c600d8
Update src/xr/xr-plane.js
willeastcott a6a39d2
Update xr-manager.js
Maksims bb3dbac
Update component.js
Maksims File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import { EventHandler } from '../core/event-handler.js'; | ||
import { XrPlane } from './xr-plane.js'; | ||
|
||
/** | ||
* @class | ||
* @name XrPlaneDetection | ||
* @classdesc Plane Detection provides the ability to detect real world surfaces based on estimations of underlying AR system. | ||
* @description Plane Detection provides the ability to detect real world surfaces based on estimations of underlying AR system. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @param {XrManager} manager - WebXR Manager. | ||
* @property {boolean} supported True if Plane Detection is supported. | ||
* @property {boolean} available True if Plane Detection is available. This property can be set to true only during running session. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @property {XrPlane[]|null} planes List of {@link XrPlane} that contain individual plane information, or null if plane detection isn't available. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @example | ||
* // start session with plane detection enabled | ||
* app.xr.start(camera, pc.XRTYPE_VR, pc.XRSPACE_LOCALFLOOR, { | ||
* planeDetection: true | ||
* }); | ||
* @example | ||
* app.xr.planeDetection.on('add', function (plane) { | ||
* // new plane been added | ||
* }); | ||
*/ | ||
class XrPlaneDetection extends EventHandler { | ||
constructor(manager) { | ||
super(); | ||
|
||
this._manager = manager; | ||
this._supported = !! window.XRPlane; | ||
this._available = false; | ||
|
||
// key - XRPlane (native plane does not have ID's) | ||
// value - XrPlane | ||
this._planesIndex = new Map(); | ||
Maksims marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
this._planes = null; | ||
|
||
if (this._supported) { | ||
this._manager.on('end', this._onSessionEnd, this); | ||
} | ||
} | ||
|
||
/** | ||
* @event | ||
* @name XrPlaneDetection#available | ||
* @description Fired when plane detection becomes available. | ||
*/ | ||
|
||
/** | ||
* @event | ||
* @name XrPlaneDetection#unavailable | ||
* @description Fired when plane detection becomes unavailable. | ||
*/ | ||
|
||
/** | ||
* @event | ||
* @name XrPlaneDetection#add | ||
* @description Fired when new {@link XrPlane} is added to the list. | ||
* @param {XrPlane} plane - Plane that has been added. | ||
* @example | ||
* app.xr.planeDetection.on('add', function (plane) { | ||
* // new plane is added | ||
* }); | ||
*/ | ||
|
||
/** | ||
* @event | ||
* @name XrPlaneDetection#remove | ||
* @description Fired when a {@link XrPlane} is removed to the list. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @param {XrPlane} plane - Plane that has been removed. | ||
* @example | ||
* app.xr.planeDetection.on('remove', function (plane) { | ||
* // new plane is removed | ||
* }); | ||
*/ | ||
|
||
_onSessionEnd() { | ||
for (let i = 0; i < this._planes.length; i++) { | ||
this._planes[i].destroy(); | ||
} | ||
this._planesIndex.clear(); | ||
this._planes = null; | ||
|
||
if (this._available) { | ||
this._available = false; | ||
this.fire('unavailable'); | ||
} | ||
} | ||
|
||
update(frame) { | ||
let detectedPlanes; | ||
|
||
if (! this._available) { | ||
try { | ||
detectedPlanes = frame.detectedPlanes; | ||
this._planes = []; | ||
this._available = true; | ||
this.fire('available'); | ||
} catch (ex) { | ||
return; | ||
} | ||
} else { | ||
detectedPlanes = frame.detectedPlanes; | ||
} | ||
|
||
// iterate through indexed planes | ||
for (const [xrPlane, plane] of this._planesIndex) { | ||
Maksims marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (detectedPlanes.has(xrPlane)) | ||
continue; | ||
|
||
// if indexed plane is not listed in detectedPlanes anymore | ||
// then remove it | ||
this._planesIndex.delete(xrPlane); | ||
this._planes.splice(this._planes.indexOf(plane), 1); | ||
plane.destroy(); | ||
this.fire('remove', plane); | ||
} | ||
|
||
// iterate through detected planes | ||
for (const xrPlane of detectedPlanes) { | ||
Maksims marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let plane = this._planesIndex.get(xrPlane); | ||
|
||
if (! plane) { | ||
// detected plane is not indexed | ||
// then create new XrPlane | ||
plane = new XrPlane(this, xrPlane); | ||
this._planesIndex.set(xrPlane, plane); | ||
this._planes.push(plane); | ||
plane.update(frame); | ||
this.fire('add', plane); | ||
} else { | ||
// if already indexed, just update | ||
plane.update(frame); | ||
} | ||
} | ||
} | ||
|
||
get supported() { | ||
return this._supported; | ||
} | ||
|
||
get available() { | ||
return this._available; | ||
} | ||
|
||
get planes() { | ||
return this._planes; | ||
} | ||
} | ||
|
||
export { XrPlaneDetection }; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { EventHandler } from '../core/event-handler.js'; | ||
import { Vec3 } from '../math/vec3.js'; | ||
import { Quat } from '../math/quat.js'; | ||
|
||
let ids = 0; | ||
|
||
/** | ||
* @class | ||
* @name XrPlane | ||
* @classdesc Detected Plane instance that provides position, rotation and polygon points. Plane is a subject to change during its lifetime. | ||
* @description Detected Plane instance that provides position, rotation and polygon points. Plane is a subject to change during its lifetime. | ||
* @param {XrPlaneDetection} planeDetection - Plane detection system. | ||
* @param {object} xrPlane - XRPlane that is instantiated by WebXR system. | ||
* @property {number} id Unique identifier of a plane. | ||
* @property {string|null} orientation Plane's pecific orientation (horizontal or vertical) or null if orientation is anything else. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
class XrPlane extends EventHandler { | ||
constructor(planeDetection, xrPlane) { | ||
super(); | ||
|
||
this._id = ++ids; | ||
|
||
this._planeDetection = planeDetection; | ||
this._manager = this._planeDetection._manager; | ||
|
||
this._xrPlane = xrPlane; | ||
this._lastChangedTime = this._xrPlane.lastChangedTime; | ||
this._orientation = this._xrPlane.orientation; | ||
|
||
this._position = new Vec3(); | ||
this._rotation = new Quat(); | ||
} | ||
|
||
/** | ||
* @event | ||
* @name XrPlane#remove | ||
* @description Fired when {@link XrPlane} is removed. | ||
* @example | ||
* plane.once('remove', function () { | ||
* // plane is not available anymore | ||
* }); | ||
*/ | ||
|
||
/** | ||
* @event | ||
* @name XrPlane#change | ||
* @description Fired when {@link XrPlane} attributes such as: orientation and/or points have been changed. Position and Rotation can change at any time without triggering `change` event. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @example | ||
* plane.on('change', function () { | ||
* // plane has been changed | ||
* }); | ||
*/ | ||
|
||
destroy() { | ||
this.fire('remove'); | ||
} | ||
|
||
update(frame) { | ||
const pose = frame.getPose(this._xrPlane.planeSpace, this._manager._referenceSpace); | ||
if (pose) { | ||
this._position.copy(pose.transform.position); | ||
this._rotation.copy(pose.transform.orientation); | ||
} | ||
|
||
// has not changed | ||
if (this._lastChangedTime !== this._xrPlane.lastChangedTime) { | ||
this._lastChangedTime = this._xrPlane.lastChangedTime; | ||
|
||
// attributes have been changed | ||
this.fire('change'); | ||
} | ||
} | ||
|
||
/** | ||
* @function | ||
* @name XrPlane#getPosition | ||
* @description Get the world space position of a plane. | ||
* @returns {Vec3} The world space position of a plane. | ||
*/ | ||
getPosition() { | ||
return this._position; | ||
} | ||
|
||
/** | ||
* @function | ||
* @name XrPlane#getRotation | ||
* @description Get the world space rotation of a plane. | ||
* @returns {Vec3} The world space rotation of a plane. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
getRotation() { | ||
return this._rotation; | ||
} | ||
mvaligursky marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
get id() { | ||
return this.id; | ||
} | ||
|
||
get orientation() { | ||
return this._orientation; | ||
} | ||
|
||
/** | ||
* @name XrPlane#points | ||
* @type {object[]} | ||
* @description List of DOMPointReadOnly objects that is an object with `x y z` properties that define local point of a planes polygon. | ||
willeastcott marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @example | ||
* // prepare reusable objects | ||
* var vecA = new pc.Vec3(); | ||
* var vecB = new pc.Vec3(); | ||
* var color = new pc.Color(1, 1, 1); | ||
* | ||
* // update Mat4 to plane position and rotation | ||
* transform.setTRS(plane.getPosition(), plane.getRotation(), pc.Vec3.ONE); | ||
* | ||
* // draw lines between points | ||
* for (var i = 0; i < plane.points.length; i++) { | ||
* vecA.copy(plane.points[i]); | ||
* vecB.copy(plane.points[(i + 1) % plane.points.length]); | ||
* | ||
* // transform from planes local to world coords | ||
* transform.transformPoint(vecA, vecA); | ||
* transform.transformPoint(vecB, vecB); | ||
* | ||
* // render line | ||
* app.renderLine(vecA, vecB, color); | ||
* } | ||
*/ | ||
get points() { | ||
return this._xrPlane.polygon; | ||
} | ||
} | ||
|
||
export { XrPlane }; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a duplicate of the param definition at line 190
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except that declaration is an object