diff --git a/dist-footer.js b/dist-footer.js new file mode 100644 index 0000000..303b13a --- /dev/null +++ b/dist-footer.js @@ -0,0 +1,22 @@ + +XRDisplay = window.XRDisplay +XRSession = window.XRSession +XRSessionCreateParameters = window.XRSessionCreateParameters +Reality = window.Reality +XRPointCloud = window.XRPointCloud +XRLightEstimate = window.XRLightEstimate +XRAnchor = window.XRAnchor; +XRPlaneAnchor = window.XRPlaneAnchor; +XRFaceAnchor = window.XRFaceAnchor; +XRImageAnchor = window.XRImageAnchor; +XRAnchorOffset = window.XRAnchorOffset; +XRStageBounds = window.XRStageBounds; +XRStageBoundsPoint = window.XRStageBoundsPoint; +XRPresentationFrame = window.XRPresentationFrame; +XRView = window.XRView; +XRViewport = window.XRViewport; +XRCoordinateSystem = window.XRCoordinateSystem; +XRViewPose = window.XRViewPose; +XRLayer = window.XRLayer; +XRWebGLLayer = window.XRWebGLLayer; +XRVideoFrame = window.XRVideoFrame; diff --git a/dist-header.js b/dist-header.js new file mode 100644 index 0000000..431400f --- /dev/null +++ b/dist-header.js @@ -0,0 +1,25 @@ +/* if there is a navigator.xr, clear it out */ +if(typeof navigator.xr != 'undefined') { + if(typeof XRDisplay != 'undefined') { XRDisplay = null } + if(typeof XRSession != 'undefined') { XRSession = null } + if(typeof XRSessionCreateParameters != 'undefined') { XRSessionCreateParameters = null } + if(typeof Reality != 'undefined') { Reality = null } + if(typeof XRPointCloud != 'undefined') { XRPointCloud = null } + if(typeof XRLightEstimate != 'undefined') { XRLightEstimate = null } + if(typeof XRAnchor != 'undefined') { XRAnchor = null } + if(typeof XRPlaneAnchor != 'undefined') { XRPlaneAnchor = null } + if(typeof XRFaceAnchor != 'undefined') { XRFaceAnchor = null } + if(typeof XRImageAnchor != 'undefined') { XRImageAnchor = null } + if(typeof XRAnchorOffset != 'undefined') { XRAnchorOffset = null } + if(typeof XRStageBounds != 'undefined') { XRStageBounds = null } + if(typeof XRStageBoundsPoint != 'undefined') { XRStageBoundsPoint = null } + if(typeof XRPresentationFrame != 'undefined') { XRPresentationFrame = null } + if(typeof XRView != 'undefined') { XRView = null } + if(typeof XRViewport != 'undefined') { XRViewport = null } + if(typeof XRCoordinateSystem != 'undefined') { XRCoordinateSystem = null } + if(typeof XRViewPose != 'undefined') { XRViewPose = null } + if(typeof XRLayer != 'undefined') { XRLayer = null } + if(typeof XRWebGLLayer != 'undefined') { XRWebGLLayer = null } + if(typeof XRVideoFrame != 'undefined') { XRVideoFrame = null } + //navigator.xr = null; +} \ No newline at end of file diff --git a/examples/ar_anchors/index.html b/examples/ar_anchors/index.html index 33ceca0..a12fabc 100644 --- a/examples/ar_anchors/index.html +++ b/examples/ar_anchors/index.html @@ -35,8 +35,11 @@ + + diff --git a/examples/ar_simplest/index.html b/examples/ar_simplest/index.html index e26679d..ac4d18a 100644 --- a/examples/ar_simplest/index.html +++ b/examples/ar_simplest/index.html @@ -28,8 +28,11 @@ + + diff --git a/examples/boombox/index.html b/examples/boombox/index.html index ef4ef86..f160df4 100644 --- a/examples/boombox/index.html +++ b/examples/boombox/index.html @@ -28,8 +28,11 @@ + + diff --git a/examples/face_tracking/index.html b/examples/face_tracking/index.html index e1cfc4a..d14b217 100644 --- a/examples/face_tracking/index.html +++ b/examples/face_tracking/index.html @@ -26,8 +26,11 @@ - - + + diff --git a/examples/hit_test/index.html b/examples/hit_test/index.html index 50a6ffa..710c5c1 100644 --- a/examples/hit_test/index.html +++ b/examples/hit_test/index.html @@ -30,8 +30,11 @@ + + diff --git a/examples/image_detection/index.html b/examples/image_detection/index.html index c46efa6..4c44e82 100644 --- a/examples/image_detection/index.html +++ b/examples/image_detection/index.html @@ -39,9 +39,11 @@ - - - + + @@ -89,7 +91,7 @@ this.duckyCreated = false this.imageDetectionCreationRequested = false - this.imageActivateDection = false; + this.imageActivateDetection = false; this.imageActivated = false; loadGLTF('./DuckyMesh.glb').then(gltf => { @@ -123,20 +125,20 @@ this.resetButton.innerText = 'Reset' this.el.appendChild(this.resetButton) this.resetButton.addEventListener('click', ev => { - this.imageActivateDection = true; + this.imageActivateDetection = true; this.removeAnchoredNode(this.ducky) }) // ready to go! - this.imageActivateDection = true; + this.imageActivateDetection = true; }).catch(error => { console.error(`error creating ducky: ${error}`) }) } - if (!this.imageActivated && this.imageActivateDection) { + if (!this.imageActivated && this.imageActivateDetection) { this.imageActivated = true; - this.imageActivateDection = false; + this.imageActivateDetection = false; this.session.activateDetectionImage(hubsImageName).then(imageAnchorTransform => { this.imageActivated = false; diff --git a/examples/light/index.html b/examples/light/index.html index 9626655..508ea16 100644 --- a/examples/light/index.html +++ b/examples/light/index.html @@ -30,8 +30,11 @@ + + diff --git a/examples/opencv-aruco/index.html b/examples/opencv-aruco/index.html index 009723b..63746c1 100644 --- a/examples/opencv-aruco/index.html +++ b/examples/opencv-aruco/index.html @@ -44,8 +44,11 @@ + + diff --git a/examples/opencv-face/index.html b/examples/opencv-face/index.html index 6d63357..ae559c3 100644 --- a/examples/opencv-face/index.html +++ b/examples/opencv-face/index.html @@ -57,8 +57,11 @@ + + diff --git a/examples/peoples/index.html b/examples/peoples/index.html index 2780b71..387b847 100644 --- a/examples/peoples/index.html +++ b/examples/peoples/index.html @@ -44,8 +44,11 @@ + + diff --git a/examples/persistence/index.html b/examples/persistence/index.html new file mode 100644 index 0000000..f9b29c7 --- /dev/null +++ b/examples/persistence/index.html @@ -0,0 +1,242 @@ + + + + Hit test example + + + + + + + + + + +
+
+

Hit Test with Persistence

+
(click to dismiss)
+

Find anchors by searching on tap events.

+
+ + + diff --git a/examples/persistence/screenshot.jpeg b/examples/persistence/screenshot.jpeg new file mode 100644 index 0000000..23ba81c Binary files /dev/null and b/examples/persistence/screenshot.jpeg differ diff --git a/examples/reticle/index.html b/examples/reticle/index.html index 502e39f..d338904 100644 --- a/examples/reticle/index.html +++ b/examples/reticle/index.html @@ -30,8 +30,11 @@ + + diff --git a/examples/sensing/index.html b/examples/sensing/index.html index b8b2574..24ab61d 100644 --- a/examples/sensing/index.html +++ b/examples/sensing/index.html @@ -25,8 +25,11 @@ - - + + @@ -89,6 +92,8 @@ this.listenerSetup = true this.session.addEventListener(XRSession.NEW_WORLD_ANCHOR, this._handleNewWorldAnchor.bind(this)) this.session.addEventListener(XRSession.UPDATE_WORLD_ANCHOR, this._handleUpdateWorldAnchor.bind(this)) + this.session.addEventListener(XRSession.REMOVE_WORLD_ANCHOR, this._handleRemoveWorldAnchor.bind(this)) + } } diff --git a/examples/simplecv/index.html b/examples/simplecv/index.html index 947fdd8..33f6c0b 100644 --- a/examples/simplecv/index.html +++ b/examples/simplecv/index.html @@ -47,8 +47,11 @@ + + diff --git a/examples/vr_simplest/index.html b/examples/vr_simplest/index.html index ac64e54..2edec0c 100644 --- a/examples/vr_simplest/index.html +++ b/examples/vr_simplest/index.html @@ -36,8 +36,11 @@ + + diff --git a/index.html b/index.html index 1ced9bf..4504fcb 100644 --- a/index.html +++ b/index.html @@ -296,6 +296,14 @@ +
  • + Map Sharing and Persistence + source +

    Small test app to see if ARKit Map Sharing is working.

    + + + +
  • diff --git a/package.json b/package.json index b8af6c8..7e5c670 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,9 @@ "babel-loader": "^7.1.1", "babel-preset-env": "^1.6.0", "http-server": "^0.10.0", - "webpack": "^3.5.5" + "webpack": "^3.5.5", + "wrapper-webpack-plugin": "^1.0.0" + }, + "dependencies": { } } diff --git a/polyfill/Reality.js b/polyfill/Reality.js index a8bcd5c..e0bff3d 100644 --- a/polyfill/Reality.js +++ b/polyfill/Reality.js @@ -28,14 +28,14 @@ export default class Reality extends EventHandlerBase { Called when at least one active XRSession is using this Reality */ _start(parameters){ - throw new Error('Exending classes should implement _start') + throw new Error('Extending classes should implement _start') } /* Called when no more active XRSessions are using this Reality */ _stop(){ - throw new Error('Exending classes should implement _stop') + throw new Error('Extending classes should implement _stop') } /* @@ -63,7 +63,7 @@ export default class Reality extends EventHandlerBase { */ _addAnchor(anchor, display){ // returns DOMString anchor UID - throw new Error('Exending classes should implement _addAnchor') + throw new Error('Extending classes should implement _addAnchor') } /* @@ -72,15 +72,15 @@ export default class Reality extends EventHandlerBase { normalized screen x and y are in range 0..1, with 0,0 at top left and 1,1 at bottom right */ _findAnchor(normalizedScreenX, normalizedScreenY, display){ - throw new Error('Exending classes should implement _findAnchor') + throw new Error('Extending classes should implement _findAnchor') } _createImageAnchor(uid, buffer, width, height, physicalWidthInMeters) { - throw new Error('Exending classes should implement _createImageAnchor') + throw new Error('Extending classes should implement _createImageAnchor') } activateDetectionImage(uid, display) { - throw new Error('Exending classes should implement _activateDetectionImage') + throw new Error('Extending classes should implement _activateDetectionImage') } /* @@ -88,7 +88,7 @@ export default class Reality extends EventHandlerBase { returns a Promise that resolves either to an AnchorOffset or null if the floor level is unknown */ _findFloorAnchor(display, uid=null){ - throw new Error('Exending classes should implement _findFloorAnchor') + throw new Error('Extending classes should implement _findFloorAnchor') } _getAnchor(uid){ @@ -97,17 +97,28 @@ export default class Reality extends EventHandlerBase { _removeAnchor(uid){ // returns void - throw new Error('Exending classes should implement _removeAnchor') + throw new Error('Extending classes should implement _removeAnchor') } _hitTestNoAnchor(normalizedScreenX, normalizedScreenY, display){ - throw new Error('Exending classes should implement _hitTestNoAnchor') + throw new Error('Extending classes should implement _hitTestNoAnchor') } _getLightAmbientIntensity(){ - throw new Error('Exending classes should implement _getLightAmbientIntensity') + throw new Error('Extending classes should implement _getLightAmbientIntensity') } + _getWorldMap() { + throw new Error('Extending classes should implement _getWorldMap') + } + + _setWorldMap(worldMap) { + throw new Error('Extending classes should implement _setWorldMap') + } + + _getWorldMappingStatus() { + throw new Error('Extending classes should implement _getWorldMappingStatus') + } // attribute EventHandler onchange; } diff --git a/polyfill/XRDisplay.js b/polyfill/XRDisplay.js index 81f729a..e7bb5b9 100644 --- a/polyfill/XRDisplay.js +++ b/polyfill/XRDisplay.js @@ -101,6 +101,8 @@ export default class XRDisplay extends EventHandlerBase { //attribute EventHandler ondeactivate; } +XRDisplay.VIDEO_FRAME = 'videoFrame' +XRDisplay.TRACKING_CHANGED = 'tracking-changed' XRDisplay.NEW_WORLD_ANCHOR = 'world-anchor' XRDisplay.UPDATE_WORLD_ANCHOR = 'update-world-anchor' XRDisplay.REMOVE_WORLD_ANCHOR = 'remove-world-anchor' diff --git a/polyfill/XRPolyfill.js b/polyfill/XRPolyfill.js index 5ed242e..65f7214 100644 --- a/polyfill/XRPolyfill.js +++ b/polyfill/XRPolyfill.js @@ -1,24 +1,24 @@ -import XRDisplay from './XRDisplay.js' -import XRSession from './XRSession.js' -import XRSessionCreateParameters from './XRSessionCreateParameters.js' -import Reality from './Reality.js' -import XRPointCloud from './XRPointCloud.js' -import XRLightEstimate from './XRLightEstimate.js' -import XRAnchor from './XRAnchor.js' -import XRPlaneAnchor from './XRPlaneAnchor.js' -import XRFaceAnchor from './XRFaceAnchor.js' -import XRImageAnchor from './XRImageAnchor.js' -import XRAnchorOffset from './XRAnchorOffset.js' -import XRStageBounds from './XRStageBounds.js' -import XRStageBoundsPoint from './XRStageBoundsPoint.js' -import XRPresentationFrame from './XRPresentationFrame.js' -import XRView from './XRView.js' -import XRViewport from './XRViewport.js' -import XRCoordinateSystem from './XRCoordinateSystem.js' -import XRViewPose from './XRViewPose.js' -import XRLayer from './XRLayer.js' -import XRWebGLLayer from './XRWebGLLayer.js' -import XRVideoFrame from './XRVideoFrame.js' +import _XRDisplay from './XRDisplay.js' +import _XRSession from './XRSession.js' +import _XRSessionCreateParameters from './XRSessionCreateParameters.js' +import _Reality from './Reality.js' +import _XRPointCloud from './XRPointCloud.js' +import _XRLightEstimate from './XRLightEstimate.js' +import _XRAnchor from './XRAnchor.js' +import _XRPlaneAnchor from './XRPlaneAnchor.js' +import _XRFaceAnchor from './XRFaceAnchor.js' +import _XRImageAnchor from './XRImageAnchor.js' +import _XRAnchorOffset from './XRAnchorOffset.js' +import _XRStageBounds from './XRStageBounds.js' +import _XRStageBoundsPoint from './XRStageBoundsPoint.js' +import _XRPresentationFrame from './XRPresentationFrame.js' +import _XRView from './XRView.js' +import _XRViewport from './XRViewport.js' +import _XRCoordinateSystem from './XRCoordinateSystem.js' +import _XRViewPose from './XRViewPose.js' +import _XRLayer from './XRLayer.js' +import _XRWebGLLayer from './XRWebGLLayer.js' +import _XRVideoFrame from './XRVideoFrame.js' import EventHandlerBase from './fill/EventHandlerBase.js' import FlatDisplay from './display/FlatDisplay.js' @@ -35,27 +35,49 @@ so you can safely include this script in any page. class XRPolyfill extends EventHandlerBase { constructor(){ super() - window.XRDisplay = XRDisplay - window.XRSession = XRSession - window.XRSessionCreateParameters = XRSessionCreateParameters - window.Reality = Reality - window.XRPointCloud = XRPointCloud - window.XRLightEstimate = XRLightEstimate - window.XRAnchor = XRAnchor - window.XRPlaneAnchor = XRPlaneAnchor - window.XRFaceAnchor = XRFaceAnchor - window.XRImageAnchor = XRImageAnchor - window.XRAnchorOffset = XRAnchorOffset - window.XRStageBounds = XRStageBounds - window.XRStageBoundsPoint = XRStageBoundsPoint - window.XRPresentationFrame = XRPresentationFrame - window.XRView = XRView - window.XRViewport = XRViewport - window.XRCoordinateSystem = XRCoordinateSystem - window.XRViewPose = XRViewPose - window.XRLayer = XRLayer - window.XRWebGLLayer = XRWebGLLayer - window.XRVideoFrame = XRVideoFrame + window.XRDisplay = _XRDisplay + window.XRSession = _XRSession + window.XRSessionCreateParameters = _XRSessionCreateParameters + window.Reality = _Reality + window.XRPointCloud = _XRPointCloud + window.XRLightEstimate = _XRLightEstimate + window.XRAnchor = _XRAnchor + window.XRPlaneAnchor = _XRPlaneAnchor + window.XRFaceAnchor = _XRFaceAnchor + window.XRImageAnchor = _XRImageAnchor + window.XRAnchorOffset = _XRAnchorOffset + window.XRStageBounds = _XRStageBounds + window.XRStageBoundsPoint = _XRStageBoundsPoint + window.XRPresentationFrame = _XRPresentationFrame + window.XRView = _XRView + window.XRViewport = _XRViewport + window.XRCoordinateSystem = _XRCoordinateSystem + window.XRViewPose = _XRViewPose + window.XRLayer = _XRLayer + window.XRWebGLLayer = _XRWebGLLayer + window.XRVideoFrame = _XRVideoFrame + + XRDisplay = window.XRDisplay + XRSession = window.XRSession + XRSessionCreateParameters = window.XRSessionCreateParameters + Reality = window.Reality + XRPointCloud = window.XRPointCloud + XRLightEstimate = window.XRLightEstimate + XRAnchor = window.XRAnchor; + XRPlaneAnchor = window.XRPlaneAnchor; + XRFaceAnchor = window.XRFaceAnchor; + XRImageAnchor = window.XRImageAnchor; + XRAnchorOffset = window.XRAnchorOffset; + XRStageBounds = window.XRStageBounds; + XRStageBoundsPoint = window.XRStageBoundsPoint; + XRPresentationFrame = window.XRPresentationFrame; + XRView = window.XRView; + XRViewport = window.XRViewport; + XRCoordinateSystem = window.XRCoordinateSystem; + XRViewPose = window.XRViewPose; + XRLayer = window.XRLayer; + XRWebGLLayer = window.XRWebGLLayer; + XRVideoFrame = window.XRVideoFrame; this._getVRDisplaysFinished = false; @@ -125,4 +147,6 @@ class XRPolyfill extends EventHandlerBase { } /* Install XRPolyfill if window.XR does not exist */ -if(typeof navigator.XR === 'undefined') navigator.XR = new XRPolyfill() +if(typeof navigator.XR === 'undefined') { + navigator.XR = new XRPolyfill() +} diff --git a/polyfill/XRPresentationFrame.js b/polyfill/XRPresentationFrame.js index f74ae84..9a5a315 100644 --- a/polyfill/XRPresentationFrame.js +++ b/polyfill/XRPresentationFrame.js @@ -56,13 +56,13 @@ export default class XRPresentationFrame { /* Create an anchor at a specific position defined by XRAnchor.coordinates */ - addAnchor(coordinateSystem, position=[0,0,0], orientation=[0,0,0,1]){ + addAnchor(coordinateSystem, position=[0,0,0], orientation=[0,0,0,1],uid=null){ //DOMString? addAnchor(XRCoordinateSystem, position, orientation); let poseMatrix = MatrixMath.mat4_fromRotationTranslation(new Float32Array(16), orientation, position) MatrixMath.mat4_multiply(poseMatrix, coordinateSystem.getTransformTo(this._session._display._trackerCoordinateSystem), poseMatrix) let anchorCoordinateSystem = new XRCoordinateSystem(this._session._display, XRCoordinateSystem.TRACKER) anchorCoordinateSystem._relativeMatrix = poseMatrix - return this._session.reality._addAnchor(new XRAnchor(anchorCoordinateSystem), this._session.display) + return this._session.reality._addAnchor(new XRAnchor(anchorCoordinateSystem, uid), this._session.display) } // normalized screen x and y are in range 0..1, with 0,0 at top left and 1,1 at bottom right diff --git a/polyfill/XRSession.js b/polyfill/XRSession.js index c3df0b4..dc331c0 100644 --- a/polyfill/XRSession.js +++ b/polyfill/XRSession.js @@ -28,6 +28,7 @@ export default class XRSession extends EventHandlerBase { this._tempMatrix = MatrixMath.mat4_generateIdentity() this._tempMatrix2 = MatrixMath.mat4_generateIdentity() + this._display.addEventListener(XRDisplay.TRACKING_CHANGED, this._handleTrackingChanged.bind(this)) this._display.addEventListener(XRDisplay.NEW_WORLD_ANCHOR, this._handleNewWorldAnchor.bind(this)) this._display.addEventListener(XRDisplay.REMOVE_WORLD_ANCHOR, this._handleRemoveWorldAnchor.bind(this)) this._display.addEventListener(XRDisplay.UPDATE_WORLD_ANCHOR, this._handleUpdateWorldAnchor.bind(this)) @@ -106,7 +107,8 @@ export default class XRSession extends EventHandlerBase { // new anchor each minute if (this._frameAnchors.length == 0 || (this._frameAnchors[0].timestamp + 60000) < frame.timestamp) { const headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.EYE_LEVEL) - const anchorUID = frame.addAnchor(headCoordinateSystem, [0,-1,0]) + const anchorUID = frame.addAnchor(headCoordinateSystem, [0,-1,0], [0,0,0,1], + 'cameraAnchor-' + new Date().getTime() + '-' + Math.floor((Math.random() * Number.MAX_SAFE_INTEGER))); const anchor = frame.getAnchor(anchorUID) anchor.timestamp = frame.timestamp; this._frameAnchors.unshift(anchor) @@ -245,19 +247,23 @@ export default class XRSession extends EventHandlerBase { let xrAnchor = event.detail //console.log(`New world anchor: ${JSON.stringify(xrAnchor)}`) - try { - this.dispatchEvent( - new CustomEvent( - XRSession.NEW_WORLD_ANCHOR, - { - source: this, - detail: xrAnchor - } + if (!xrAnchor.uid.startsWith('cameraAnchor-')) { + try { + this.dispatchEvent( + new CustomEvent( + XRSession.NEW_WORLD_ANCHOR, + { + source: this, + detail: xrAnchor + } + ) ) - ) - } catch(e) { - console.error('NEW_WORLD_ANCHOR event error', e) - } + } catch(e) { + console.error('NEW_WORLD_ANCHOR event error', e) + } + } else { + console.log('not passing NEW_WORLD_ANCHOR event to app for ', xrAnchor.uid) + } } _handleUpdateWorldAnchor(event) { @@ -297,6 +303,34 @@ export default class XRSession extends EventHandlerBase { console.error('REMOVE_WORLD_ANCHOR event error', e) } } + + _handleTrackingChanged(event) { + try { + this.dispatchEvent( + new CustomEvent( + XRSession.TRACKING_CHANGED, + { + source: this, + detail: event.detail + } + ) + ) + } catch(e) { + console.error('TRACKING_CHANGED event error', e) + } + } + + getWorldMap() { + return this.reality._getWorldMap() + } + + setWorldMap(worldMap) { + return this.reality._setWorldMap(worldMap) + } + + getWorldMappingStatus() { + return this.reality._getWorldMappingStatus() + } /* attribute EventHandler onblur; attribute EventHandler onfocus; @@ -314,6 +348,8 @@ XRSession.AUGMENTATION = 'augmentation' XRSession.TYPES = [XRSession.REALITY, XRSession.AUGMENTATION] +XRSession.TRACKING_CHANGED = 'tracking-changed' + XRSession.NEW_WORLD_ANCHOR = 'world-anchor' XRSession.UPDATE_WORLD_ANCHOR = 'update-world-anchor' XRSession.REMOVE_WORLD_ANCHOR = 'remove-world-anchor' \ No newline at end of file diff --git a/polyfill/display/FlatDisplay.js b/polyfill/display/FlatDisplay.js index dbd1290..42dce54 100644 --- a/polyfill/display/FlatDisplay.js +++ b/polyfill/display/FlatDisplay.js @@ -314,6 +314,20 @@ export default class FlatDisplay extends XRDisplay { // #define WEB_AR_TRACKING_STATE_LIMITED_MOTION @"ar_tracking_limited_excessive_motion" // #define WEB_AR_TRACKING_STATE_LIMITED_FEATURES @"ar_tracking_limited_insufficient_features" // #define WEB_AR_TRACKING_STATE_NOT_AVAILABLE @"ar_tracking_not_available" + // #define WEB_AR_TRACKING_STATE_RELOCALIZING @"ar_tracking_relocalizing" + try { + this.dispatchEvent( + new CustomEvent( + XRDisplay.TRACKING_CHANGED, + { + source: this, + detail: ev.detail + } + ) + ); + } catch (e) { + console.error('trackingChanged callback error', e); + } } @@ -322,13 +336,13 @@ export default class FlatDisplay extends XRDisplay { try { this.dispatchEvent( new CustomEvent( - "videoFrame", - { - source: this, - detail: ev.detail - } - ) - ) + XRDisplay.VIDEO_FRAME, + { + source: this, + detail: ev.detail + } + ) + ) } catch(e) { console.error('computer vision callback error', e) } diff --git a/polyfill/platform/ARKitWrapper.js b/polyfill/platform/ARKitWrapper.js index 2289212..efdebd8 100644 --- a/polyfill/platform/ARKitWrapper.js +++ b/polyfill/platform/ARKitWrapper.js @@ -88,6 +88,7 @@ export default class ARKitWrapper extends EventHandlerBase { this._timeOffsetComputed = false; this.timestamp = 0; + this.worldMappingStatus = ARKitWrapper.WEB_AR_WORLDMAPPING_NOT_AVAILABLE; this._globalCallbacksMap = {} // Used to map a window.arkitCallback method name to an ARKitWrapper.on* method name // Set up the window.arkitCallback methods that the ARKit bridge depends on @@ -684,6 +685,43 @@ export default class ARKitWrapper extends EventHandlerBase { }) } + /*** + * getWorldMap requests a worldmap from the platform + * @returns {Promise} a promise that will be resolved when the worldMap has been retrieved, or an error otherwise + */ + getWorldMap() { + return new Promise((resolve, reject) => { + if (!this._isInitialized){ + reject(new Error('ARKit is not initialized')); + return; + } + + window.webkit.messageHandlers.getWorldMap.postMessage({ + callback: this._createPromiseCallback('getWorldMap', resolve) + }) + }) + } + + /*** + * setWorldMap requests a worldmap for the platform be set + * @returns {Promise} a promise that will be resolved when the worldMap has been set, or an error otherwise + */ + setWorldMap(worldMap) { + return new Promise((resolve, reject) => { + if (!this._isInitialized){ + reject(new Error('ARKit is not initialized')); + return; + } + + window.webkit.messageHandlers.setWorldMap.postMessage({ + worldMap: worldMap.worldMap, + callback: this._createPromiseCallback('setWorldMap', resolve) + }) + }) + } + + + /* RACE CONDITION: call stop, then watch: stop does not set isWatching false until it gets a message back from the app, so watch will return and not issue a watch command. May want to set isWatching false immediately? @@ -858,7 +896,7 @@ export default class ARKitWrapper extends EventHandlerBase { this.lightIntensity = data.light_intensity; this.viewMatrix_ = data.camera_view; this.projectionMatrix_ = data.projection_camera; - + this.worldMappingStatus = data.worldMappingStatus; if(data.newObjects.length){ for (let i = 0; i < data.newObjects.length; i++) { const element = data.newObjects[i]; @@ -906,7 +944,7 @@ export default class ARKitWrapper extends EventHandlerBase { } else { plane.center = element.plane_center; plane.extent[0] = element.plane_extent.x - plane.extent[1] = element.plane_extent.y + plane.extent[1] = element.plane_extent.z plane.modelMatrix = element.transform; plane.alignment = element.plane_alignment } @@ -1286,6 +1324,12 @@ ARKitWrapper.ORIENTATION_RIGHT = 6 // 0th row on right, 0th column at ARKitWrapper.ORIENTATION_RIGHT_MIRRORED = 7 // 0th row on right, 0th column on bottom ARKitWrapper.ORIENTATION_LEFT = 8 // 0th row on left, 0th column at bottom - 90 deg CCW +// world mapping status +ARKitWrapper.WEB_AR_WORLDMAPPING_NOT_AVAILABLE = "ar_worldmapping_not_available" +ARKitWrapper.WEB_AR_WORLDMAPPING_LIMITED = "ar_worldmapping_limited" +ARKitWrapper.WEB_AR_WORLDMAPPING_EXTENDING = "ar_worldmapping_extending" +ARKitWrapper.WEB_AR_WORLDMAPPING_MAPPED = "ar_worldmapping_mapped" + // hit test types ARKitWrapper.HIT_TEST_TYPE_FEATURE_POINT = 1 ARKitWrapper.HIT_TEST_TYPE_ESTIMATED_HORIZONTAL_PLANE = 2 diff --git a/polyfill/reality/CameraReality.js b/polyfill/reality/CameraReality.js index ac95c24..f70b83e 100644 --- a/polyfill/reality/CameraReality.js +++ b/polyfill/reality/CameraReality.js @@ -697,6 +697,54 @@ export default class CameraReality extends Reality { } } + _getWorldMappingStatus(){ + if(this._arKitWrapper !== null){ + return this._arKitWrapper.worldMappingStatus; + }else{ + // No platform support for ligth estimation + return null; + } + } + + /** + * retrieves a worldMap from the platform, if possible + * @returns a promise when the worldMap has been retrieved + * @private + */ + _getWorldMap() { + return new Promise((resolve, reject) => { + if (this._arKitWrapper) { + this._arKitWrapper.getWorldMap().then(ARKitWorldMap => { + if (ARKitWorldMap.saved === true) { + resolve(ARKitWorldMap.worldMap) + } else if (ARKitWorldMap.error !== null) { + reject(ARKitWorldMap.error) + } else { + reject(null) + } + }) + } else { + reject('ARKit not supported') + } + }) + } + + /** + * sets a worldMap for the platform, if possible + * @param worldMap a platform specific worldmap + * @returns a promise when the worldMap has been set + * @private + */ + _setWorldMap(worldMap) { + if (this._arKitWrapper) { + return this._arKitWrapper.setWorldMap(worldMap) + } else { + return new Promise((resolve, reject) => { + reject(new Error('setWorldMap not supported')); + }) + } + } + _getTimeStamp(timestamp) { if(this._arKitWrapper !== null){ return this._arKitWrapper.timestamp; diff --git a/webpack.config.js b/webpack.config.js index 1e4da39..5d8a48e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,25 +1,37 @@ const path = require('path'); +const fs = require('fs'); + +WrapperPlugin = require('wrapper-webpack-plugin'); + +const headerDoc = fs.readFileSync('./dist-header.js', 'utf8'); +const footerDoc = fs.readFileSync('./dist-footer.js', 'utf8'); var xrPolyfill = { - entry: './polyfill/XRPolyfill.js', - output: { - filename: 'webxr-polyfill.js', - path: path.resolve(__dirname, 'dist') - }, + entry: './polyfill/XRPolyfill.js', + output: { + filename: 'webxr-polyfill.js', + path: path.resolve(__dirname, 'dist') + }, + plugins: [ + new WrapperPlugin({ + header: headerDoc, + footer: footerDoc + }) + ], module: { - rules: [ + rules: [ { - test: /\.js$/, - include: [ - path.resolve(__dirname, "polyfill"), - ], - use: { - loader: 'babel-loader', - options: { - presets: ['env'] + test: /\.js$/, + include: [ + path.resolve(__dirname, "polyfill"), + ], + use: { + loader: 'babel-loader', + options: { + presets: ['env'] + } } } - } ] }, resolve: { @@ -36,17 +48,17 @@ var xrVideoWorker = { module: { rules: [ { - test: /\.js$/, - include: [ - path.resolve(__dirname, "polyfill"), - ], - use: { - loader: 'babel-loader', - options: { - presets: ['env'] + test: /\.js$/, + include: [ + path.resolve(__dirname, "polyfill"), + ], + use: { + loader: 'babel-loader', + options: { + presets: ['env'] + } } } - } ] }, resolve: {