Make it possible to enter VR mode

This commit is contained in:
Manish Goregaokar 2018-03-09 15:19:06 -08:00
parent 7e115826a1
commit 975685c23b
7 changed files with 103 additions and 4 deletions

View File

@ -42,6 +42,12 @@
aria-expanded="false" aria-controls="#pf-settings">
<span class="pf-material-icons">settings</span>
</button>
<button id="pf-vr" type="button"
class="btn btn-outline-secondary pf-toolbar-button"
aria-expanded="false" aria-controls="#pf-vr"
style="display: none">
<span>VR</span>
</button>
</div>
</div>
{{>partials/spinner.html}}

View File

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

View File

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

View File

@ -167,6 +167,16 @@ export abstract class DemoAppController<View extends DemoView> 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);

View File

@ -137,6 +137,10 @@ export abstract class Renderer {
abstract setHintsUniform(uniforms: UniformMap): void;
abstract pathTransformsForObject(objectIndex: number): PathTransformBuffers<Float32Array>;
redrawVR(frame: VRFrameData): void {
this.redraw();
}
redraw(): void {
const renderContext = this.renderContext;

View File

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

View File

@ -8,7 +8,8 @@
"lodash",
"node",
"opentype.js",
"webgl-ext"
"webgl-ext",
"webvr-api"
],
"typeRoots": [
"node_modules/@types"