Merge pull request #115 from mozilla/develop

Merging current polyfill for app 1.10 release.
This commit is contained in:
Blair MacIntyre 2018-11-21 15:36:53 -05:00 коммит произвёл GitHub
Родитель 468a618818 ca18c3cc6a
Коммит bfb89ab1b3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
29 изменённых файлов: 648 добавлений и 114 удалений

22
dist-footer.js Normal file
Просмотреть файл

@ -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;

25
dist-header.js Normal file
Просмотреть файл

@ -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;
}

Просмотреть файл

@ -35,8 +35,11 @@
</style>
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -28,8 +28,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<script src="../models/TeapotBufferGeometry.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>

Просмотреть файл

@ -28,8 +28,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<script src="../libs/three-gltf-loader.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -26,8 +26,11 @@
<script src="../libs/three.js"></script>
<script src="../libs/dat.gui.min.js"></script>
<script src="../libs/three-gltf-loader.js"></script>
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -30,8 +30,11 @@
</style>
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -39,9 +39,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<script src="../libs/three-gltf-loader.js"></script>
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script type="module" src="../../polyfill/platform/ARKitWrapper.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>
@ -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;

Просмотреть файл

@ -30,8 +30,11 @@
</style>
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -44,8 +44,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.js"></script>
<script src="../libs/stats.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -57,8 +57,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.js"></script>
<script src="../libs/stats.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -44,8 +44,11 @@
<script src="../libs/postprocessing/BloomPass.js"></script>
<script src="../libs/postprocessing/FilmPass.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -0,0 +1,242 @@
<html>
<head>
<title>Hit test example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body, html {
padding: 0;
margin: 0;
overflow: hidden;
position: fixed;
width: 100%;
height: 100vh;
-webkit-user-select: none;
user-select: none;
}
#target {
width: 100%;
height: 100%;
position: absolute;
}
.common-message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
}
</style>
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>
<div id="target" />
<div onclick="hideMe(this)" id="description">
<h2>Hit Test with Persistence</h2>
<h5>(click to dismiss)</h5>
<p>Find anchors by searching on tap events.</p>
</div>
<script>
/*
HitTestExample shows how to find surfaces or other features and place content relative to them.
In a production application, you would not create a separate anchor for every user action because
your application would quickly slow down tracking so many anchors. Instead, find an anchor
for groups of content that are positioned relative to some surface or other feature.
*/
class HitTestExample extends XRExampleBase {
constructor(domElement){
super(domElement, false, true, false, true)
// A message at the bottom of the screen that shows whether a surface has been found
this._messageEl = document.createElement('div')
this.el.appendChild(this._messageEl)
this._messageEl.style.position = 'absolute'
this._messageEl.style.bottom = '10px'
this._messageEl.style.left = '10px'
this._messageEl.style.color = 'white'
this._messageEl.style['font-size'] = '16px'
this._mapMessageEl = document.createElement('div')
this.el.appendChild(this._mapMessageEl)
this._mapMessageEl.style.position = 'absolute'
this._mapMessageEl.style.bottom = '30px'
this._mapMessageEl.style.left = '10px'
this._mapMessageEl.style.color = 'grey'
this._mapMessageEl.style['font-size'] = '16px'
this.anchorsToAdd = [] // { node, anchorOffset }
this.tempMat = new THREE.Matrix4();
this.tempScale = new THREE.Vector3();
this.tempPos = new THREE.Vector3();
this.tempQuaternion = new THREE.Quaternion();
this.el.addEventListener('touchstart', this._onTouchStart.bind(this), false)
this.listenerSetup = false
}
// Called during construction to allow the app to populate this.scene
initializeScene(){
// Add a box at the scene origin
let box = new THREE.Mesh(
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
)
box.position.set(0, 0.05, 0)
var axesHelper = AxesHelper( 0.2 );
this.floorGroup.add( axesHelper );
this.floorGroup.add(box)
// Add a few lights
this.scene.add(new THREE.AmbientLight('#FFF', 0.2))
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
directionalLight.position.set(0, 10, 0)
this.scene.add(directionalLight)
this.listenerSetup = false
}
// Called once per frame, before render, to give the app a chance to update this.scene
updateScene(frame){
const worldCoordinates = frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)
// Create anchors and start tracking them
for(let anchorToAdd of this.anchorsToAdd){
var anchor = frame.getAnchor(anchorToAdd.anchorOffset.anchorUID)
this.tempMat.fromArray(anchorToAdd.anchorOffset.getOffsetTransform(anchor.coordinateSystem))
this.tempMat.decompose(this.tempPos,this.tempQuaternion, this.tempScale);
const anchorUID = frame.addAnchor(worldCoordinates, [this.tempPos.x, this.tempPos.y, this.tempPos.z], [this.tempQuaternion.x, this.tempQuaternion.y, this.tempQuaternion.z, this.tempQuaternion.w])
this.addAnchoredNode(new XRAnchorOffset(anchorUID), anchorToAdd.node)
console.log("created anchor with uid=", anchorUID)
}
this.anchorsToAdd = []
this._mapMessageEl.innerHTML = this.session.getWorldMappingStatus();
if (!this.listenerSetup) {
this.listenerSetup = true
this.session.addEventListener(XRSession.NEW_WORLD_ANCHOR, this._handleNewWorldAnchor.bind(this))
this.session.addEventListener(XRSession.TRACKING_CHANGED, this._handleTrackingChanged.bind(this))
}
}
// Save screen taps as normalized coordinates for use in this.updateScene
_onTouchStart(ev){
if (!ev.touches || ev.touches.length === 0) {
console.error('No touches on touch event', ev)
return
}
const x = ev.touches[0].clientX / window.innerWidth
const y = ev.touches[0].clientY / window.innerHeight
// Attempt a hit test using the normalized screen coordinates
this.session.hitTest(x, y).then(anchorOffset => {
if(anchorOffset === null){
this._messageEl.innerHTML = 'miss'
} else {
// Save this info for use during the next render frame
this.anchorsToAdd.push({
node: this._createSceneGraphNode(),
anchorOffset: anchorOffset
})
this._messageEl.innerHTML = 'hit'
this.session.getWorldMap().then(worldMap => {
self.worldMap = worldMap;
console.log("got worldMap, size = ", worldMap.worldMap.length)
// if you have a world map, you can use it with a similar command.
// to see it in action, uncomment the following code:
//
// setTimeout(() => this.session.setWorldMap(worldMap).then(val => {
// console.log("set worldMap ok")
// }).catch(err => {
// console.error('Could not set world Map', err)
// }), 1000);
}).catch(err => {
console.error('Could not get world Map', err)
self.worldMap = null;
});
}
}).catch(err => {
console.error('Error in hit test', err)
})
}
_handleNewWorldAnchor(event) {
let anchor = event.detail
if (anchor.uid.startsWith('anchor-')) {
// it's an anchor we created last time
console.log("RECEIVED anchor with uid=", anchor.uid)
this.addAnchoredNode(new XRAnchorOffset(anchor.uid), this._createSceneGraphNode())
}
}
_handleTrackingChanged(event) {
this._messageEl.innerHTML = event.detail
}
// Creates a box used to indicate the location of an anchor offset
_createSceneGraphNode(){
let group = new THREE.Group()
let geometry = new THREE.BoxBufferGeometry(0.1, 0.1, 0.1)
let material = new THREE.MeshPhongMaterial({ color: '#99FF99' })
let mesh = new THREE.Mesh(geometry, material)
mesh.position.set(0, 0.05, 0)
group.add(mesh)
return group
}
}
function AxesHelper( size ) {
size = size || 1;
var vertices = [
0, 0, 0, size, 0, 0,
0, 0, 0, 0, size, 0,
0, 0, 0, 0, 0, size
];
var colors = [
1, 0, 0, 1, 0.6, 0,
0, 1, 0, 0.6, 1, 0,
0, 0, 1, 0, 0.6, 1
];
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
return new THREE.LineSegments(geometry, material);
}
window.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
try {
window.pageApp = new HitTestExample(document.getElementById('target'))
} catch(e) {
console.error('page error', e)
}
}, 1000)
})
</script>
</body>
</html>

