Add all four sides of the Mozilla Monument to the 3D demo
This commit is contained in:
parent
e34ca3d3e4
commit
57374e9f30
|
@ -23,6 +23,7 @@ import {PathfinderError, assert, panic, unwrapNull} from "./utils";
|
|||
import {PathfinderDemoView, Timings} from "./view";
|
||||
import SSAAStrategy from "./ssaa-strategy";
|
||||
import * as _ from "lodash";
|
||||
import PathfinderBufferTexture from "./buffer-texture";
|
||||
|
||||
const WIDTH: number = 150000;
|
||||
|
||||
|
@ -34,9 +35,11 @@ const PIXELS_PER_UNIT: number = 1.0;
|
|||
|
||||
const FOV: number = 45.0;
|
||||
const NEAR_CLIP_PLANE: number = 0.01;
|
||||
const FAR_CLIP_PLANE: number = 10000.0;
|
||||
const FAR_CLIP_PLANE: number = 200000.0;
|
||||
|
||||
const SCALE: glmatrix.vec3 = glmatrix.vec3.fromValues(1.0 / 200.0, 1.0 / 200.0, 1.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 ANTIALIASING_STRATEGIES: AntialiasingStrategyTable = {
|
||||
none: NoAAStrategy,
|
||||
|
@ -48,58 +51,65 @@ interface AntialiasingStrategyTable {
|
|||
ssaa: typeof SSAAStrategy;
|
||||
}
|
||||
|
||||
interface Panels {
|
||||
upper: string[][];
|
||||
lower: string[][];
|
||||
interface TextLine {
|
||||
names: string[];
|
||||
}
|
||||
|
||||
interface MonumentSide {
|
||||
lines: TextLine[];
|
||||
}
|
||||
|
||||
class ThreeDController extends DemoAppController<ThreeDView> {
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
this.textPromise = window.fetch(TEXT_DATA_URI)
|
||||
this.monumentPromise = window.fetch(TEXT_DATA_URI)
|
||||
.then(response => response.json())
|
||||
.then(textData => this.parseTextData(textData));
|
||||
|
||||
this.loadInitialFile();
|
||||
}
|
||||
|
||||
private parseTextData(textData: any): string[][] {
|
||||
const panels = {
|
||||
upper: [],
|
||||
lower: [],
|
||||
};
|
||||
private parseTextData(textData: any): MonumentSide[] {
|
||||
const sides = [];
|
||||
for (let sideIndex = 0; sideIndex < 4; sideIndex++)
|
||||
sides[sideIndex] = { upper: { lines: [] }, lower: { lines: [] } };
|
||||
|
||||
for (const nameData of textData.monument) {
|
||||
if (nameData.side !== '1')
|
||||
const side = parseInt(nameData.side) - 1;
|
||||
const row = parseInt(nameData.row) - 1;
|
||||
const number = parseInt(nameData.number) - 1;
|
||||
|
||||
if (sides[side] == null)
|
||||
continue;
|
||||
|
||||
const row = parseInt(nameData.row) - 1, number = parseInt(nameData.number) - 1;
|
||||
const panel: string[][] = panels[nameData.panel as ('upper' | 'lower')];
|
||||
const lines: TextLine[] = sides[side][nameData.panel as ('upper' | 'lower')].lines;
|
||||
if (lines[row] == null)
|
||||
lines[row] = { names: [] };
|
||||
|
||||
if (panel[row] == null)
|
||||
panel[row] = [];
|
||||
panel[row][number] = nameData.name;
|
||||
lines[row].names[number] = nameData.name;
|
||||
}
|
||||
|
||||
return panels.upper.concat(panels.lower);
|
||||
return sides.map(side => ({ lines: side.upper.lines.concat(side.lower.lines) }));
|
||||
}
|
||||
|
||||
protected fileLoaded(): void {
|
||||
const font = opentype.parse(this.fileData);
|
||||
assert(font.isSupported(), "The font type is unsupported!");
|
||||
|
||||
this.textPromise.then(text => this.layoutText(font, text));
|
||||
this.monumentPromise.then(monument => this.layoutMonument(font, monument));
|
||||
}
|
||||
|
||||
private layoutText(font: opentype.Font, text: string[][]) {
|
||||
private layoutMonument(font: opentype.Font, monument: MonumentSide[]) {
|
||||
const createGlyph = (glyph: opentype.Glyph) => new ThreeDGlyph(glyph);
|
||||
let textFrames = [];
|
||||
for (const monumentSide of monument) {
|
||||
let textRuns = [];
|
||||
for (let lineNumber = 0; lineNumber < text.length; lineNumber++) {
|
||||
const line = text[lineNumber];
|
||||
for (let lineNumber = 0; lineNumber < monumentSide.lines.length; lineNumber++) {
|
||||
const line = monumentSide.lines[lineNumber];
|
||||
|
||||
const lineY = -lineNumber * font.lineHeight();
|
||||
const lineGlyphs = line.map(string => {
|
||||
const lineGlyphs = line.names.map(string => {
|
||||
const glyphs = font.stringToGlyphs(string).map(createGlyph);
|
||||
return { glyphs: glyphs, width: _.sumBy(glyphs, glyph => glyph.advanceWidth) };
|
||||
});
|
||||
|
@ -110,15 +120,16 @@ class ThreeDController extends DemoAppController<ThreeDView> {
|
|||
|
||||
let currentX = 0.0;
|
||||
for (const glyphInfo of lineGlyphs) {
|
||||
textRuns.push(new TextRun(glyphInfo.glyphs, [currentX, lineY], font, createGlyph));
|
||||
const textRunOrigin = [currentX, lineY];
|
||||
textRuns.push(new TextRun(glyphInfo.glyphs, textRunOrigin, font, createGlyph));
|
||||
currentX += glyphInfo.width + spacing;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(pcwalton)
|
||||
const textFrame = new TextFrame(textRuns, glmatrix.vec3.create());
|
||||
textFrames.push(new TextFrame(textRuns));
|
||||
}
|
||||
|
||||
this.glyphStorage = new GlyphStorage(this.fileData, [textFrame], createGlyph, font);
|
||||
this.glyphStorage = new GlyphStorage(this.fileData, textFrames, createGlyph, font);
|
||||
this.glyphStorage.layoutRuns();
|
||||
|
||||
this.glyphStorage.partition().then((baseMeshes: PathfinderMeshData) => {
|
||||
|
@ -150,7 +161,7 @@ class ThreeDController extends DemoAppController<ThreeDView> {
|
|||
private baseMeshes: PathfinderMeshData;
|
||||
private expandedMeshes: ExpandedMeshData[];
|
||||
|
||||
private textPromise: Promise<string[][]>;
|
||||
private monumentPromise: Promise<MonumentSide[]>;
|
||||
}
|
||||
|
||||
class ThreeDView extends PathfinderDemoView {
|
||||
|
@ -166,7 +177,15 @@ class ThreeDView extends PathfinderDemoView {
|
|||
}
|
||||
|
||||
uploadPathMetadata() {
|
||||
const textGlyphs = this.appController.glyphStorage.allGlyphs;
|
||||
this.pathColorsBufferTextures = [];
|
||||
this.pathTransformBufferTextures = [];
|
||||
|
||||
const textFrameCount = this.appController.glyphStorage.textFrames.length;
|
||||
for (let textFrameIndex = 0;
|
||||
textFrameIndex < textFrameCount;
|
||||
textFrameIndex++) {
|
||||
const textFrame = this.appController.glyphStorage.textFrames[textFrameIndex];
|
||||
const textGlyphs = textFrame.allGlyphs;
|
||||
const pathCount = textGlyphs.length;
|
||||
|
||||
const pathColors = new Uint8Array(4 * (pathCount + 1));
|
||||
|
@ -184,8 +203,14 @@ class ThreeDView extends PathfinderDemoView {
|
|||
pathTransforms.set([1, 1, glyphRect[0], glyphRect[1]], startOffset);
|
||||
}
|
||||
|
||||
this.pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
this.pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
const pathColorsBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathColors');
|
||||
const pathTransformBufferTexture = new PathfinderBufferTexture(this.gl,
|
||||
'uPathTransform');
|
||||
pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
this.pathColorsBufferTextures.push(pathColorsBufferTexture);
|
||||
this.pathTransformBufferTextures.push(pathTransformBufferTexture);
|
||||
}
|
||||
}
|
||||
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
|
@ -237,6 +262,13 @@ class ThreeDView extends PathfinderDemoView {
|
|||
return transform;
|
||||
}
|
||||
|
||||
protected getModelviewTransform(objectIndex: number): glmatrix.mat4 {
|
||||
const transform = glmatrix.mat4.create();
|
||||
glmatrix.mat4.rotateY(transform, transform, Math.PI / 2.0 * objectIndex);
|
||||
glmatrix.mat4.translate(transform, transform, TEXT_TRANSLATION);
|
||||
return transform;
|
||||
}
|
||||
|
||||
protected get directCurveProgramName(): keyof ShaderMap<void> {
|
||||
return 'direct3DCurve';
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
view.setFramebufferSizeUniform(uniforms);
|
||||
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
|
||||
this.bVertexPathIDBufferTexture.bind(view.gl, uniforms, 1);
|
||||
view.pathTransformBufferTexture.bind(view.gl, uniforms, 2);
|
||||
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 2);
|
||||
view.gl.uniform1f(uniforms.uScaleX, this.supersampleScale[0]);
|
||||
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
||||
6,
|
||||
|
@ -335,7 +335,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
view.setFramebufferSizeUniform(uniforms);
|
||||
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
|
||||
this.bVertexPathIDBufferTexture.bind(view.gl, uniforms, 1);
|
||||
view.pathTransformBufferTexture.bind(view.gl, uniforms, 2);
|
||||
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 2);
|
||||
view.gl.uniform1f(uniforms.uScaleX, this.supersampleScale[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class MeshDebuggerAppController extends AppController {
|
|||
|
||||
const createGlyph = (glyph: opentype.Glyph) => new MeshDebuggerGlyph(glyph);
|
||||
const textRun = new TextRun<MeshDebuggerGlyph>(CHARACTER, [0, 0], font, createGlyph);
|
||||
const textFrame = new TextFrame([textRun], glmatrix.vec3.create());
|
||||
const textFrame = new TextFrame([textRun]);
|
||||
this.glyphStorage = new GlyphStorage(this.fileData, [textFrame], createGlyph, font);
|
||||
|
||||
this.glyphStorage.partition().then(meshes => {
|
||||
|
|
|
@ -21,6 +21,7 @@ import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
|||
import {panic, unwrapNull} from './utils';
|
||||
import {PathfinderDemoView, Timings} from './view';
|
||||
import SSAAStrategy from "./ssaa-strategy";
|
||||
import PathfinderBufferTexture from "./buffer-texture";
|
||||
|
||||
const parseColor = require('parse-color');
|
||||
|
||||
|
@ -208,8 +209,12 @@ class SVGDemoView extends PathfinderDemoView {
|
|||
pathTransforms.set([1, 1, 0, 0], startOffset);
|
||||
}
|
||||
|
||||
this.pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
this.pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
const pathColorsBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathColors');
|
||||
const pathTransformBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathTransform');
|
||||
pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
this.pathColorsBufferTextures = [pathColorsBufferTexture];
|
||||
this.pathTransformBufferTextures = [pathTransformBufferTexture];
|
||||
}
|
||||
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
|
|
|
@ -248,7 +248,9 @@ class TextDemoView extends MonochromePathfinderView {
|
|||
pathColors[(pathIndex + 1) * 4 + 3] = 0xff; // alpha
|
||||
}
|
||||
|
||||
this.pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
const pathColorsBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathColors');
|
||||
pathColorsBufferTexture.upload(this.gl, pathColors);
|
||||
this.pathColorsBufferTextures = [pathColorsBufferTexture];
|
||||
}
|
||||
|
||||
/// Lays out glyphs on the canvas.
|
||||
|
@ -322,7 +324,9 @@ class TextDemoView extends MonochromePathfinderView {
|
|||
transforms[pathID * 4 + 3] = atlasOrigin[1];
|
||||
}
|
||||
|
||||
this.pathTransformBufferTexture.upload(this.gl, transforms);
|
||||
const pathTransformBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathTransform');
|
||||
pathTransformBufferTexture.upload(this.gl, transforms);
|
||||
this.pathTransformBufferTextures = [pathTransformBufferTexture];
|
||||
}
|
||||
|
||||
private createAtlasFramebuffer() {
|
||||
|
|
|
@ -68,9 +68,8 @@ export class TextRun<Glyph extends PathfinderGlyph> {
|
|||
}
|
||||
|
||||
export class TextFrame<Glyph extends PathfinderGlyph> {
|
||||
constructor(runs: TextRun<Glyph>[], origin: glmatrix.vec3) {
|
||||
constructor(runs: TextRun<Glyph>[]) {
|
||||
this.runs = runs;
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
expandMeshes(uniqueGlyphs: Glyph[], meshes: PathfinderMeshData): ExpandedMeshData {
|
||||
|
@ -253,7 +252,7 @@ export class SimpleTextLayout<Glyph extends PathfinderGlyph> {
|
|||
const textRuns: TextRun<Glyph>[] = text.split("\n").map((line, lineNumber) => {
|
||||
return new TextRun<Glyph>(line, [0.0, -lineHeight * lineNumber], font, createGlyph);
|
||||
});
|
||||
this.textFrame = new TextFrame(textRuns, glmatrix.vec3.create());
|
||||
this.textFrame = new TextFrame(textRuns);
|
||||
|
||||
this.glyphStorage = new GlyphStorage(fontData, [this.textFrame], createGlyph, font);
|
||||
}
|
||||
|
|
|
@ -104,8 +104,8 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
const shaderSource = this.compileShaders(commonShaderSource, shaderSources);
|
||||
this.shaderPrograms = this.linkShaders(shaderSource);
|
||||
|
||||
this.pathTransformBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathTransform');
|
||||
this.pathColorsBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathColors');
|
||||
this.pathTransformBufferTextures = [];
|
||||
this.pathColorsBufferTextures = [];
|
||||
|
||||
this.antialiasingStrategy = new NoAAStrategy(0, false);
|
||||
this.antialiasingStrategy.init(this);
|
||||
|
@ -266,15 +266,18 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.finishTiming();
|
||||
}
|
||||
|
||||
private setTransformUniform(uniforms: UniformMap) {
|
||||
private setTransformUniform(uniforms: UniformMap, objectIndex: number) {
|
||||
const transform = glmatrix.mat4.create();
|
||||
if (this.antialiasingStrategy != null)
|
||||
glmatrix.mat4.mul(transform, this.antialiasingStrategy.transform, this.worldTransform);
|
||||
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
||||
this.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
||||
}
|
||||
|
||||
private renderDirect() {
|
||||
for (const meshes of this.meshes) {
|
||||
for (let objectIndex = 0; objectIndex < this.meshes.length; objectIndex++) {
|
||||
const meshes = this.meshes[objectIndex];
|
||||
|
||||
// Set up implicit cover state.
|
||||
this.gl.depthFunc(this.gl.GREATER);
|
||||
this.gl.depthMask(true);
|
||||
|
@ -303,10 +306,14 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverInteriorIndices);
|
||||
|
||||
// Draw direct interior parts.
|
||||
this.setTransformUniform(directInteriorProgram.uniforms);
|
||||
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
|
||||
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
|
||||
this.pathColorsBufferTexture.bind(this.gl, directInteriorProgram.uniforms, 0);
|
||||
this.pathTransformBufferTexture.bind(this.gl, directInteriorProgram.uniforms, 1);
|
||||
this.pathColorsBufferTextures[objectIndex].bind(this.gl,
|
||||
directInteriorProgram.uniforms,
|
||||
0);
|
||||
this.pathTransformBufferTextures[objectIndex].bind(this.gl,
|
||||
directInteriorProgram.uniforms,
|
||||
1);
|
||||
let indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
||||
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
||||
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
||||
|
@ -354,10 +361,14 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverCurveIndices);
|
||||
|
||||
// Draw direct curve parts.
|
||||
this.setTransformUniform(directCurveProgram.uniforms);
|
||||
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
|
||||
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
|
||||
this.pathColorsBufferTexture.bind(this.gl, directCurveProgram.uniforms, 0);
|
||||
this.pathTransformBufferTexture.bind(this.gl, directCurveProgram.uniforms, 1);
|
||||
this.pathColorsBufferTextures[objectIndex].bind(this.gl,
|
||||
directCurveProgram.uniforms,
|
||||
0);
|
||||
this.pathTransformBufferTextures[objectIndex].bind(this.gl,
|
||||
directCurveProgram.uniforms,
|
||||
1);
|
||||
indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
||||
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
||||
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
||||
|
@ -413,6 +424,10 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
||||
}
|
||||
|
||||
protected getModelviewTransform(pathIndex: number): glmatrix.mat4 {
|
||||
return glmatrix.mat4.create();
|
||||
}
|
||||
|
||||
protected abstract createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
|
@ -454,8 +469,8 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
meshes: PathfinderMeshBuffers[];
|
||||
meshData: PathfinderMeshData[];
|
||||
|
||||
pathTransformBufferTexture: PathfinderBufferTexture;
|
||||
protected pathColorsBufferTexture: PathfinderBufferTexture;
|
||||
pathTransformBufferTextures: PathfinderBufferTexture[];
|
||||
protected pathColorsBufferTextures: PathfinderBufferTexture[];
|
||||
|
||||
private atlasRenderingTimerQuery: WebGLQuery;
|
||||
private compositingTimerQuery: WebGLQuery;
|
||||
|
|
Loading…
Reference in New Issue