Added UI value cacheing

This commit is contained in:
Lucas Dower 2022-02-19 15:54:28 +00:00
parent bb11207e70
commit 24a4038362
10 changed files with 69 additions and 40 deletions

View File

@ -110,6 +110,7 @@ export class AppContext {
this._warnings = [];
const groupName = UI.Get.uiOrder[action];
LOG(`Doing ${action}`);
UI.Get.cacheValues(action);
const delegate = this._actionMap.get(action)!;
try {
delegate.action();
@ -141,12 +142,8 @@ export class AppContext {
}
private _import() {
const objPath = UI.Get.layout.import.elements.input.getValue();
this._loadedMesh = new ObjImporter().createMesh(objPath);
this._loadedMesh = new ObjImporter().createMesh();
Renderer.Get.useMesh(this._loadedMesh);
LOG(this._loadedMesh);
LOG(Renderer.Get);
}
private _simplify() {
@ -154,30 +151,23 @@ export class AppContext {
}
private _voxelise() {
const desiredHeight = UI.Get.layout.build.elements.height.getValue();
const ambientOcclusion = UI.Get.layout.build.elements.ambientOcclusion.getValue() === 'on';
const multisampleColouring = UI.Get.layout.build.elements.multisampleColouring.getValue() === 'on';
const textureFiltering = UI.Get.layout.build.elements.textureFiltering.getValue() === 'nearest' ? TextureFiltering.Nearest : TextureFiltering.Linear;
ASSERT(this._loadedMesh);
this._loadedVoxelMesh = new VoxelMesh(desiredHeight);
this._loadedVoxelMesh.voxelise(this._loadedMesh, multisampleColouring, textureFiltering);
this._loadedVoxelMesh = new VoxelMesh();
this._loadedVoxelMesh.voxelise(this._loadedMesh);
Renderer.Get.useVoxelMesh(this._loadedVoxelMesh, ambientOcclusion);
Renderer.Get.useVoxelMesh(this._loadedVoxelMesh);
}
private _palette() {
const ditheringEnabled = UI.Get.layout.palette.elements.dithering.getValue() === 'on';
ASSERT(this._loadedVoxelMesh);
this._loadedBlockMesh = new BlockMesh(ditheringEnabled);
this._loadedBlockMesh = new BlockMesh();
this._loadedBlockMesh.assignBlocks(this._loadedVoxelMesh);
Renderer.Get.useBlockMesh(this._loadedBlockMesh);
}
private _export() {
const exportFormat = UI.Get.layout.export.elements.export.getValue();
const exportFormat = UI.Get.layout.export.elements.export.getCachedValue() as string;
const exporter = (exportFormat === 'schematic') ? new Schematic() : new Litematic();
if (exportFormat === 'schematic') {

View File

@ -3,6 +3,7 @@ import { Voxel, VoxelMesh } from './voxel_mesh';
import { BlockInfo } from './block_atlas';
import { CustomError, LOG } from './util';
import { Renderer } from './renderer';
import { UI } from './ui/layout';
interface Block {
voxel: Voxel;
@ -15,10 +16,10 @@ export class BlockMesh {
private _blocks: Block[];
private _voxelMesh?: VoxelMesh;
public constructor(ditheringEnabled: boolean) {
public constructor() {
LOG('New block mesh');
this._ditheringEnabled = ditheringEnabled;
this._ditheringEnabled = UI.Get.layout.palette.elements.dithering.getCachedValue() as string === 'on';
this._blockPalette = [];
this._blocks = [];
}

View File

@ -7,6 +7,7 @@ import { IImporter } from '../importer';
import { MaterialType, Mesh, SolidMaterial, TexturedMaterial, Tri } from '../mesh';
import { Vector3 } from '../vector';
import { UV, ASSERT, RGB, LOG_WARN } from '../util';
import { UI } from '../ui/layout';
export class ObjImporter extends IImporter {
private _vertices!: Vector3[];
@ -15,7 +16,8 @@ export class ObjImporter extends IImporter {
private _materials!: {[key: string]: (SolidMaterial | TexturedMaterial)};
private _mtlLibs!: string[];
override createMesh(filePath: string): Mesh {
override createMesh(): Mesh {
const filePath = UI.Get.layout.import.elements.input.getCachedValue();
ASSERT(path.isAbsolute(filePath));
this._parseOBJ(filePath);

View File

@ -129,10 +129,10 @@ export class Renderer {
this._meshToUse = MeshType.TriangleMesh;
}
public useVoxelMesh(voxelMesh: VoxelMesh, ambientOcclusionEnabled: boolean) {
public useVoxelMesh(voxelMesh: VoxelMesh) {
LOG('Using voxel mesh');
LOG(voxelMesh);
this._voxelBuffer = voxelMesh.createBuffer(ambientOcclusionEnabled);
this._voxelBuffer = voxelMesh.createBuffer();
this._meshToUse = MeshType.VoxelMesh;
this._voxelSize = voxelMesh?.getVoxelSize();
}

View File

@ -1,7 +1,11 @@
import { ASSERT } from '../../util';
export abstract class BaseUIElement {
protected _id: string;
protected _label: string;
protected _isEnabled: boolean;
protected _value: any;
protected _cachedValue?: any;
constructor(label: string) {
this._id = '_' + Math.random().toString(16);
@ -14,8 +18,22 @@ export abstract class BaseUIElement {
this._onEnabledChanged();
}
public getCachedValue() {
ASSERT(this._cachedValue !== undefined, 'Attempting to access value before cached');
return this._cachedValue;
}
protected getValue() {
return this._value;
}
public cacheValue() {
this._cachedValue = this.getValue();
}
public abstract generateHTML(): string;
public abstract registerEvents(): void;
protected abstract _onEnabledChanged(): void;
}

View File

@ -30,7 +30,7 @@ export class ComboBoxElement extends LabelledElement {
public registerEvents(): void {
}
public getValue() {
protected getValue() {
const element = document.getElementById(this._id) as HTMLSelectElement;
ASSERT(element !== null);
return this._items[element.selectedIndex].id;

View File

@ -42,18 +42,16 @@ export class FileInputElement extends LabelledElement {
if (files && files.length === 1) {
const filePath = files[0];
this._loadedFilePath = filePath;
this._value = filePath;
} else {
this._loadedFilePath = '';
this._value = '';
}
const parsedPath = path.parse(this._loadedFilePath);
element.innerHTML = parsedPath.name + parsedPath.ext;
};
}
public getValue() {
return this._loadedFilePath;
}
protected _onEnabledChanged() {
super._onEnabledChanged();

View File

@ -6,7 +6,6 @@ export class SliderElement extends LabelledElement {
private _min: number;
private _max: number;
private _decimals: number;
private _value: number;
private _dragging: boolean;
public constructor(label: string, min: number, max: number, decimals: number, value: number) {
@ -77,7 +76,7 @@ export class SliderElement extends LabelledElement {
elementValue.innerHTML = this._value.toFixed(this._decimals);
}
public getValue() {
protected getValue() {
return this._value;
}

View File

@ -4,7 +4,8 @@ import { ComboBoxElement } from './elements/combobox';
import { FileInputElement } from './elements/file_input';
import { ButtonElement } from './elements/button';
import { OutputElement } from './elements/output';
import { Action, ActionReturnType, AppContext } from '../app_context';
import { Action, AppContext } from '../app_context';
import { LOG } from '../util';
export interface Group {
label: string;
@ -13,6 +14,7 @@ export interface Group {
submitButton: ButtonElement;
output: OutputElement;
}
export class UI {
public uiOrder = ['import', 'simplify', 'build', 'palette', 'export'];
private _ui = {
@ -138,6 +140,15 @@ export class UI {
` + itemHTML + `</div></div>`;
}
public cacheValues(action: Action) {
const group = this._getActionGroup(action);
for (const elementName of group.elementsOrder) {
LOG(`Caching ${elementName}`);
const element = group.elements[elementName];
element.cacheValue();
}
}
private _buildGroup(group: Group) {
let groupHTML = '';
for (const elementName of group.elementsOrder) {
@ -212,4 +223,9 @@ export class UI {
group.output.clearMessage();
}
}
private _getActionGroup(action: Action): Group {
const key = this.uiOrder[action];
return this._uiDull[key];
}
}

View File

@ -7,6 +7,7 @@ import { OcclusionManager } from './occlusion';
import { Axes, generateRays, rayIntersectTriangle } from './ray';
import { Texture, TextureFiltering } from './texture';
import { Triangle, UVTriangle } from './triangle';
import { UI } from './ui/layout';
import { Bounds, LOG, RGB, UV } from './util';
import { Vector3 } from './vector';
@ -23,9 +24,10 @@ export class VoxelMesh {
private _loadedTextures: { [materialName: string]: Texture };
private _bounds: Bounds;
public constructor(desiredHeight: number) {
public constructor() {
LOG('New voxel mesh');
const desiredHeight = UI.Get.layout.build.elements.height.getCachedValue() as number;
this._voxelSize = 8.0 / Math.round(desiredHeight);
this._voxels = [];
this._voxelsHash = new HashMap(2048);
@ -41,7 +43,7 @@ export class VoxelMesh {
return this._voxelsHash.has(pos);
}
public voxelise(mesh: Mesh, multisampleColouring: boolean, filtering: TextureFiltering) {
public voxelise(mesh: Mesh) {
LOG('Voxelising');
mesh.tris.forEach((tri, index) => {
@ -52,11 +54,11 @@ export class VoxelMesh {
}
}
const uvTriangle = mesh.getUVTriangle(index);
this._voxeliseTri(uvTriangle, material, tri.material, multisampleColouring, filtering);
this._voxeliseTri(uvTriangle, material, tri.material);
});
}
private _voxeliseTri(triangle: UVTriangle, material: (SolidMaterial | TexturedMaterial), materialName: string, multisampleColouring: boolean, filtering: TextureFiltering) {
private _voxeliseTri(triangle: UVTriangle, material: (SolidMaterial | TexturedMaterial), materialName: string) {
const v0Scaled = Vector3.divScalar(triangle.v0, this._voxelSize);
const v1Scaled = Vector3.divScalar(triangle.v1, this._voxelSize);
const v2Scaled = Vector3.divScalar(triangle.v2, this._voxelSize);
@ -79,22 +81,23 @@ export class VoxelMesh {
}
let voxelColour: RGB;
if (multisampleColouring && material.type === MaterialType.textured) {
const useMultisampleColouring = UI.Get.layout.build.elements.multisampleColouring.getCachedValue() as string === 'on';
if (useMultisampleColouring && material.type === MaterialType.textured) {
const samples: RGB[] = [];
for (let i = 0; i < AppConfig.MULTISAMPLE_COUNT; ++i) {
const samplePosition = Vector3.mulScalar(Vector3.add(voxelPosition, Vector3.random().addScalar(-0.5)), this._voxelSize);
samples.push(this._getVoxelColour(triangle, material, materialName, samplePosition, filtering));
samples.push(this._getVoxelColour(triangle, material, materialName, samplePosition));
}
voxelColour = RGB.averageFrom(samples);
} else {
voxelColour = this._getVoxelColour(triangle, material, materialName, Vector3.mulScalar(voxelPosition, this._voxelSize), filtering);
voxelColour = this._getVoxelColour(triangle, material, materialName, Vector3.mulScalar(voxelPosition, this._voxelSize));
}
this._addVoxel(voxelPosition, voxelColour);
}
});
}
private _getVoxelColour(triangle: UVTriangle, material: (SolidMaterial | TexturedMaterial), materialName: string, location: Vector3, filtering: TextureFiltering): RGB {
private _getVoxelColour(triangle: UVTriangle, material: (SolidMaterial | TexturedMaterial), materialName: string, location: Vector3): RGB {
if (material.type == MaterialType.solid) {
return material.colour;
}
@ -112,7 +115,8 @@ export class VoxelMesh {
triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
);
const filtering = UI.Get.layout.build.elements.textureFiltering.getCachedValue() as string === 'linear' ? TextureFiltering.Linear : TextureFiltering.Nearest;
return this._loadedTextures[materialName].getRGB(uv, filtering);
}
@ -147,7 +151,7 @@ export class VoxelMesh {
// //////////////////////////////////////////////////////////////////////////
public createBuffer(ambientOcclusionEnabled: boolean) {
public createBuffer() {
const buffer = new RenderBuffer([
{ name: 'position', numComponents: 3 },
{ name: 'colour', numComponents: 3 },
@ -156,6 +160,7 @@ export class VoxelMesh {
{ name: 'normal', numComponents: 3 },
]);
const ambientOcclusionEnabled = UI.Get.layout.build.elements.ambientOcclusion.getCachedValue() as string === 'on';
for (const voxel of this._voxels) {
// Each vertex of a face needs the occlusion data for the other 3 vertices
// in it's face, not just itself. Also flatten occlusion data.