From 975685c23b4254de3857c20c4ebbb69bc6fb4d51 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 9 Mar 2018 15:19:06 -0800 Subject: [PATCH] Make it possible to enter VR mode --- demo/client/html/3d-demo.html.hbs | 6 +++ demo/client/package.json | 1 + demo/client/src/3d-demo.ts | 4 +- demo/client/src/app-controller.ts | 10 ++++ demo/client/src/renderer.ts | 4 ++ demo/client/src/view.ts | 79 ++++++++++++++++++++++++++++++- demo/client/tsconfig.json | 3 +- 7 files changed, 103 insertions(+), 4 deletions(-) diff --git a/demo/client/html/3d-demo.html.hbs b/demo/client/html/3d-demo.html.hbs index 72e0df2e..51e87851 100644 --- a/demo/client/html/3d-demo.html.hbs +++ b/demo/client/html/3d-demo.html.hbs @@ -42,6 +42,12 @@ aria-expanded="false" aria-controls="#pf-settings"> settings + {{>partials/spinner.html}} diff --git a/demo/client/package.json b/demo/client/package.json index 00f2d33b..4a18d00c 100644 --- a/demo/client/package.json +++ b/demo/client/package.json @@ -17,6 +17,7 @@ "@types/opentype.js": "0.0.0", "@types/papaparse": "^4.1.33", "@types/webgl-ext": "0.0.29", + "@types/webvr-api": "0.0.31", "base64-js": "^1.2.3", "bootstrap": "^4.0.0", "gl-matrix": "^2.4.0", diff --git a/demo/client/src/3d-demo.ts b/demo/client/src/3d-demo.ts index 42bdcb1b..0a8f9a50 100644 --- a/demo/client/src/3d-demo.ts +++ b/demo/client/src/3d-demo.ts @@ -44,8 +44,8 @@ const FONT: string = 'open-sans'; const PIXELS_PER_UNIT: number = 1.0; const FOV: number = 45.0; -const NEAR_CLIP_PLANE: number = 0.1; -const FAR_CLIP_PLANE: number = 10000.0; +export const NEAR_CLIP_PLANE: number = 0.1; +export const FAR_CLIP_PLANE: number = 100000.0; const ATLAS_FONT_SIZE: number = 48; diff --git a/demo/client/src/app-controller.ts b/demo/client/src/app-controller.ts index 9df5b686..1ac86945 100644 --- a/demo/client/src/app-controller.ts +++ b/demo/client/src/app-controller.ts @@ -167,6 +167,16 @@ export abstract class DemoAppController extends AppContro }, false); } + const vrButton = document.getElementById('pf-vr') as HTMLInputElement | + null; + if (vrButton != null) { + vrButton.addEventListener('click', event => { + this.view.then(view => { + view.enterVR(); + }); + }, false); + } + this.filePickerView = FilePickerView.create(); if (this.filePickerView != null) { this.filePickerView.onFileLoaded = fileData => this.fileLoaded(fileData, null); diff --git a/demo/client/src/renderer.ts b/demo/client/src/renderer.ts index 6530c2dd..d8db48e4 100644 --- a/demo/client/src/renderer.ts +++ b/demo/client/src/renderer.ts @@ -137,6 +137,10 @@ export abstract class Renderer { abstract setHintsUniform(uniforms: UniformMap): void; abstract pathTransformsForObject(objectIndex: number): PathTransformBuffers; + redrawVR(frame: VRFrameData): void { + this.redraw(); + } + redraw(): void { const renderContext = this.renderContext; diff --git a/demo/client/src/view.ts b/demo/client/src/view.ts index 2e017d73..e1af24a3 100644 --- a/demo/client/src/view.ts +++ b/demo/client/src/view.ts @@ -10,6 +10,7 @@ import * as glmatrix from 'gl-matrix'; +import {FAR_CLIP_PLANE, NEAR_CLIP_PLANE} from './3d-demo'; import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from "./aa-strategy"; import {StemDarkeningMode, SubpixelAAType} from "./aa-strategy"; import {AAOptions} from './app-controller'; @@ -174,6 +175,10 @@ export abstract class DemoView extends PathfinderView implements RenderContext { protected colorBufferHalfFloatExt: any; private wantsScreenshot: boolean; + private vrDisplay: VRDisplay | null; + private vrFrameData: VRFrameData | null; + private inVRRAF: boolean; + private inVR: boolean; /// NB: All subclasses are responsible for creating a renderer in their constructors. constructor(areaLUT: HTMLImageElement, @@ -194,6 +199,61 @@ export abstract class DemoView extends PathfinderView implements RenderContext { this.gammaLUT = gammaLUT; this.wantsScreenshot = false; + + + this.inVRRAF = false; + this.inVR = false; + this.vrDisplay = null; + if ("VRFrameData" in window) { + this.vrFrameData = new VRFrameData; + } else { + this.vrFrameData = null; + } + + this.vrSetup(); + } + + vrSetup(): void { + if (navigator.getVRDisplays) { + navigator.getVRDisplays().then((displays) => { + if (displays.length > 0) { + this.vrDisplay = displays[displays.length - 1]; + + // It's heighly reccommended that you set the near and far planes to + // something appropriate for your scene so the projection matricies + // WebVR produces have a well scaled depth buffer. + this.vrDisplay.depthNear = NEAR_CLIP_PLANE; + this.vrDisplay.depthFar = FAR_CLIP_PLANE; + unwrapNull(document.getElementById('pf-vr')).style.display = "initial"; + } else { + // no vr displays + } + }); + } else { + // no vr support + } + + window.addEventListener('vrdisplaypresentchange', () => { + + if (this.vrDisplay == null) + return; + + if (this.vrDisplay.isPresenting) { + const that = this; + function vrCallback(): void { + if (that.vrDisplay == null || !that.inVR) { + return; + } + that.vrDisplay.requestAnimationFrame(vrCallback); + that.inVRRAF = true; + that.redraw(); + that.inVRRAF = false; + } + this.vrDisplay.requestAnimationFrame(vrCallback); + } else { + this.inVR = false; + } + }); } attachMeshes(meshes: PathfinderPackedMeshes[]): void { @@ -245,13 +305,30 @@ export abstract class DemoView extends PathfinderView implements RenderContext { return buffer; } + enterVR(): void { + if (this.vrDisplay != null) { + this.inVR = true; + this.vrDisplay.requestPresent([{ source: this.canvas }]); + } + } + redraw(): void { super.redraw(); if (!this.renderer.meshesAttached) return; - this.renderer.redraw(); + if (!this.inVR || this.vrDisplay == null || this.vrFrameData == null) { + this.renderer.redraw(); + } else { + if (!this.inVRRAF) { + // redraw() called outside of vr RAF, will get drawn later + return; + } + this.vrDisplay.getFrameData(this.vrFrameData); + this.renderer.redrawVR(this.vrFrameData); + this.vrDisplay.submitFrame(); + } // Invoke the post-render hook. this.renderingFinished(); diff --git a/demo/client/tsconfig.json b/demo/client/tsconfig.json index 09871b14..b5cc0f86 100644 --- a/demo/client/tsconfig.json +++ b/demo/client/tsconfig.json @@ -8,7 +8,8 @@ "lodash", "node", "opentype.js", - "webgl-ext" + "webgl-ext", + "webvr-api" ], "typeRoots": [ "node_modules/@types"