-
Notifications
You must be signed in to change notification settings - Fork 787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ar #77
Conversation
c247f3a
to
21958b6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thanks Chris! This is a tricky area to get right. Handful of comments about WebXR and some caveats I'm aware of.
One thing that bit me before (and I think it'll be easier to wrangle with current architecture) was changing scales between inline and AR (where inline is sized to a specific dimension, and AR is unmodified scale), and back to inline. Check out scaleModelToFitRoom()
and resetModelPose()
in ModelScene
<script src="../node_modules/resize-observer-polyfill/dist/ResizeObserver.js"></script> | ||
|
||
<!-- Fullscreen polyfill is required to support all stable browsers: --> | ||
<script src="../node_modules/fullscreen-polyfill/dist/fullscreen.polyfill.js"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a future idea, it'd be cool to test our example pages for all appropriate polyfills
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 #81
@@ -8,7 +8,7 @@ | |||
"dist" | |||
], | |||
"scripts": { | |||
"clean": "rm -r ./lib ./dist", | |||
"clean": "rm -rf ./lib ./dist", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beat me to it 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍻
console.log('Attempting to enter fullscreen and present in AR...'); | ||
|
||
try { | ||
const enterFullscreen = this.requestFullscreen(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no browsers shipping with unprefixed/normalized fullscreen API -- this seems less like a 'bring your own polyfills to choose browser support' scenario and more like one we should normalize on our end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this is only used for WebXR mode. If we had a fullscreen feature for all models, I'd feel strongly about including a fullscreen API normalizer, but if it's just for WebXR, it's less critical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thoughts on this:
- It is a classic case where a polyfill should be used (as opposed to every library normalizing it everywhere).
- The polyfill is only needed for the Web XR case, which right now is a niche / experimental case
- If you don't count Web XR, Chrome stable requires zero polyfills. This seems like a reasonable litmus test for whether we should ask for a polyfill or bundle some kind of normalization.
.map((element, index) => { | ||
return (index === 0) === element[$scene].isVisible; | ||
}) | ||
.reduce(((l, r) => l && r), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
const $onWebXRFrame = Symbol('onWebXRFrame'); | ||
const $onOutputCanvasClick = Symbol('onOutputCanvasClick'); | ||
const $onFullscreenchange = Symbol('onFullscreenchange'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This instance isn't accessible to developers; we could get away with less "private" properties, or maybe combine several under a $state
object in categories, e.g. all three.js scene components under the same $scene
object or something. Just an idea, too many symbols can hurt readability IMO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed 👍will tone down the symbol usage
src/utils.js
Outdated
@@ -17,6 +17,45 @@ import {Vector3} from 'three'; | |||
|
|||
export const deserializeUrl = (url) => url != null ? toFullUrl(url) : url; | |||
|
|||
export const HAS_WEBXR_DEVICE_API = navigator.xr != null && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd make a note that these can be true on Chrome release if the correct flags are set, even though there is no ARCore bridge shipping on that platform, and that these are only hints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will document
// NOTE: This is needed in tests so that we don't have to manually trigger | ||
// the IntersectionObserver polyfill in Safari. Ordinarily, it would be | ||
// triggered by a resize or scroll event. | ||
// @see https://github.com/w3c/IntersectionObserver/tree/master/polyfill#configuring-the-polyfill |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙀
src/three-components/ARRenderer.js
Outdated
this[$renderer].setSize(window.innerWidth, window.innerHeight); | ||
this[$renderer].setPixelRatio(1); | ||
this[$renderer].autoClear = false; | ||
this[$renderer].gammaInput = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gammaInput
can be removed (and is also being removed from three?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
this[$currentSession] = null; | ||
session.cancelAnimationFrame(this[$rafId]); | ||
|
||
await session.end(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After end()
ing the session, we should defer to an end
event on XRSession: https://immersive-web.github.io/webxr/#dom-xrsession-onend
The session can abort on its own accord and will need to clean it up when that happens
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the end
event is called, ultimately we'll get a error while trying to end AR session
for attempting to re-destroy it -- same result, but maybe would be better to have this execute the ending of the session, and an onEnd that cleans up everything else (which manually calling session.end()
will call the event anyway, leading to the same path for both scenarios)
src/three-components/Renderer.js
Outdated
}); | ||
this.canvas = document.createElement('canvas'); | ||
this.context = this.canvas.getContext( | ||
'webgl', {antialias: true, alpha: true, preserveDrawingBuffer: true}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be aggressive about only enabling alpha
and preserveDrawingBuffer
if we think there's a good chance of WebXR support, otherwise will have unneeeded overhead in 95% scenarios
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, will fix
Also, were there any other issues on iOS devices that you've found? (I haven't tried in months) |
@jsantell responded to the feedback. PTAL! |
if (!buttonIsVisible) { | ||
this[$enterARElement].style.display = 'none'; | ||
if (iosCandidate || | ||
(canShowButton && await renderer.supportsPresentation())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much nicer
const gl = this.renderer.getContext(); | ||
|
||
await gl.setCompatibleXRDevice(device); | ||
session.baseLayer = new XRWebGLLayer(session, gl, {alpha: true}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this third argument is necessary (and already configured on the context)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Just copied this configuration from ARView
FWIW.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah there's been a handful of changes over the months inconsistently applied in demos due to platforms or discoveries across a handful of projects so I was extra cautious about all the old code I wrote months ago 😄
src/three-components/ARRenderer.js
Outdated
this.camera.updateMatrixWorld(true); | ||
// NOTE: Clearing depth caused issues on Samsung devices | ||
// @see https://github.com/googlecodelabs/ar-with-webxr/issues/8 | ||
this.renderer.clearDepth(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for leaving this? This can be safely removed (as far as AR consequences go) and only prevents Samsung devices from working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oversight, will fix
src/three-components/Renderer.js
Outdated
|
||
import {isMobile} from '../utils.js'; | ||
import {IS_AR_CANDIDATE} from '../constants.js'; | ||
// import {IS_MOBILE} from '../constants.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove
src/three-components/Renderer.js
Outdated
// Only enable certain options when Web XR capabilities are detected: | ||
if (IS_AR_CANDIDATE) { | ||
Object.assign( | ||
webGlOptions, {antialias: true, preserveDrawingBuffer: true}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
antialias is redundant here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but i think you'll need alpha -- unless adding that in XRWebGLLayer solves that? I didn't think that was something you could change after instantiation, but if this works, great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug, actually. Should be alpha
.
this[$currentSession] = null; | ||
session.cancelAnimationFrame(this[$rafId]); | ||
|
||
await session.end(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the end
event is called, ultimately we'll get a error while trying to end AR session
for attempting to re-destroy it -- same result, but maybe would be better to have this execute the ending of the session, and an onEnd that cleans up everything else (which manually calling session.end()
will call the event anyway, leading to the same path for both scenarios)
src/three-components/ARRenderer.js
Outdated
const presentedScene = this[$presentedScene]; | ||
|
||
const x = 0; | ||
const y = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is not using click coords, should make a note that it fires it out from the center of the screen
AR now works in iOS Safari 12+ and Web XR-capable Chrome Canary on Android.
Video recording of AR on Pixel 2
Video recording of AR on iPad Mini / iOS 12
Notable changes include:
ARRenderer
has been added, that is modeled after the oldARView
Renderer
incorporatesARRenderer
and exposes its public API toRenderer
consumers. I don't love this approach, but it seemed like the easiest factoring to start with. Open to suggestionsARRenderer
screenful
has been replaced with a Fullscreen API polyfill approach, so that we just rely on standard APIs in the implementationTest status on OSX:
Test status on iOS 12 Safari:
Fixes #55