123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import { WebXRFeaturesManager, WebXRFeatureName } from "../webXRFeaturesManager.js";
- import { Observable } from "../../Misc/observable.js";
- import { WebXRAbstractFeature } from "./WebXRAbstractFeature.js";
- import { Matrix } from "../../Maths/math.vector.js";
- import { Tools } from "../../Misc/tools.js";
- /**
- * Enum that describes the state of the image trackability score status for this session.
- */
- var ImageTrackingScoreStatus;
- (function (ImageTrackingScoreStatus) {
- // AR Session has not yet assessed image trackability scores.
- ImageTrackingScoreStatus[ImageTrackingScoreStatus["NotReceived"] = 0] = "NotReceived";
- // A request to retrieve trackability scores has been sent, but no response has been received.
- ImageTrackingScoreStatus[ImageTrackingScoreStatus["Waiting"] = 1] = "Waiting";
- // Image trackability scores have been received for this session
- ImageTrackingScoreStatus[ImageTrackingScoreStatus["Received"] = 2] = "Received";
- })(ImageTrackingScoreStatus || (ImageTrackingScoreStatus = {}));
- /**
- * Image tracking for immersive AR sessions.
- * Providing a list of images and their estimated widths will enable tracking those images in the real world.
- */
- export class WebXRImageTracking extends WebXRAbstractFeature {
- /**
- * constructs the image tracking feature
- * @param _xrSessionManager the session manager for this module
- * @param options read-only options to be used in this module
- */
- constructor(_xrSessionManager,
- /**
- * read-only options to be used in this module
- */
- options) {
- super(_xrSessionManager);
- this.options = options;
- /**
- * This will be triggered if the underlying system deems an image untrackable.
- * The index is the index of the image from the array used to initialize the feature.
- */
- this.onUntrackableImageFoundObservable = new Observable();
- /**
- * An image was deemed trackable, and the system will start tracking it.
- */
- this.onTrackableImageFoundObservable = new Observable();
- /**
- * The image was found and its state was updated.
- */
- this.onTrackedImageUpdatedObservable = new Observable();
- this._trackableScoreStatus = ImageTrackingScoreStatus.NotReceived;
- this._trackedImages = [];
- this.xrNativeFeatureName = "image-tracking";
- }
- /**
- * attach this feature
- * Will usually be called by the features manager
- *
- * @returns true if successful.
- */
- attach() {
- return super.attach();
- }
- /**
- * detach this feature.
- * Will usually be called by the features manager
- *
- * @returns true if successful.
- */
- detach() {
- return super.detach();
- }
- /**
- * Get a tracked image by its ID.
- *
- * @param id the id of the image to load (position in the init array)
- * @returns a trackable image, if exists in this location
- */
- getTrackedImageById(id) {
- return this._trackedImages[id] || null;
- }
- /**
- * Dispose this feature and all of the resources attached
- */
- dispose() {
- super.dispose();
- this._trackedImages.forEach((trackedImage) => {
- trackedImage.originalBitmap.close();
- });
- this._trackedImages.length = 0;
- this.onTrackableImageFoundObservable.clear();
- this.onUntrackableImageFoundObservable.clear();
- this.onTrackedImageUpdatedObservable.clear();
- }
- /**
- * Extends the session init object if needed
- * @returns augmentation object fo the xr session init object.
- */
- async getXRSessionInitExtension() {
- if (!this.options.images || !this.options.images.length) {
- return {};
- }
- const promises = this.options.images.map((image) => {
- if (typeof image.src === "string") {
- return this._xrSessionManager.scene.getEngine()._createImageBitmapFromSource(image.src);
- }
- else {
- return Promise.resolve(image.src); // resolve is probably unneeded
- }
- });
- try {
- const images = await Promise.all(promises);
- this._originalTrackingRequest = images.map((image, idx) => {
- return {
- image,
- widthInMeters: this.options.images[idx].estimatedRealWorldWidth,
- };
- });
- return {
- trackedImages: this._originalTrackingRequest,
- };
- }
- catch (ex) {
- Tools.Error("Error loading images for tracking, WebXRImageTracking disabled for this session.");
- return {};
- }
- }
- _onXRFrame(_xrFrame) {
- if (!_xrFrame.getImageTrackingResults || this._trackableScoreStatus === ImageTrackingScoreStatus.Waiting) {
- return;
- }
- // Image tracking scores may be generated a few frames after the XR Session initializes.
- // If we haven't received scores yet, then kick off the task to check scores and return immediately.
- if (this._trackableScoreStatus === ImageTrackingScoreStatus.NotReceived) {
- this._checkScoresAsync();
- return;
- }
- const imageTrackedResults = _xrFrame.getImageTrackingResults();
- for (const result of imageTrackedResults) {
- let changed = false;
- const imageIndex = result.index;
- const imageObject = this._trackedImages[imageIndex];
- if (!imageObject) {
- // something went wrong!
- continue;
- }
- imageObject.xrTrackingResult = result;
- if (imageObject.realWorldWidth !== result.measuredWidthInMeters) {
- imageObject.realWorldWidth = result.measuredWidthInMeters;
- changed = true;
- }
- // Get the pose of the image relative to a reference space.
- const pose = _xrFrame.getPose(result.imageSpace, this._xrSessionManager.referenceSpace);
- if (pose) {
- const mat = imageObject.transformationMatrix;
- Matrix.FromArrayToRef(pose.transform.matrix, 0, mat);
- if (!this._xrSessionManager.scene.useRightHandedSystem) {
- mat.toggleModelMatrixHandInPlace();
- }
- changed = true;
- }
- const state = result.trackingState;
- const emulated = state === "emulated";
- if (imageObject.emulated !== emulated) {
- imageObject.emulated = emulated;
- changed = true;
- }
- if (changed) {
- this.onTrackedImageUpdatedObservable.notifyObservers(imageObject);
- }
- }
- }
- async _checkScoresAsync() {
- if (!this._xrSessionManager.session.getTrackedImageScores || this._trackableScoreStatus !== ImageTrackingScoreStatus.NotReceived) {
- return;
- }
- this._trackableScoreStatus = ImageTrackingScoreStatus.Waiting;
- const imageScores = await this._xrSessionManager.session.getTrackedImageScores();
- if (!imageScores || imageScores.length === 0) {
- this._trackableScoreStatus = ImageTrackingScoreStatus.NotReceived;
- return;
- }
- // check the scores for all
- for (let idx = 0; idx < imageScores.length; ++idx) {
- if (imageScores[idx] == "untrackable") {
- this.onUntrackableImageFoundObservable.notifyObservers(idx);
- }
- else {
- const originalBitmap = this._originalTrackingRequest[idx].image;
- const imageObject = {
- id: idx,
- originalBitmap,
- transformationMatrix: new Matrix(),
- ratio: originalBitmap.width / originalBitmap.height,
- };
- this._trackedImages[idx] = imageObject;
- this.onTrackableImageFoundObservable.notifyObservers(imageObject);
- }
- }
- this._trackableScoreStatus = imageScores.length > 0 ? ImageTrackingScoreStatus.Received : ImageTrackingScoreStatus.NotReceived;
- }
- }
- /**
- * The module's name
- */
- WebXRImageTracking.Name = WebXRFeatureName.IMAGE_TRACKING;
- /**
- * The (Babylon) version of this module.
- * This is an integer representing the implementation version.
- * This number does not correspond to the WebXR specs version
- */
- WebXRImageTracking.Version = 1;
- //register the plugin
- WebXRFeaturesManager.AddWebXRFeature(WebXRImageTracking.Name, (xrSessionManager, options) => {
- return () => new WebXRImageTracking(xrSessionManager, options);
- }, WebXRImageTracking.Version, false);
- //# sourceMappingURL=WebXRImageTracking.js.map
|