diff --git a/index.html b/index.html index 257717d..ffe8e4a 100644 --- a/index.html +++ b/index.html @@ -1063,6 +1063,20 @@ _bindEventTarget('xr'); } else if (target === 'xr') { console.log('xr click'); + if(fakeXrDisplay){ + _endFakeVrDisplay() + .then(() => _startVrDisplay()) + .catch(err => { + console.warn(err.stack); + }); + } else if(display){ + _endVrDisplay() + .then(() => _startFakeVrDisplay()) + .catch(err => { + console.warn(err.stack); + }); + } + } else if (target === 'transform') { console.log('transform click'); } @@ -1280,13 +1294,13 @@ const maxX = viewport.x + viewport.z; const maxY = viewport.y + viewport.w; const shouldOrbit = x >= minX && x < maxX && y >= minY && y < maxY && !menuOpen; - if (shouldOrbit && !orbitControls) { + if (shouldOrbit && !orbitControls && fakeXrDisplay) { _addOrbitControls(); } else if (!shouldOrbit && orbitControls) { _removeOrbitControls(); } - if (orbitControls) { + if (orbitControls && fakeXrDisplay) { const localCamera = camera; localCamera.matrixWorldInverse.fromArray(fakeXrDisplay.viewMatrix); localCamera.matrixWorld.getInverse(localCamera.matrixWorldInverse); @@ -3291,7 +3305,14 @@ gl.uniform1i(gl.uiTexLocation, 0); gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, fakeXrDisplay.texture); + if(fakeXrDisplay){ + gl.bindTexture(gl.TEXTURE_2D, fakeXrDisplay.texture); + } else if (display) { + // xxx + gl.bindTexture(gl.TEXTURE_2D, display.texture); + } else { + gl.bindTexture(gl.TEXTURE_2D, 0); + } gl.uniform1i(gl.viewportTexLocation, 1); gl.uniform4f(gl.viewportLocation, viewport.x, viewport.y, viewport.z, viewport.w); @@ -3304,25 +3325,103 @@ animateComposeContext(time, frame); } -// bootstrap +// bootstrap Xr +const _startVrDisplay = async () => { + if (navigator.xr) { + const session = await navigator.xr.requestSession({ + exclusive: true, + }); + + display = session; + + const _end = () => { + renderer.vr.enabled = false; + renderer.vr.setSession(null); + renderer.vr.setAnimationLoop(null); + + session.removeEventListener('end', _end); + }; + session.addEventListener('end', _end); + + await new Promise((accept, reject) => { + session.requestAnimationFrame((timestamp, frame) => { + session.layers = layers; + + renderer.vr.setSession(session, { + frameOfReferenceType: 'stage', + }); + + const {views} = frame.getViewerPose(); + const viewport = session.baseLayer.getViewport(views[0]); + const width = viewport.width; + const height = viewport.height; + // console.log("session.isPresenting = " + session.isPresenting()); + // renderer.setSize(width * 2, height); + + renderer.setAnimationLoop(null); + + renderer.vr.enabled = true; + renderer.vr.setSession(session, { + frameOfReferenceType: 'stage', + }); + renderer.vr.setAnimationLoop(animate); + + console.log('entered xr'); + + accept(); + }); + }); + } else { // WebVR + console.log('request device'); + const displays = await navigator.getVRDisplays(); + display = displays[0]; + + if (display) { + console.log('request present vr'); + await display.requestPresent([{ + source: renderer.domElement, + }]); + const {renderWidth: width, renderHeight: height} = display.getEyeParameters('left'); + renderer.setSize(width * 2, height); + + renderer.setAnimationLoop(null); + renderer.vr.enabled = true; + renderer.vr.setAnimationLoop(animate); + + console.log('entered vr'); + } else { + console.log('no vr displays'); + renderer.setAnimationLoop(animate); + } + } +}; +const _endVrDisplay = async () => { + if (display) { + await display.end(); + // await display.exitPresent(); + } + + display = null; + // renderer.domElement.framebuffer = null; // XXX destroy this framebuffer +}; + +// bootstrap fakeXr const _emitLayersVrDisplayActivate = () => { for (let i = 0; i < layers.length; i++) { const layer = layers[i]; - if (layer.tagName === 'IFRAME' && layer.d === 3) { - layer.contentWindow.runAsync('vrdisplayactivate'); + // layer.contentWindow.runAsync('vrdisplayactivate'); } } }; const _emitLayersExitPresent = () => { for (let i = 0; i < layers.length; i++) { const layer = layers[i]; - if (layer.tagName === 'IFRAME' && layer.d === 3) { - layer.contentWindow.runAsync('exitPresent'); + // layer.contentWindow.runAsync('exitPresent'); } - } +} }; const _startFakeVrDisplay = async (width, height) => { fakeXrDisplay = new FakeXRDisplay(); @@ -3346,7 +3445,7 @@ renderer.vr.setSession(null); renderer.vr.setAnimationLoop(null); - _emitLayersExitPresent(); + _emitLayersExitPresent(); session.removeEventListener('end', _end); }; @@ -3362,14 +3461,14 @@ }); renderer.vr.setAnimationLoop(animate); - _emitLayersVrDisplayActivate(); + _emitLayersVrDisplayActivate(); accept(); }); }); } else { const displays = await navigator.getVRDisplays(); - const display = displays[0]; + const fakeDisplay = displays[0]; await display.requestPresent([{ source: renderer.domElement, }]); @@ -3377,7 +3476,7 @@ fakeXrDisplay.display = display; const _vrdisplaypresentchange = () => { - _emitLayersExitPresent(); + _emitLayersExitPresent(); display.removeEventListener('vrdisplaypresentchange', _vrdisplaypresentchange); };