From f94e7f7b7a54f28441b5beb601da539845159795 Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Wed, 14 Apr 2021 18:38:00 +0300 Subject: [PATCH 01/30] WebXR Anchors --- src/index.js | 2 + src/xr/xr-anchor.js | 102 +++++++++++++++++++++++++ src/xr/xr-anchors.js | 177 +++++++++++++++++++++++++++++++++++++++++++ src/xr/xr-manager.js | 6 ++ 4 files changed, 287 insertions(+) create mode 100644 src/xr/xr-anchor.js create mode 100644 src/xr/xr-anchors.js diff --git a/src/index.js b/src/index.js index acd021b0a65..e1abca08d16 100644 --- a/src/index.js +++ b/src/index.js @@ -297,6 +297,8 @@ export { XrHitTestSource } from './xr/xr-hit-test-source.js'; export { XrImageTracking } from './xr/xr-image-tracking.js'; export { XrTrackedImage } from './xr/xr-tracked-image.js'; export { XrDomOverlay } from './xr/xr-dom-overlay.js'; +export { XrAnchors } from './xr/xr-anchors.js'; +export { XrAnchor } from './xr/xr-anchor.js'; // BACKWARDS COMPATIBILITY export * from './deprecated.js'; diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js new file mode 100644 index 00000000000..08a208d8fcb --- /dev/null +++ b/src/xr/xr-anchor.js @@ -0,0 +1,102 @@ +import { EventHandler } from '../core/event-handler.js'; + +import { Vec3 } from '../math/vec3.js'; +import { Quat } from '../math/quat.js'; + +/** + * @class + * @name XrAnchor + * @classdesc Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. + * @description Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. + * @param {XrAnchors} anchors - Anchors manager. + * @property {object} xrAndhor native XRAnchor object that is provided by WebXR API. + */ +class XrAnchor extends EventHandler { + constructor(anchors, xrAnchor) { + super(); + + this._anchors = anchors; + this._xrAnchor = xrAnchor; + + this._position = new Vec3(); + this._rotation = new Quat(); + } + + /** + * @event + * @name XrAnchor#remove + * @description Fired when {@link XrAnchor} is removed. + * @example + * // once anchor is removed + * anchor.once('remove', function () { + * // destroy its related entity + * entity.destroy(); + * }); + */ + + /** + * @event + * @name XrAnchor#change + * @description Fired when {@link XrAnchor}'s position and/or rotation is changed. + * @example + * anchor.on('change', function () { + * // anchor has been updated + * entity.setPosition(anchor.getPosition()); + * entity.setRotation(anchor.getRotation()); + * }); + */ + + /** + * @function + * @name XrAnchor#remove + * @description Remove an anchor from tracking. + */ + remove() { + this._anchors._index.delete(this._xrAnchor); + + const ind = this._anchors._list.indexOf(this); + if (ind !== -1) this._anchors._list.splice(ind, 1); + + this._xrAnchor = null; + + this.fire('remove'); + this._anchors.fire('remove', this); + } + + update(frame) { + if (! this._xrAnchor) + return; + + const pose = frame.getPose(this._xrAnchor.anchorSpace, this._anchors.manager._referenceSpace); + if (pose) { + if (this._position.equals(pose.transform.position) && this._rotation.equals(pose.transform.orientation)) + return; + + this._position.copy(pose.transform.position); + this._rotation.copy(pose.transform.orientation); + this.fire('change'); + } + } + + /** + * @function + * @name XrAnchor#getPosition + * @description Get the world space position of an anchor. + * @returns {Vec3} The world space position of an anchor. + */ + getPosition() { + return this._position; + } + + /** + * @function + * @name XrAnchor#getRotation + * @description Get the world space rotation of an anchor. + * @returns {Quat} The world space rotation of an anchor. + */ + getRotation() { + return this._rotation; + } +} + +export { XrAnchor }; diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js new file mode 100644 index 00000000000..d9fc40382dd --- /dev/null +++ b/src/xr/xr-anchors.js @@ -0,0 +1,177 @@ +import { EventHandler } from '../core/event-handler.js'; +import { XrAnchor } from './xr-anchor.js'; + +/** + * @class + * @name XrAnchors + * @classdesc Anchor provides an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by underlying AR system, such that the anchor remain aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer sessions with lots of movement. + * @description Anchor provides an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by underlying AR system, such that the anchor remain aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer sessions with lots of movement. + * @param {XrManager} manager - WebXR Manager. + * @property {boolean} supported True if Anchors are supported. + * @property {XrAnchor[]} anchors List of active {@link XrAnchor}'s. + */ +class XrAnchors extends EventHandler { + constructor(manager) { + super(); + + this.manager = manager; + this._supported = !! window.XRAnchor; + + // list of anchor creation requests + this._creationQueue = []; + + // key - XRAnchor (native anchor does not have ID's) + // value - XrAnchor + this._index = new Map(); + this._list = null; + + // map of callbacks to XRAnchor's, + // so that we can call callback + // once anchor is first time updated with a pose + // + // key - XRAnchor + // value - function + this._callbacks = new Map(); + + if (this._supported) { + this.manager.on('start', this._onSessionStart, this); + this.manager.on('end', this._onSessionEnd, this); + } + } + + /** + * @event + * @name XrAnchors#error + * @param {Error} error - Error object related to a failure of anchors. + * @description Fired when anchor failed to be created. + */ + + /** + * @event + * @name XrAnchors#add + * @description Fired when new {@link XrAnchor} is added. + * @param {XrAnchor} anchor - Anchor that has been added. + * @example + * app.xr.anchors.on('add', function (anchor) { + * // new anchor is added + * }); + */ + + /** + * @event + * @name XrAnchors#remove + * @description Fired when {@link XrAnchor} is removed. + * @param {XrAnchor} anchor - Anchor that has been removed. + * @example + * app.xr.anchors.on('remove', function (anchor) { + * // anchor that is removed + * }); + */ + + _onSessionStart() { + this._list = []; + } + + _onSessionEnd() { + // clear anchor creation queue + for (let i = 0; i < this._creationQueue.length; i++) { + if (! this._creationQueue[i].callback) + continue; + + this._creationQueue[i].callback(new Error('session ended'), null); + } + this._creationQueue.length = 0; + + // remove all anchors + if (this._list) { + let i = this._list.length; + while (i--) { + this._list[i].remove(); + } + this._list = null; + } + } + + /** + * @function + * @name XrAnchors#create + * @description Create anchor with position and rotation, with a callback. + * @param {Vec3} position - Position for an anchor + * @param {Quat} [rotation] - Rotastion for an anchor + * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created + * @example + * // image with width of 20cm (0.2m) + * app.xr.imageTracking.add(bookCoverImg, 0.2); + */ + create(position, rotation, callback) { + this._creationQueue.push({ + transform: new XRRigidTransform(position, rotation), + callback: callback + }); + } + + update(frame) { + // check if need to create anchors + if (this._creationQueue.length) { + for (let i = 0; i < this._creationQueue.length; i++) { + const request = this._creationQueue[i]; + + frame.createAnchor(request.transform, this.manager._referenceSpace) + .then((xrAnchor) => { + if (request.callback) + this._callbacks.set(xrAnchor, request.callback); + }) + .catch((ex) => { + if (request.callback) + request.callback(ex, null); + + this.fire('error', ex); + }); + } + + this._creationQueue.length = 0; + } + + // check if removed + for (const [xrAnchor, anchor] of this._index) { + if (frame.trackedAnchors.has(xrAnchor)) + continue; + + anchor.remove(); + } + + // update existing anchors + for (let i = 0; i < this._list.length; i++) { + this._list[i].update(frame); + } + + // check if added + for (const xrAnchor of frame.trackedAnchors) { + if (this._index.has(xrAnchor)) + continue; + + const anchor = new XrAnchor(this, xrAnchor); + this._index.set(xrAnchor, anchor); + this._list.push(anchor); + anchor.update(frame); + + const callback = this._callbacks.get(xrAnchor); + if (callback) { + this._callbacks.delete(xrAnchor); + callback(null, anchor); + } + + this.fire('add', anchor); + } + } + + get supported() { + return this._supported; + } + + get anchors() { + return this._list; + } +} + +export { XrAnchors }; diff --git a/src/xr/xr-manager.js b/src/xr/xr-manager.js index 17dd4ca33cd..4006045a752 100644 --- a/src/xr/xr-manager.js +++ b/src/xr/xr-manager.js @@ -13,6 +13,7 @@ import { XrLightEstimation } from './xr-light-estimation.js'; import { XrImageTracking } from './xr-image-tracking.js'; import { XrDomOverlay } from './xr-dom-overlay.js'; import { XrDepthSensing } from './xr-depth-sensing.js'; +import { XrAnchors } from './xr-anchors.js'; /** * @class @@ -61,6 +62,7 @@ class XrManager extends EventHandler { this.imageTracking = new XrImageTracking(this); this.input = new XrInput(this); this.lightEstimation = new XrLightEstimation(this); + this.anchors = new XrAnchors(this); this._camera = null; this.views = []; @@ -220,6 +222,7 @@ class XrManager extends EventHandler { opts.optionalFeatures.push('light-estimation'); opts.optionalFeatures.push('hit-test'); opts.optionalFeatures.push('depth-sensing'); + opts.optionalFeatures.push('anchors'); if (options && options.imageTracking) { opts.optionalFeatures.push('image-tracking'); @@ -516,6 +519,9 @@ class XrManager extends EventHandler { if (this.imageTracking.supported) this.imageTracking.update(frame); + + if (this.anchors.supported) + this.anchors.update(frame); } this.fire('update', frame); From 571f5d550f8c5bf1283c949ba055397400d44412 Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Wed, 14 Apr 2021 18:39:42 +0300 Subject: [PATCH 02/30] better wording --- src/xr/xr-anchors.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index d9fc40382dd..57ac6670cf9 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -4,8 +4,8 @@ import { XrAnchor } from './xr-anchor.js'; /** * @class * @name XrAnchors - * @classdesc Anchor provides an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by underlying AR system, such that the anchor remain aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer sessions with lots of movement. - * @description Anchor provides an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by underlying AR system, such that the anchor remain aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer sessions with lots of movement. + * @classdesc Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. + * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. * @property {XrAnchor[]} anchors List of active {@link XrAnchor}'s. From ab8229675b0c46227d13cf3b754104cd28db0fea Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Wed, 14 Apr 2021 18:41:11 +0300 Subject: [PATCH 03/30] better parameter name --- src/xr/xr-anchors.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 57ac6670cf9..fbb1713b282 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -8,7 +8,7 @@ import { XrAnchor } from './xr-anchor.js'; * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. - * @property {XrAnchor[]} anchors List of active {@link XrAnchor}'s. + * @property {XrAnchor[]} list List of active {@link XrAnchor}'s. */ class XrAnchors extends EventHandler { constructor(manager) { @@ -169,7 +169,7 @@ class XrAnchors extends EventHandler { return this._supported; } - get anchors() { + get list() { return this._list; } } From 7e018ee46b61ef87dd3c242a5e8b1308aa884552 Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Wed, 14 Apr 2021 19:03:00 +0300 Subject: [PATCH 04/30] fix --- src/xr/xr-anchor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 08a208d8fcb..6b6790e6b7f 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -57,6 +57,8 @@ class XrAnchor extends EventHandler { const ind = this._anchors._list.indexOf(this); if (ind !== -1) this._anchors._list.splice(ind, 1); + this._xrAnchor.delete(); + this._xrAnchor = null; this.fire('remove'); From 1ce923096bf9be084da6a63c5433157549b759d2 Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Thu, 20 May 2021 20:08:57 +0300 Subject: [PATCH 05/30] fixes --- src/callbacks.js | 7 +++++++ src/framework/components/camera/component.js | 1 + src/xr/xr-anchors.js | 10 ++++++++-- src/xr/xr-manager.js | 5 ++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/callbacks.js b/src/callbacks.js index be07b276a4e..9f9ea80aa0e 100644 --- a/src/callbacks.js +++ b/src/callbacks.js @@ -197,3 +197,10 @@ * @param {Error|null} err - The Error object if failed to create hit test source or null. * @param {XrHitTestSource|null} hitTestSource - Object that provides access to hit results against real world geometry. */ + +/** + * @callback callbacks.XrAnchorCreate + * @description Callback used by {@link XrAnchors#create}. + * @param {Error|null} err - The Error object if failed to create an anchor or null. + * @param {XrAnchor|null} anchor - The anchor that is tracked against real world geometry. + */ diff --git a/src/framework/components/camera/component.js b/src/framework/components/camera/component.js index b670fb6c959..af2f96f415e 100644 --- a/src/framework/components/camera/component.js +++ b/src/framework/components/camera/component.js @@ -597,6 +597,7 @@ class CameraComponent extends Component { * @param {callbacks.XrError} [options.callback] - Optional callback function called once * the session is started. The callback has one argument Error - it is null if the XR * session started successfully. + * @param {boolean} [options.anchors] - Optional boolean to attempt to enable {@link XrAnchors}. * @param {object} [options.depthSensing] - Optional object with depth sensing parameters to attempt to enable {@link XrDepthSensing}. * @param {string} [options.depthSensing.usagePreference] - Optional usage preference for depth sensing, can be 'cpu-optimized' or 'gpu-optimized' (XRDEPTHSENSINGUSAGE_*), defaults to 'cpu-optimized'. Most preferred and supported will be chosen by the underlying depth sensing system. * @param {string} [options.depthSensing.dataFormatPreference] - Optional data format preference for depth sensing, can be 'luminance-alpha' or 'float32' (XRDEPTHSENSINGFORMAT_*), defaults to 'luminance-alpha'. Most preferred and supported will be chosen by the underlying depth sensing system. diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index fbb1713b282..4d3aadbf4ff 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -9,6 +9,10 @@ import { XrAnchor } from './xr-anchor.js'; * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. * @property {XrAnchor[]} list List of active {@link XrAnchor}'s. + * @example + * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { + * anchors: true + * }); */ class XrAnchors extends EventHandler { constructor(manager) { @@ -100,8 +104,10 @@ class XrAnchors extends EventHandler { * @param {Quat} [rotation] - Rotastion for an anchor * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created * @example - * // image with width of 20cm (0.2m) - * app.xr.imageTracking.add(bookCoverImg, 0.2); + * app.xr.anchors.create(position, rotation, function(err, anchor) { + * if (err) return; + * // new anchor has been created + * }); */ create(position, rotation, callback) { this._creationQueue.push({ diff --git a/src/xr/xr-manager.js b/src/xr/xr-manager.js index 5b07862e0be..8e917a99961 100644 --- a/src/xr/xr-manager.js +++ b/src/xr/xr-manager.js @@ -178,12 +178,15 @@ class XrManager extends EventHandler { * @example * button.on('click', function () { * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { + * anchors: true, + * imageTracking: true, * depthSensing: { } * }); * }); * @param {object} [options] - Object with additional options for XR session initialization. * @param {string[]} [options.optionalFeatures] - Optional features for XRSession start. It is used for getting access to additional WebXR spec extensions. * @param {callbacks.XrError} [options.callback] - Optional callback function called once session is started. The callback has one argument Error - it is null if successfully started XR session. + * @param {boolean} [options.anchors] - Optional boolean to attempt to enable {@link XrAnchors}. * @param {object} [options.depthSensing] - Optional object with depth sensing parameters to attempt to enable {@link XrDepthSensing}. * @param {string} [options.depthSensing.usagePreference] - Optional usage preference for depth sensing, can be 'cpu-optimized' or 'gpu-optimized' (XRDEPTHSENSINGUSAGE_*), defaults to 'cpu-optimized'. Most preferred and supported will be chosen by the underlying depth sensing system. * @param {string} [options.depthSensing.dataFormatPreference] - Optional data format preference for depth sensing, can be 'luminance-alpha' or 'float32' (XRDEPTHSENSINGFORMAT_*), defaults to 'luminance-alpha'. Most preferred and supported will be chosen by the underlying depth sensing system. @@ -237,7 +240,7 @@ class XrManager extends EventHandler { opts.domOverlay = { root: this.domOverlay.root }; } - if (options && options.anchors) { + if (options && options.anchors && this.anchors.supported) { opts.optionalFeatures.push('anchors'); } From a5c60599c06b2b7264e37e7c661c99398c079073 Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Fri, 21 May 2021 00:06:42 +0300 Subject: [PATCH 06/30] lint --- src/xr/xr-anchors.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 4d3aadbf4ff..b0db8d8fc8c 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -104,9 +104,10 @@ class XrAnchors extends EventHandler { * @param {Quat} [rotation] - Rotastion for an anchor * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created * @example - * app.xr.anchors.create(position, rotation, function(err, anchor) { - * if (err) return; - * // new anchor has been created + * app.xr.anchors.create(position, rotation, function (err, anchor) { + * if (! err) { + * // new anchor has been created + * } * }); */ create(position, rotation, callback) { From c46e237ccbc5af436271408f69b8426dbdffd83a Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Tue, 15 Jun 2021 14:30:02 +0300 Subject: [PATCH 07/30] Update xr-manager.js --- src/xr/xr-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-manager.js b/src/xr/xr-manager.js index e79d7791ac4..6f491729f80 100644 --- a/src/xr/xr-manager.js +++ b/src/xr/xr-manager.js @@ -557,7 +557,7 @@ class XrManager extends EventHandler { if (this.anchors.supported) this.anchors.update(frame); - + if (this.planeDetection.supported) this.planeDetection.update(frame); } From e138780f319ceb18f2b7cb7c7b93c4b05c7b54aa Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:15 +0100 Subject: [PATCH 08/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index b0db8d8fc8c..09cc51a53c4 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -8,7 +8,7 @@ import { XrAnchor } from './xr-anchor.js'; * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. - * @property {XrAnchor[]} list List of active {@link XrAnchor}'s. +* @property {XrAnchor[]} list Array of active {@link XrAnchor}s. * @example * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { * anchors: true From fead641008055268a7fc110a19471b6563d0cd6e Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:23 +0100 Subject: [PATCH 09/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 09cc51a53c4..c0234fc6449 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -24,7 +24,7 @@ class XrAnchors extends EventHandler { // list of anchor creation requests this._creationQueue = []; - // key - XRAnchor (native anchor does not have ID's) + // key - XRAnchor (native anchor does not have an ID) // value - XrAnchor this._index = new Map(); this._list = null; From 16d56032563bebecefbaf2ba36415a413221e246 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:34 +0100 Subject: [PATCH 10/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index c0234fc6449..85223206b86 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -29,9 +29,8 @@ class XrAnchors extends EventHandler { this._index = new Map(); this._list = null; - // map of callbacks to XRAnchor's, - // so that we can call callback - // once anchor is first time updated with a pose + // map of callbacks to XRAnchors so that we can call its callback once an anchor is updated + // with a pose for the first time // // key - XRAnchor // value - function From 3d45f16acee2044705e468485e1b2fb0a44c933b Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:41 +0100 Subject: [PATCH 11/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 85223206b86..52e5814458c 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -52,7 +52,7 @@ class XrAnchors extends EventHandler { /** * @event * @name XrAnchors#add - * @description Fired when new {@link XrAnchor} is added. + * @description Fired when a new {@link XrAnchor} is added. * @param {XrAnchor} anchor - Anchor that has been added. * @example * app.xr.anchors.on('add', function (anchor) { From ab7d2fa431751ab9be1d48d962b8552c376faef5 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:46 +0100 Subject: [PATCH 12/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 52e5814458c..3e3e6f5a6d3 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -63,7 +63,7 @@ class XrAnchors extends EventHandler { /** * @event * @name XrAnchors#remove - * @description Fired when {@link XrAnchor} is removed. + * @description Fired when an {@link XrAnchor} is removed. * @param {XrAnchor} anchor - Anchor that has been removed. * @example * app.xr.anchors.on('remove', function (anchor) { From 1e9106a84d4d8a8a485704a3fbea27379e1f6b12 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:53 +0100 Subject: [PATCH 13/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 3e3e6f5a6d3..72124de71a2 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -98,7 +98,7 @@ class XrAnchors extends EventHandler { /** * @function * @name XrAnchors#create - * @description Create anchor with position and rotation, with a callback. + * @description Create anchor with position, rotation and a callback. * @param {Vec3} position - Position for an anchor * @param {Quat} [rotation] - Rotastion for an anchor * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created From c9a1ee00e7e7ca474501008e6199cd8b2bdd8de9 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:47:59 +0100 Subject: [PATCH 14/30] Update src/xr/xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 72124de71a2..7a804bfb720 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -100,7 +100,7 @@ class XrAnchors extends EventHandler { * @name XrAnchors#create * @description Create anchor with position, rotation and a callback. * @param {Vec3} position - Position for an anchor - * @param {Quat} [rotation] - Rotastion for an anchor + * @param {Quat} [rotation] - Rotation for an anchor * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created * @example * app.xr.anchors.create(position, rotation, function (err, anchor) { From 1bf096e4291eea038813f3b880ee30e8b97db45b Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:48:10 +0100 Subject: [PATCH 15/30] Update src/xr/xr-anchor.js --- src/xr/xr-anchor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 6b6790e6b7f..681d129deb8 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -37,7 +37,7 @@ class XrAnchor extends EventHandler { /** * @event * @name XrAnchor#change - * @description Fired when {@link XrAnchor}'s position and/or rotation is changed. + * @description Fired when an {@link XrAnchor}'s position and/or rotation is changed. * @example * anchor.on('change', function () { * // anchor has been updated From ca749af69efe38d4df0adaecd7d0907367dcad79 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:48:15 +0100 Subject: [PATCH 16/30] Update src/xr/xr-anchor.js --- src/xr/xr-anchor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 681d129deb8..3026c9d12e7 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -25,7 +25,7 @@ class XrAnchor extends EventHandler { /** * @event * @name XrAnchor#remove - * @description Fired when {@link XrAnchor} is removed. + * @description Fired when an {@link XrAnchor} is removed. * @example * // once anchor is removed * anchor.once('remove', function () { From 27a2e0afe8bddf75f8eebc945026a69467a11f5a Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:48:21 +0100 Subject: [PATCH 17/30] Update src/xr/xr-anchor.js --- src/xr/xr-anchor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 3026c9d12e7..434f61a16f9 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -8,7 +8,7 @@ import { Quat } from '../math/quat.js'; * @name XrAnchor * @classdesc Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. * @description Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. - * @param {XrAnchors} anchors - Anchors manager. + * @param {XrAnchors} anchors - Anchor manager. * @property {object} xrAndhor native XRAnchor object that is provided by WebXR API. */ class XrAnchor extends EventHandler { From b62c049a8ccf7ed9481aecbed1e805fc828d6988 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:48:27 +0100 Subject: [PATCH 18/30] Update src/xr/xr-anchor.js --- src/xr/xr-anchor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 434f61a16f9..29caa454f01 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -9,7 +9,7 @@ import { Quat } from '../math/quat.js'; * @classdesc Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. * @description Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. * @param {XrAnchors} anchors - Anchor manager. - * @property {object} xrAndhor native XRAnchor object that is provided by WebXR API. + * @property {object} xrAnchor native XRAnchor object that is provided by the WebXR API. */ class XrAnchor extends EventHandler { constructor(anchors, xrAnchor) { From 56a1d8592a6dfda1b0a230bb4f99a69df7fd871c Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Wed, 16 Jun 2021 00:48:32 +0100 Subject: [PATCH 19/30] Update src/xr/xr-anchor.js --- src/xr/xr-anchor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 29caa454f01..7110ca7209e 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -6,8 +6,8 @@ import { Quat } from '../math/quat.js'; /** * @class * @name XrAnchor - * @classdesc Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. - * @description Anchor provides position and rotation, that is updated by underlying AR system, that tries to better persist an anchor relative to evolving understanding of a real world. + * @classdesc An anchor keeps track of a position and rotation that is fixed relative to the real world. This allows the application to adjust the location of the virtual objects placed in the scene in a way that helps with maintaining the illusion that the placed objects are really present in the user’s environment. + * @description Creates an XrAnchor. * @param {XrAnchors} anchors - Anchor manager. * @property {object} xrAnchor native XRAnchor object that is provided by the WebXR API. */ From b0d94954311441f122063ae942e672a184bd6026 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Wed, 16 Jun 2021 15:07:13 +0300 Subject: [PATCH 20/30] Rename xr-anchors.js to xr-anchor.js --- src/xr/xr-anchor.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 7110ca7209e..5492221863a 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -24,11 +24,11 @@ class XrAnchor extends EventHandler { /** * @event - * @name XrAnchor#remove - * @description Fired when an {@link XrAnchor} is removed. + * @name XrAnchor#destroy + * @description Fired when an {@link XrAnchor} is destroyed. * @example - * // once anchor is removed - * anchor.once('remove', function () { + * // once anchor is destroyed + * anchor.once('destroy', function () { * // destroy its related entity * entity.destroy(); * }); @@ -48,10 +48,10 @@ class XrAnchor extends EventHandler { /** * @function - * @name XrAnchor#remove - * @description Remove an anchor from tracking. + * @name XrAnchor#destroy + * @description Destroy an anchor. */ - remove() { + destroy() { this._anchors._index.delete(this._xrAnchor); const ind = this._anchors._list.indexOf(this); @@ -61,8 +61,8 @@ class XrAnchor extends EventHandler { this._xrAnchor = null; - this.fire('remove'); - this._anchors.fire('remove', this); + this.fire('destroy'); + this._anchors.fire('destroy', this); } update(frame) { From 3b1f0aa4f05be132d17abccaf5c0d61c7d6578d5 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Wed, 16 Jun 2021 15:07:47 +0300 Subject: [PATCH 21/30] Update xr-anchors.js --- src/xr/xr-anchors.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index 7a804bfb720..e35bd4acbdb 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -62,12 +62,12 @@ class XrAnchors extends EventHandler { /** * @event - * @name XrAnchors#remove - * @description Fired when an {@link XrAnchor} is removed. - * @param {XrAnchor} anchor - Anchor that has been removed. + * @name XrAnchors#destroy + * @description Fired when an {@link XrAnchor} is destroyed. + * @param {XrAnchor} anchor - Anchor that has been destroyed. * @example - * app.xr.anchors.on('remove', function (anchor) { - * // anchor that is removed + * app.xr.anchors.on('destroy', function (anchor) { + * // anchor that is destroyed * }); */ @@ -85,11 +85,11 @@ class XrAnchors extends EventHandler { } this._creationQueue.length = 0; - // remove all anchors + // destroy all anchors if (this._list) { let i = this._list.length; while (i--) { - this._list[i].remove(); + this._list[i].destroy(); } this._list = null; } @@ -138,12 +138,12 @@ class XrAnchors extends EventHandler { this._creationQueue.length = 0; } - // check if removed + // check if destroyed for (const [xrAnchor, anchor] of this._index) { if (frame.trackedAnchors.has(xrAnchor)) continue; - anchor.remove(); + anchor.destroy(); } // update existing anchors From 47a2af100ec0f4e3d7c591b939e434a1ece5f43c Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Wed, 16 Jun 2021 15:08:28 +0300 Subject: [PATCH 22/30] Update xr-anchors.js --- src/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index e35bd4acbdb..c0a290c915d 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -8,7 +8,7 @@ import { XrAnchor } from './xr-anchor.js'; * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. -* @property {XrAnchor[]} list Array of active {@link XrAnchor}s. + * @property {XrAnchor[]} list Array of active {@link XrAnchor}s. * @example * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { * anchors: true From 5625bbccf00cb8351e34836eab731100e8226f4e Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Tue, 29 Jun 2021 19:18:37 +0300 Subject: [PATCH 23/30] fix warning --- src/framework/application.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/framework/application.js b/src/framework/application.js index 51b39e26c10..d5a421d3f4d 100644 --- a/src/framework/application.js +++ b/src/framework/application.js @@ -106,7 +106,6 @@ import { ApplicationStats } from './stats.js'; import { Entity } from './entity.js'; import { SceneRegistry } from './scene-registry.js'; import { SceneDepth } from './scene-depth.js'; -import { XRTYPE_VR } from "../xr/constants"; import { FILLMODE_FILL_WINDOW, FILLMODE_KEEP_ASPECT, From a90772583ecbd9fdea8d63330be9cfa91e7d9d8d Mon Sep 17 00:00:00 2001 From: Maksims Mihejevs Date: Thu, 1 Jul 2021 12:47:35 +0300 Subject: [PATCH 24/30] hide constructors from docs --- src/xr/xr-anchor.js | 1 + src/xr/xr-anchors.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/xr/xr-anchor.js b/src/xr/xr-anchor.js index 5492221863a..794153aebe2 100644 --- a/src/xr/xr-anchor.js +++ b/src/xr/xr-anchor.js @@ -8,6 +8,7 @@ import { Quat } from '../math/quat.js'; * @name XrAnchor * @classdesc An anchor keeps track of a position and rotation that is fixed relative to the real world. This allows the application to adjust the location of the virtual objects placed in the scene in a way that helps with maintaining the illusion that the placed objects are really present in the user’s environment. * @description Creates an XrAnchor. + * @hideconstructor * @param {XrAnchors} anchors - Anchor manager. * @property {object} xrAnchor native XRAnchor object that is provided by the WebXR API. */ diff --git a/src/xr/xr-anchors.js b/src/xr/xr-anchors.js index c0a290c915d..eeefab436af 100644 --- a/src/xr/xr-anchors.js +++ b/src/xr/xr-anchors.js @@ -6,6 +6,7 @@ import { XrAnchor } from './xr-anchor.js'; * @name XrAnchors * @classdesc Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. + * @hideconstructor * @param {XrManager} manager - WebXR Manager. * @property {boolean} supported True if Anchors are supported. * @property {XrAnchor[]} list Array of active {@link XrAnchor}s. From d9974bfdcf39bdc3a8192b3b4128efcc95bda28e Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Tue, 8 Aug 2023 19:00:47 +0300 Subject: [PATCH 25/30] update PR to match recent engine guidlines and some bug fixes --- src/framework/xr/xr-anchor.js | 68 +++++++++------- src/framework/xr/xr-anchors.js | 137 ++++++++++++++++++++++----------- src/framework/xr/xr-manager.js | 2 +- 3 files changed, 133 insertions(+), 74 deletions(-) diff --git a/src/framework/xr/xr-anchor.js b/src/framework/xr/xr-anchor.js index 54c94cfba90..3ed6cdf9a1f 100644 --- a/src/framework/xr/xr-anchor.js +++ b/src/framework/xr/xr-anchor.js @@ -4,29 +4,43 @@ import { Vec3 } from '../../core/math/vec3.js'; import { Quat } from '../../core/math/quat.js'; /** - * @class - * @name XrAnchor - * @classdesc An anchor keeps track of a position and rotation that is fixed relative to the real world. This allows the application to adjust the location of the virtual objects placed in the scene in a way that helps with maintaining the illusion that the placed objects are really present in the user’s environment. - * @description Creates an XrAnchor. - * @hideconstructor - * @param {import('./xr-anchors.js').XrAnchors} anchors - Anchor manager. - * @property {object} xrAnchor native XRAnchor object that is provided by the WebXR API. + * An anchor keeps track of a position and rotation that is fixed relative to the real world. + * This allows the application to adjust the location of the virtual objects placed in the + * scene in a way that helps with maintaining the illusion that the placed objects are really + * present in the user’s environment. + * + * @augments EventHandler + * @category XR */ class XrAnchor extends EventHandler { + /** + * @type {Vec3} + * @private + */ + _position = new Vec3(); + + /** + * @type {Quat} + * @private + */ + _rotation = new Quat(); + + /** + * @param {import('./xr-anchors.js').XrAnchors} anchors - Anchor manager. + * @param {object} xrAnchor - native XRAnchor object that is provided by WebXR API + * @hideconstructor + */ constructor(anchors, xrAnchor) { super(); this._anchors = anchors; this._xrAnchor = xrAnchor; - - this._position = new Vec3(); - this._rotation = new Quat(); } /** - * @event - * @name XrAnchor#destroy - * @description Fired when an {@link XrAnchor} is destroyed. + * Fired when an {@link XrAnchor} is destroyed. + * + * @event XrAnchor#destroy * @example * // once anchor is destroyed * anchor.once('destroy', function () { @@ -36,9 +50,9 @@ class XrAnchor extends EventHandler { */ /** - * @event - * @name XrAnchor#change - * @description Fired when an {@link XrAnchor}'s position and/or rotation is changed. + * Fired when an {@link XrAnchor}'s position and/or rotation is changed. + * + * @event XrAnchor#change * @example * anchor.on('change', function () { * // anchor has been updated @@ -48,26 +62,28 @@ class XrAnchor extends EventHandler { */ /** - * @function - * @name XrAnchor#destroy - * @description Destroy an anchor. + * Destroy an anchor. */ destroy() { + if (!this._xrAnchor) return; this._anchors._index.delete(this._xrAnchor); const ind = this._anchors._list.indexOf(this); if (ind !== -1) this._anchors._list.splice(ind, 1); this._xrAnchor.delete(); - this._xrAnchor = null; this.fire('destroy'); this._anchors.fire('destroy', this); } + /** + * @param {*} frame - XRFrame from requestAnimationFrame callback. + * @ignore + */ update(frame) { - if (! this._xrAnchor) + if (!this._xrAnchor) return; const pose = frame.getPose(this._xrAnchor.anchorSpace, this._anchors.manager._referenceSpace); @@ -82,9 +98,8 @@ class XrAnchor extends EventHandler { } /** - * @function - * @name XrAnchor#getPosition - * @description Get the world space position of an anchor. + * Get the world space position of an anchor. + * * @returns {Vec3} The world space position of an anchor. */ getPosition() { @@ -92,9 +107,8 @@ class XrAnchor extends EventHandler { } /** - * @function - * @name XrAnchor#getRotation - * @description Get the world space rotation of an anchor. + * Get the world space rotation of an anchor. + * * @returns {Quat} The world space rotation of an anchor. */ getRotation() { diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 1dfc8fcb6e8..1fd67b241ef 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -1,66 +1,93 @@ import { EventHandler } from '../../core/event-handler.js'; +import { platform } from '../../core/platform.js'; import { XrAnchor } from './xr-anchor.js'; /** - * @callback callbacks.XrAnchorCreate - * @description Callback used by {@link XrAnchors#create}. + * Callback used by {@link XrAnchors#create}. + * + * @callback XrAnchorCreate * @param {Error|null} err - The Error object if failed to create an anchor or null. * @param {XrAnchor|null} anchor - The anchor that is tracked against real world geometry. */ /** - * @class - * @name XrAnchors - * @classdesc Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. - * @description Anchors provide an ability to specify a point in the world that need to be updated to correctly reflect the evolving understanding of the world by the underlying AR system, such that the anchor remains aligned with the same place in the physical world. Anchors tend to persist better relative to the real world, especially during a longer session with lots of movement. - * @hideconstructor - * @param {import('./xr-manager.js').XrManager} manager - WebXR Manager. + * Anchors provide an ability to specify a point in the world that need to be updated to + * correctly reflect the evolving understanding of the world by the underlying AR system, + * such that the anchor remains aligned with the same place in the physical world. + * Anchors tend to persist better relative to the real world, especially during a longer + * session with lots of movement. + * * @property {boolean} supported True if Anchors are supported. * @property {XrAnchor[]} list Array of active {@link XrAnchor}s. - * @example + * @augments EventHandler + * @category XR + * ```javascript * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { * anchors: true * }); + * ``` */ class XrAnchors extends EventHandler { - constructor(manager) { - super(); + /** + * @type {boolean} + * @private + */ + _supported = platform.browser && !!window.XRAnchor; - this.manager = manager; - this._supported = !! window.XRAnchor; + /** + * List of anchor creation requests. + * + * @type {Array} + * @private + */ + _creationQueue = []; - // list of anchor creation requests - this._creationQueue = []; + /** + * @type {Map} + * @ignore + */ + _index = new Map(); - // key - XRAnchor (native anchor does not have an ID) - // value - XrAnchor - this._index = new Map(); - this._list = null; + /** + * @type {Array} + * @ignore + */ + _list = []; - // map of callbacks to XRAnchors so that we can call its callback once an anchor is updated - // with a pose for the first time - // - // key - XRAnchor - // value - function - this._callbacksAnchors = new Map(); + /** + * Map of callbacks to XRAnchors so that we can call its callback once + * an anchor is updated with a pose for the first time. + * + * @type {Map} + * @private + */ + _callbacksAnchors = new Map(); + + /** + * @param {import('./xr-manager.js').XrManager} manager - WebXR Manager. + * @hideconstructor + */ + constructor(manager) { + super(); + + this.manager = manager; if (this._supported) { - this.manager.on('start', this._onSessionStart, this); this.manager.on('end', this._onSessionEnd, this); } } /** - * @event - * @name XrAnchors#error + * Fired when anchor failed to be created. + * + * @event XrAnchors#error * @param {Error} error - Error object related to a failure of anchors. - * @description Fired when anchor failed to be created. */ /** - * @event - * @name XrAnchors#add - * @description Fired when a new {@link XrAnchor} is added. + * Fired when a new {@link XrAnchor} is added. + * + * @event XrAnchors#add * @param {XrAnchor} anchor - Anchor that has been added. * @example * app.xr.anchors.on('add', function (anchor) { @@ -69,9 +96,9 @@ class XrAnchors extends EventHandler { */ /** - * @event - * @name XrAnchors#destroy - * @description Fired when an {@link XrAnchor} is destroyed. + * Fired when an {@link XrAnchor} is destroyed. + * + * @event XrAnchors#destroy * @param {XrAnchor} anchor - Anchor that has been destroyed. * @example * app.xr.anchors.on('destroy', function (anchor) { @@ -79,14 +106,11 @@ class XrAnchors extends EventHandler { * }); */ - _onSessionStart() { - this._list = []; - } - + /** @private */ _onSessionEnd() { // clear anchor creation queue for (let i = 0; i < this._creationQueue.length; i++) { - if (! this._creationQueue[i].callback) + if (!this._creationQueue[i].callback) continue; this._creationQueue[i].callback(new Error('session ended'), null); @@ -99,17 +123,16 @@ class XrAnchors extends EventHandler { while (i--) { this._list[i].destroy(); } - this._list = null; + this._list.length = 0; } } /** - * @function - * @name XrAnchors#create - * @description Create anchor with position, rotation and a callback. + * Create anchor with position, rotation and a callback. + * * @param {import('../../core/math/vec3.js').Vec3} position - Position for an anchor * @param {import('../../core/math/quat.js').Quat} [rotation] - Rotation for an anchor - * @param {callbacks.XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created + * @param {XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created * @example * app.xr.anchors.create(position, rotation, function (err, anchor) { * if (! err) { @@ -119,11 +142,15 @@ class XrAnchors extends EventHandler { */ create(position, rotation, callback) { this._creationQueue.push({ - transform: new XRRigidTransform(position, rotation), + transform: new XRRigidTransform(position, rotation), // eslint-disable-line no-undef callback: callback }); } + /** + * @param {*} frame - XRFrame from requestAnimationFrame callback. + * @ignore + */ update(frame) { // check if need to create anchors if (this._creationQueue.length) { @@ -164,6 +191,14 @@ class XrAnchors extends EventHandler { if (this._index.has(xrAnchor)) continue; + try { + const tmp = xrAnchor.anchorSpace; // eslint-disable-line no-unused-vars + } catch (ex) { + // if anchorSpace is not available, then anchor is invalid + // and should not be created + continue; + } + const anchor = new XrAnchor(this, xrAnchor); this._index.set(xrAnchor, anchor); this._list.push(anchor); @@ -179,10 +214,20 @@ class XrAnchors extends EventHandler { } } + /** + * True if Anchors are supported. + * + * @type {boolean} + */ get supported() { return this._supported; } + /** + * List of available {@link XrAnchor}s. + * + * @type {Array} + */ get list() { return this._list; } diff --git a/src/framework/xr/xr-manager.js b/src/framework/xr/xr-manager.js index 91d0b3f187d..051ae143dc7 100644 --- a/src/framework/xr/xr-manager.js +++ b/src/framework/xr/xr-manager.js @@ -76,7 +76,7 @@ class XrManager extends EventHandler { /** * @type {XRReferenceSpace|null} - * @private + * @ignore */ _referenceSpace = null; From 2dc0c047a2049dba8798c3d7fbc7cf7eac7cfead Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Wed, 9 Aug 2023 17:13:27 +0300 Subject: [PATCH 26/30] ts.. --- package-lock.json | 7 +++++++ package.json | 1 + src/framework/xr/xr-anchors.js | 2 ++ 3 files changed, 10 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9592ebb56a6..569a235ac27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@rollup/plugin-strip": "^3.0.2", "@rollup/plugin-terser": "^0.4.3", "@rollup/pluginutils": "^5.0.2", + "@types/webxr": "^0.5.2", "@webgpu/types": "^0.1.34", "c8": "^8.0.0", "chai": "^4.3.7", @@ -2308,6 +2309,12 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, + "node_modules/@types/webxr": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.2.tgz", + "integrity": "sha512-szL74BnIcok9m7QwYtVmQ+EdIKwbjPANudfuvDrAF8Cljg9MKUlIoc1w5tjj9PMpeSH3U1Xnx//czQybJ0EfSw==", + "dev": true + }, "node_modules/@webgpu/types": { "version": "0.1.34", "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.34.tgz", diff --git a/package.json b/package.json index 767f9659aba..7d5d928e670 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "@rollup/plugin-strip": "^3.0.2", "@rollup/plugin-terser": "^0.4.3", "@rollup/pluginutils": "^5.0.2", + "@types/webxr": "^0.5.2", "@webgpu/types": "^0.1.34", "c8": "^8.0.0", "chai": "^4.3.7", diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 1fd67b241ef..857f11025cd 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -43,6 +43,8 @@ class XrAnchors extends EventHandler { _creationQueue = []; /** + * Index of XrAnchors, with XRAnchor (native handle) used as a key. + * * @type {Map} * @ignore */ From 5fad7ed4d9583f03a542075dba4034e5a1e61a13 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Thu, 10 Aug 2023 12:35:46 +0300 Subject: [PATCH 27/30] Update src/framework/xr/xr-anchors.js Co-authored-by: Will Eastcott --- src/framework/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 857f11025cd..fbd0dffc2d2 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -11,7 +11,7 @@ import { XrAnchor } from './xr-anchor.js'; */ /** - * Anchors provide an ability to specify a point in the world that need to be updated to + * Anchors provide an ability to specify a point in the world that needs to be updated to * correctly reflect the evolving understanding of the world by the underlying AR system, * such that the anchor remains aligned with the same place in the physical world. * Anchors tend to persist better relative to the real world, especially during a longer From 324a6236845cf54a56079683242237df89146c97 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Thu, 10 Aug 2023 12:36:12 +0300 Subject: [PATCH 28/30] Update src/framework/xr/xr-anchors.js Co-authored-by: Will Eastcott --- src/framework/xr/xr-anchors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index fbd0dffc2d2..3b22fa9c6ac 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -132,9 +132,9 @@ class XrAnchors extends EventHandler { /** * Create anchor with position, rotation and a callback. * - * @param {import('../../core/math/vec3.js').Vec3} position - Position for an anchor - * @param {import('../../core/math/quat.js').Quat} [rotation] - Rotation for an anchor - * @param {XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created + * @param {import('../../core/math/vec3.js').Vec3} position - Position for an anchor. + * @param {import('../../core/math/quat.js').Quat} [rotation] - Rotation for an anchor. + * @param {XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created. * @example * app.xr.anchors.create(position, rotation, function (err, anchor) { * if (! err) { From e3dafe3203e05316f2b6c3c7e4707ffe9da3fc5d Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Thu, 10 Aug 2023 12:36:19 +0300 Subject: [PATCH 29/30] Update src/framework/xr/xr-anchors.js Co-authored-by: Will Eastcott --- src/framework/xr/xr-anchors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 3b22fa9c6ac..54359b8d7d1 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -137,7 +137,7 @@ class XrAnchors extends EventHandler { * @param {XrAnchorCreate} [callback] - Callback to fire when anchor was created or failed to be created. * @example * app.xr.anchors.create(position, rotation, function (err, anchor) { - * if (! err) { + * if (!err) { * // new anchor has been created * } * }); From 0cb40428b29a66bb7add0c509d6b4a4f176deea4 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Thu, 10 Aug 2023 13:06:30 +0300 Subject: [PATCH 30/30] small PR corrections --- src/framework/xr/xr-anchors.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/framework/xr/xr-anchors.js b/src/framework/xr/xr-anchors.js index 54359b8d7d1..c273878a12d 100644 --- a/src/framework/xr/xr-anchors.js +++ b/src/framework/xr/xr-anchors.js @@ -17,15 +17,13 @@ import { XrAnchor } from './xr-anchor.js'; * Anchors tend to persist better relative to the real world, especially during a longer * session with lots of movement. * - * @property {boolean} supported True if Anchors are supported. - * @property {XrAnchor[]} list Array of active {@link XrAnchor}s. - * @augments EventHandler - * @category XR * ```javascript * app.xr.start(camera, pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, { * anchors: true * }); * ``` + * @augments EventHandler + * @category XR */ class XrAnchors extends EventHandler { /**