Двоичные данные
examples/persistence/screenshot.jpeg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Просмотреть файл

@ -30,8 +30,11 @@
</style>
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.min.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -25,8 +25,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.js"></script>
<script src="../libs/three-gltf-loader.js"></script>
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>
@ -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))
}
}

Просмотреть файл

@ -47,8 +47,11 @@
<link rel="stylesheet" href="../common.css"/>
<script src="../libs/three.js"></script>
<script src="../libs/stats.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -36,8 +36,11 @@
<script src="../libs/three.js"></script>
<script src="../models/TeapotBufferGeometry.js"></script>
<!--
<script type="module" src="../../polyfill/XRPolyfill.js"></script>
<script nomodule src="../../dist/webxr-polyfill.js"></script>
-->
<script src="../../dist/webxr-polyfill.js"></script>
<script src="../common.js"></script>
</head>
<body>

Просмотреть файл

@ -296,6 +296,14 @@
<img src="examples/sensing/screenshot.jpg" width="300" height="200"/>
</a>
</li>
<li>
<a href="examples/persistence/">Map Sharing and Persistence</a>
<a class="source" href="https://github.com/mozilla/webxr-polyfill/blob/master/examples/persistence/index.html">source</a>
<p>Small test app to see if ARKit Map Sharing is working.</p>
<a class="img" href="examples/persistence/">
<img src="examples/persistence/screenshot.jpeg" width="300" height="200"/>
</a>
</li>
</ul>
</section>
</body>

Просмотреть файл

@ -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": {
}
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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'

Просмотреть файл

@ -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()
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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'

Просмотреть файл

@ -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)
}

Просмотреть файл

@ -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<any>} 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<any>} 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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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: {