Add a simple model of the Mozilla Monument to the 3D scene
This commit is contained in:
parent
473c28e16d
commit
43513da957
|
@ -26,6 +26,7 @@ import * as _ from "lodash";
|
|||
import PathfinderBufferTexture from "./buffer-texture";
|
||||
|
||||
const WIDTH: number = 150000;
|
||||
const PADDING: number = 2000;
|
||||
|
||||
const TEXT_DATA_URI: string = "/data/mozmonument.json";
|
||||
|
||||
|
@ -34,12 +35,41 @@ const FONT: string = 'open-sans';
|
|||
const PIXELS_PER_UNIT: number = 1.0;
|
||||
|
||||
const FOV: number = 45.0;
|
||||
const NEAR_CLIP_PLANE: number = 0.01;
|
||||
const FAR_CLIP_PLANE: number = 200000.0;
|
||||
const NEAR_CLIP_PLANE: number = 0.1;
|
||||
const FAR_CLIP_PLANE: number = 3000.0;
|
||||
|
||||
const SCALE: glmatrix.vec3 = glmatrix.vec3.fromValues(1.0 / 200.0, 1.0 / 200.0, 1.0 / 200.0);
|
||||
|
||||
const TEXT_TRANSLATION: number[] = [-WIDTH * 0.5, 0.0, WIDTH * 0.5];
|
||||
const TEXT_TRANSLATION: number[] = [-(WIDTH + PADDING) * 0.5, 0.0, (WIDTH + PADDING) * 0.5];
|
||||
|
||||
const MONUMENT_TRANSLATION: glmatrix.vec3 = glmatrix.vec3.fromValues(0.0, -690.0, 0.0);
|
||||
const MONUMENT_SCALE: glmatrix.vec3 =
|
||||
glmatrix.vec3.fromValues((WIDTH + PADDING) / 400.0 - 0.5,
|
||||
700.0,
|
||||
(WIDTH + PADDING) / 400.0 - 0.5);
|
||||
|
||||
const TEXT_COLOR: Uint8Array = new Uint8Array([0xf2, 0xf8, 0xf8, 0xff]);
|
||||
const MONUMENT_COLOR: number[] = [0x70 / 0xff, 0x80 / 0xff, 0x80 / 0xff];
|
||||
|
||||
const CUBE_VERTEX_POSITIONS: Float32Array = new Float32Array([
|
||||
-1.0, -1.0, -1.0, // 0
|
||||
1.0, -1.0, -1.0, // 1
|
||||
-1.0, -1.0, 1.0, // 2
|
||||
1.0, -1.0, 1.0, // 3
|
||||
-1.0, 1.0, -1.0, // 4
|
||||
1.0, 1.0, -1.0, // 5
|
||||
-1.0, 1.0, 1.0, // 6
|
||||
1.0, 1.0, 1.0, // 7
|
||||
]);
|
||||
|
||||
const CUBE_INDICES: Uint16Array = new Uint16Array([
|
||||
0, 1, 2, 2, 1, 3, // bottom
|
||||
0, 5, 1, 0, 4, 5, // front
|
||||
2, 4, 0, 2, 6, 4, // left
|
||||
3, 5, 1, 3, 7, 5, // right
|
||||
2, 7, 3, 2, 6, 7, // back
|
||||
4, 5, 6, 6, 5, 7, // top
|
||||
]);
|
||||
|
||||
const ANTIALIASING_STRATEGIES: AntialiasingStrategyTable = {
|
||||
none: NoAAStrategy,
|
||||
|
@ -174,6 +204,14 @@ class ThreeDView extends PathfinderDemoView {
|
|||
|
||||
this.camera = new PerspectiveCamera(this.canvas);
|
||||
this.camera.onChange = () => this.setDirty();
|
||||
|
||||
this.cubeVertexPositionBuffer = unwrapNull(this.gl.createBuffer());
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexPositionBuffer);
|
||||
this.gl.bufferData(this.gl.ARRAY_BUFFER, CUBE_VERTEX_POSITIONS, this.gl.STATIC_DRAW);
|
||||
|
||||
this.cubeIndexBuffer = unwrapNull(this.gl.createBuffer());
|
||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.cubeIndexBuffer);
|
||||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, CUBE_INDICES, this.gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
uploadPathMetadata() {
|
||||
|
@ -194,9 +232,7 @@ class ThreeDView extends PathfinderDemoView {
|
|||
for (let pathIndex = 0; pathIndex < pathCount; pathIndex++) {
|
||||
const startOffset = (pathIndex + 1) * 4;
|
||||
|
||||
for (let channel = 0; channel < 3; channel++)
|
||||
pathColors[startOffset + channel] = 0x00; // RGB
|
||||
pathColors[startOffset + 3] = 0xff; // alpha
|
||||
pathColors.set(TEXT_COLOR, startOffset);
|
||||
|
||||
const textGlyph = textGlyphs[pathIndex];
|
||||
const glyphRect = textGlyph.pixelRect(PIXELS_PER_UNIT);
|
||||
|
@ -222,6 +258,38 @@ class ThreeDView extends PathfinderDemoView {
|
|||
throw new PathfinderError("Unsupported antialiasing type!");
|
||||
}
|
||||
|
||||
protected drawSceneryIfNecessary(): void {
|
||||
// Set up the cube VBO.
|
||||
const shaderProgram = this.shaderPrograms.demo3DMonument;
|
||||
this.gl.useProgram(shaderProgram.program);
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexPositionBuffer);
|
||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.cubeIndexBuffer);
|
||||
this.gl.vertexAttribPointer(shaderProgram.attributes.aPosition,
|
||||
3,
|
||||
this.gl.FLOAT,
|
||||
false,
|
||||
0,
|
||||
0);
|
||||
this.gl.enableVertexAttribArray(shaderProgram.attributes.aPosition);
|
||||
|
||||
// Set uniforms for the monument.
|
||||
const transform = this.calculateWorldTransform(MONUMENT_TRANSLATION, MONUMENT_SCALE);
|
||||
this.gl.uniformMatrix4fv(shaderProgram.uniforms.uTransform, false, transform);
|
||||
this.gl.uniform4f(shaderProgram.uniforms.uColor,
|
||||
MONUMENT_COLOR[0],
|
||||
MONUMENT_COLOR[1],
|
||||
MONUMENT_COLOR[2],
|
||||
1.0);
|
||||
|
||||
// Set state for the monument.
|
||||
this.gl.enable(this.gl.DEPTH_TEST);
|
||||
this.gl.depthMask(true);
|
||||
this.gl.disable(this.gl.SCISSOR_TEST);
|
||||
|
||||
// Draw the monument!
|
||||
this.gl.drawElements(this.gl.TRIANGLES, CUBE_INDICES.length, this.gl.UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
protected compositeIfNecessary(): void {}
|
||||
|
||||
protected updateTimings(timings: Timings) {
|
||||
|
@ -244,7 +312,9 @@ class ThreeDView extends PathfinderDemoView {
|
|||
return glmatrix.vec2.fromValues(1.0, 1.0);
|
||||
}
|
||||
|
||||
protected get worldTransform() {
|
||||
private calculateWorldTransform(modelviewTranslation: glmatrix.vec3,
|
||||
modelviewScale: glmatrix.vec3):
|
||||
glmatrix.mat4 {
|
||||
const projection = glmatrix.mat4.create();
|
||||
glmatrix.mat4.perspective(projection,
|
||||
FOV / 180.0 * Math.PI,
|
||||
|
@ -255,13 +325,25 @@ class ThreeDView extends PathfinderDemoView {
|
|||
const modelview = glmatrix.mat4.create();
|
||||
glmatrix.mat4.mul(modelview, modelview, this.camera.rotationMatrix);
|
||||
glmatrix.mat4.translate(modelview, modelview, this.camera.translation);
|
||||
glmatrix.mat4.scale(modelview, modelview, SCALE);
|
||||
glmatrix.mat4.translate(modelview, modelview, modelviewTranslation);
|
||||
glmatrix.mat4.scale(modelview, modelview, modelviewScale);
|
||||
|
||||
const transform = glmatrix.mat4.create();
|
||||
glmatrix.mat4.mul(transform, projection, modelview);
|
||||
return transform;
|
||||
}
|
||||
|
||||
protected clearForResolve(): void {
|
||||
this.gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||
this.gl.clearDepth(1.0);
|
||||
this.gl.depthMask(true);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
protected get worldTransform() {
|
||||
return this.calculateWorldTransform(glmatrix.vec3.create(), SCALE);
|
||||
}
|
||||
|
||||
protected getModelviewTransform(objectIndex: number): glmatrix.mat4 {
|
||||
const transform = glmatrix.mat4.create();
|
||||
glmatrix.mat4.rotateY(transform, transform, Math.PI / 2.0 * objectIndex);
|
||||
|
@ -277,10 +359,15 @@ class ThreeDView extends PathfinderDemoView {
|
|||
return 'direct3DInterior';
|
||||
}
|
||||
|
||||
protected depthFunction: number = this.gl.LESS;
|
||||
|
||||
private _scale: number;
|
||||
|
||||
private appController: ThreeDController;
|
||||
|
||||
private cubeVertexPositionBuffer: WebGLBuffer;
|
||||
private cubeIndexBuffer: WebGLBuffer;
|
||||
|
||||
camera: PerspectiveCamera;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,12 +63,6 @@ export class NoAAStrategy extends AntialiasingStrategy {
|
|||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
||||
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
||||
view.gl.disable(view.gl.SCISSOR_TEST);
|
||||
|
||||
// Clear.
|
||||
view.gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||
view.gl.clearDepth(0.0);
|
||||
view.gl.depthMask(true);
|
||||
view.gl.clear(view.gl.COLOR_BUFFER_BIT | view.gl.DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
resolve(view: PathfinderDemoView) {}
|
||||
|
|
|
@ -135,8 +135,8 @@ export class PerspectiveCamera extends Camera {
|
|||
if (document.pointerLockElement !== this.canvas)
|
||||
return;
|
||||
|
||||
this.rotation[1] += event.movementX * PERSPECTIVE_ROTATION_SPEED;
|
||||
this.rotation[0] += event.movementY * PERSPECTIVE_ROTATION_SPEED;
|
||||
this.rotation[0] += event.movementX * PERSPECTIVE_ROTATION_SPEED;
|
||||
this.rotation[1] += event.movementY * PERSPECTIVE_ROTATION_SPEED;
|
||||
|
||||
if (this.onChange != null)
|
||||
this.onChange();
|
||||
|
@ -144,8 +144,8 @@ export class PerspectiveCamera extends Camera {
|
|||
|
||||
get rotationMatrix(): glmatrix.mat4 {
|
||||
const matrix = glmatrix.mat4.create();
|
||||
glmatrix.mat4.fromYRotation(matrix, this.rotation[1]);
|
||||
glmatrix.mat4.rotateX(matrix, matrix, this.rotation[0]);
|
||||
glmatrix.mat4.fromXRotation(matrix, this.rotation[1]);
|
||||
glmatrix.mat4.rotateY(matrix, matrix, this.rotation[0]);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,12 +75,6 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
view.gl.viewport(0, 0, framebufferSize[0], framebufferSize[1]);
|
||||
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
||||
view.gl.enable(view.gl.SCISSOR_TEST);
|
||||
|
||||
// Clear.
|
||||
view.gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||
view.gl.clearDepth(0.0);
|
||||
view.gl.depthMask(true);
|
||||
view.gl.clear(view.gl.COLOR_BUFFER_BIT | view.gl.DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
resolve(view: PathfinderDemoView) {
|
||||
|
|
|
@ -274,6 +274,8 @@ class SVGDemoView extends PathfinderDemoView {
|
|||
return 'directInterior';
|
||||
}
|
||||
|
||||
protected depthFunction: number = this.gl.GREATER;
|
||||
|
||||
private appController: SVGDemoController;
|
||||
|
||||
camera: OrthographicCamera;
|
||||
|
|
|
@ -505,6 +505,8 @@ class TextDemoView extends MonochromePathfinderView {
|
|||
return 'directInterior';
|
||||
}
|
||||
|
||||
protected depthFunction: number = this.gl.GREATER;
|
||||
|
||||
atlasFramebuffer: WebGLFramebuffer;
|
||||
atlasDepthTexture: WebGLTexture;
|
||||
|
||||
|
|
|
@ -247,6 +247,12 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
const antialiasingStrategy = unwrapNull(this.antialiasingStrategy);
|
||||
antialiasingStrategy.prepare(this);
|
||||
|
||||
// Clear.
|
||||
this.clearForResolve();
|
||||
|
||||
// Draw "scenery" (used in the 3D view).
|
||||
this.drawSceneryIfNecessary();
|
||||
|
||||
// Perform direct rendering (Loop-Blinn).
|
||||
if (antialiasingStrategy.shouldRenderDirect)
|
||||
this.renderDirect();
|
||||
|
@ -287,7 +293,7 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
const meshes = this.meshes[objectIndex];
|
||||
|
||||
// Set up implicit cover state.
|
||||
this.gl.depthFunc(this.gl.GREATER);
|
||||
this.gl.depthFunc(this.depthFunction);
|
||||
this.gl.depthMask(true);
|
||||
this.gl.enable(this.gl.DEPTH_TEST);
|
||||
this.gl.disable(this.gl.BLEND);
|
||||
|
@ -458,6 +464,17 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
return glmatrix.mat4.create();
|
||||
}
|
||||
|
||||
protected drawSceneryIfNecessary(): void {}
|
||||
|
||||
protected clearForResolve(): void {
|
||||
this.gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||
this.gl.clearDepth(0.0);
|
||||
this.gl.depthMask(true);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
protected abstract get depthFunction(): number;
|
||||
|
||||
protected abstract createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
|
|
Loading…
Reference in New Issue