playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
102 lines (101 loc) • 2.83 kB
JavaScript
import { EventHandler } from "../../core/event-handler.js";
import { platform } from "../../core/platform.js";
import { XrTrackedImage } from "./xr-tracked-image.js";
class XrImageTracking extends EventHandler {
static EVENT_ERROR = "error";
_manager;
_supported = platform.browser && !!window.XRImageTrackingResult;
_available = false;
_images = [];
constructor(manager) {
super();
this._manager = manager;
if (this._supported) {
this._manager.on("start", this._onSessionStart, this);
this._manager.on("end", this._onSessionEnd, this);
}
}
add(image, width) {
if (!this._supported || this._manager.active) return null;
const trackedImage = new XrTrackedImage(image, width);
this._images.push(trackedImage);
return trackedImage;
}
remove(trackedImage) {
if (this._manager.active) return;
const ind = this._images.indexOf(trackedImage);
if (ind !== -1) {
trackedImage.destroy();
this._images.splice(ind, 1);
}
}
_onSessionStart() {
this._manager.session.getTrackedImageScores().then((images) => {
this._available = true;
for (let i = 0; i < images.length; i++) {
this._images[i]._trackable = images[i] === "trackable";
}
}).catch((err) => {
this._available = false;
this.fire("error", err);
});
}
_onSessionEnd() {
this._available = false;
for (let i = 0; i < this._images.length; i++) {
const image = this._images[i];
image._pose = null;
image._measuredWidth = 0;
if (image._tracking) {
image._tracking = false;
image.fire("untracked");
}
}
}
prepareImages(callback) {
if (this._images.length) {
Promise.all(this._images.map((trackedImage) => {
return trackedImage.prepare();
})).then((bitmaps) => {
callback(null, bitmaps);
}).catch((err) => {
callback(err, null);
});
} else {
callback(null, null);
}
}
update(frame) {
if (!this._available) return;
const results = frame.getImageTrackingResults();
const index = {};
for (let i = 0; i < results.length; i++) {
index[results[i].index] = results[i];
const trackedImage = this._images[results[i].index];
trackedImage._emulated = results[i].trackingState === "emulated";
trackedImage._measuredWidth = results[i].measuredWidthInMeters;
trackedImage._pose = frame.getPose(results[i].imageSpace, this._manager._referenceSpace);
}
for (let i = 0; i < this._images.length; i++) {
if (this._images[i]._tracking && !index[i]) {
this._images[i]._tracking = false;
this._images[i].fire("untracked");
} else if (!this._images[i]._tracking && index[i]) {
this._images[i]._tracking = true;
this._images[i].fire("tracked");
}
}
}
get supported() {
return this._supported;
}
get available() {
return this._available;
}
get images() {
return this._images;
}
}
export {
XrImageTracking
};