Make it possible to enter VR mode
This commit is contained in:
parent
7e115826a1
commit
975685c23b
|
@ -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}}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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();
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"lodash",
|
||||
"node",
|
||||
"opentype.js",
|
||||
"webgl-ext"
|
||||
"webgl-ext",
|
||||
"webvr-api"
|
||||
],
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
|
|
Loading…
Reference in New Issue