Tidied how progress is announced

This commit is contained in:
Lucas Dower 2022-09-17 15:15:34 +01:00
parent b495aa73a3
commit f8f57ba0b8
6 changed files with 76 additions and 71 deletions

View File

@ -67,15 +67,10 @@ export class BlockMesh {
const blockAssigner = BlockAssignerFactory.GetAssigner(blockMeshParams.blockAssigner);
let countFalling = 0;
let nextPercentage = 0.0;
ProgressManager.Get.start('Assigning');
const taskHandle = ProgressManager.Get.start('Assigning');
const voxels = this._voxelMesh.getVoxels();
for (let voxelIndex = 0; voxelIndex < voxels.length; ++voxelIndex) {
const percentage = voxelIndex / voxels.length;
if (voxelIndex / voxels.length >= nextPercentage) {
ProgressManager.Get.progress('Assigning', percentage);
nextPercentage += 0.05;
}
ProgressManager.Get.progress(taskHandle, voxelIndex / voxels.length);
const voxel = voxels[voxelIndex];
let block = blockAssigner.assignBlock(atlasPalette, voxel.colour, voxel.position, blockMeshParams.colourSpace);
@ -104,7 +99,7 @@ export class BlockMesh {
this._blocksUsed.push(block.name);
}
}
ProgressManager.Get.end('Assigning');
ProgressManager.Get.end(taskHandle);
if (blockMeshParams.fallable === 'do-nothing' && countFalling > 0) {
StatusHandler.Get.add('warning', `${countFalling.toLocaleString()} blocks will fall under gravity when this structure is placed`);

View File

@ -71,8 +71,7 @@ export class BufferGenerator {
const materialBuffers: TMeshBufferDescription[] = [];
let trianglesHandled = 0;
let nextPercentage = 0;
ProgressManager.Get.start('MeshBuffer');
const taskHandle = ProgressManager.Get.start('MeshBuffer');
// Create the buffers for each material and fill with data from the triangles
materialTriangleCount.forEach((triangleCount: number, materialName: string) => {
@ -80,11 +79,7 @@ export class BufferGenerator {
let insertIndex = 0;
for (let triIndex = 0; triIndex < numTris; ++triIndex) {
const percentage = trianglesHandled / numTris;
if (percentage >= nextPercentage) {
ProgressManager.Get.progress('MeshBuffer', percentage);
nextPercentage += 0.05;
}
ProgressManager.Get.progress(taskHandle, trianglesHandled / numTris);
const material = mesh.getMaterialByTriangle(triIndex);
if (material === materialName) {
@ -135,7 +130,7 @@ export class BufferGenerator {
});
});
ProgressManager.Get.end('MeshBuffer');
ProgressManager.Get.end(taskHandle);
return materialBuffers;
}
@ -147,14 +142,9 @@ export class BufferGenerator {
const cube: AttributeData = GeometryTemplates.getBoxBufferData(new Vector3(0, 0, 0));
const voxels = voxelMesh.getVoxels();
let nextPercentage = 0.0;
ProgressManager.Get.start('VoxelMeshBuffer');
const taskHandle = ProgressManager.Get.start('VoxelMeshBuffer');
for (let i = 0; i < numVoxels; ++i) {
const percentage = i / numVoxels;
if (i / numVoxels >= nextPercentage) {
ProgressManager.Get.progress('VoxelMeshBuffer', percentage);
nextPercentage += 0.05;
}
ProgressManager.Get.progress(taskHandle, i / numVoxels);
const voxel = voxels[i];
const voxelColourArray = [voxel.colour.r, voxel.colour.g, voxel.colour.b, voxel.colour.a];
@ -187,7 +177,7 @@ export class BufferGenerator {
}
}
}
ProgressManager.Get.end('VoxelMeshBuffer');
ProgressManager.Get.end(taskHandle);
return {
buffer: newBuffer,
@ -204,14 +194,9 @@ export class BufferGenerator {
const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
let insertIndex = 0;
let nextPercentage = 0.0;
ProgressManager.Get.start('BlockMeshBuffer');
const taskHandle = ProgressManager.Get.start('BlockMeshBuffer');
for (let i = 0; i < numBlocks; ++i) {
const percentage = i / numBlocks;
if (i / numBlocks >= nextPercentage) {
ProgressManager.Get.progress('BlockMeshBuffer', percentage);
nextPercentage += 0.05;
}
ProgressManager.Get.progress(taskHandle, i / numBlocks);
for (let f = 0; f < AppConstants.FACES_PER_VOXEL; ++f) {
const faceName = faceOrder[f];
@ -222,7 +207,7 @@ export class BufferGenerator {
}
}
}
ProgressManager.Get.end('BlockMeshBuffer');
ProgressManager.Get.end(taskHandle);
return {
buffer: newBuffer,

View File

@ -1,6 +1,19 @@
import { EAppEvent, EventManager } from './event';
import { ASSERT } from './util/error_util';
export type TTaskID =
| 'Importing'
| 'MeshBuffer'
| 'Voxelising'
| 'VoxelMeshBuffer'
| 'Assigning'
| 'BlockMeshBuffer'
| 'Exporting';
export type TTaskHandle = {
nextPercentage: number,
id: TTaskID,
}
export class ProgressManager {
/* Singleton */
@ -9,7 +22,7 @@ export class ProgressManager {
return this._instance || (this._instance = new this());
}
private _tasks: string[];
private _tasks: TTaskID[];
private constructor() {
this._tasks = [];
@ -18,35 +31,38 @@ export class ProgressManager {
/**
* Start tracking the progress of a task.
* @param taskId The id of the task (created here).
* @param max The maximum number the task progress index can reach.
* For example, if you are iterating over an array of 1000 elements, this will be 1000.
* @param divisions The number of updates the manager should track.
* For example, 4 means an event will be emitted for 20%, 40%, 60%, 80% progress.
*/
public start(taskId: string) {
public start(taskId: TTaskID): TTaskHandle {
ASSERT(!this._tasks.includes(taskId), 'Task with that Id already being tracked');
this._tasks.push(taskId);
EventManager.Get.broadcast(EAppEvent.onTaskStart, taskId);
return {
nextPercentage: 0.0,
id: taskId,
};
}
/**
* Announce progress has been made on a task.
* @param taskId The id of the task (created in `start`).
* @param progressIndex The index of the progress made so far.
* For example, if you are iteratinve over an array of 1000 elements, and are on index 230, this should be 230.
* @param percentage A number between 0.0 and 1.0, inclusive.
*/
public progress(taskId: string, percentage: number) {
EventManager.Get.broadcast(EAppEvent.onTaskProgress, taskId, percentage);
public progress(tracker: TTaskHandle, percentage: number) {
if (percentage > tracker.nextPercentage) {
EventManager.Get.broadcast(EAppEvent.onTaskProgress, tracker.id, percentage);
tracker.nextPercentage += 0.05;
}
}
/**
* Announce a task has completed.
* @param taskId The id of the task (created in `start`).
*/
public end(taskId: string) {
const taskIndex = this._tasks.findIndex((task) => { return task === taskId });
public end(tracker: TTaskHandle) {
const taskIndex = this._tasks.findIndex((task) => { return task === tracker.id; });
ASSERT(taskIndex !== -1, 'Task with that Id is not being tracked');
this._tasks.splice(taskIndex, 1);
EventManager.Get.broadcast(EAppEvent.onTaskEnd, taskId);
EventManager.Get.broadcast(EAppEvent.onTaskEnd, tracker.id);
}
}

View File

@ -78,14 +78,9 @@ export class BVHRayVoxeliser extends IVoxeliser {
LOG('Rays created...');
// Ray test BVH
let nextPercentage = 0.0;
ProgressManager.Get.start('Voxelising');
const taskHandle = ProgressManager.Get.start('Voxelising');
for (rayIndex = 0; rayIndex < rays.length; ++rayIndex) {
const percentage = rayIndex / rays.length;
if (rayIndex / rays.length >= nextPercentage) {
ProgressManager.Get.progress('Voxelising', percentage);
nextPercentage += 0.05;
}
ProgressManager.Get.progress(taskHandle, rayIndex / rays.length);
const ray = rays[rayIndex];
const intersections = bvh.intersectRay(ray.origin, axesToDirection(ray.axis), false);
@ -107,7 +102,7 @@ export class BVHRayVoxeliser extends IVoxeliser {
}
}
}
ProgressManager.Get.end('Voxelising');
ProgressManager.Get.end(taskHandle);
return voxelMesh;
}

View File

@ -2,6 +2,7 @@ import { Bounds } from '../bounds';
import { RGBA, RGBAUtil } from '../colour';
import { AppConfig } from '../config';
import { Mesh } from '../mesh';
import { ProgressManager } from '../progress';
import { Axes, Ray, rayIntersectTriangle } from '../ray';
import { Triangle, UVTriangle } from '../triangle';
import { UV } from '../util';
@ -33,36 +34,42 @@ export class NormalCorrectedRayVoxeliser extends IVoxeliser {
useMesh.scaleMesh(this._scale);
const bounds = useMesh.getBounds();
this._size = Vector3.sub(bounds.max, bounds.min);
this._offset =new Vector3(
this._offset = new Vector3(
this._size.x % 2 < 0.001 ? 0.5 : 0.0,
this._size.y % 2 < 0.001 ? 0.5 : 0.0,
this._size.z % 2 < 0.001 ? 0.5 : 0.0,
);
for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
const numTris = useMesh.getTriangleCount();
const taskHandle = ProgressManager.Get.start('Voxelising');
for (let triIndex = 0; triIndex < numTris; ++triIndex) {
ProgressManager.Get.progress(taskHandle, triIndex / numTris);
const uvTriangle = useMesh.getUVTriangle(triIndex);
const normals = useMesh.getNormals(triIndex);
const material = useMesh.getMaterialByTriangle(triIndex);
this._voxeliseTri(uvTriangle, material, normals);
}
ProgressManager.Get.end(taskHandle);
return this._voxelMesh;
}
private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3}) {
private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3 }) {
const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2,
this._offset,
);
rayList.forEach((ray) => {
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
if (intersection) {
if (intersection) {
// Move transition away from normal
const norm = normals.v0.normalise();
intersection.sub(Vector3.mulScalar(norm, 0.5));
// Correct size parity
intersection.add(this._offset);
let voxelPosition: Vector3;
switch (ray.axis) {
case Axes.x:
@ -109,7 +116,7 @@ export class NormalCorrectedRayVoxeliser extends IVoxeliser {
triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
);
return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
}
@ -126,14 +133,14 @@ export class NormalCorrectedRayVoxeliser extends IVoxeliser {
Math.floor(Math.max(v0.z, v1.z, v2.z)),
),
);
const rayList: Array<Ray> = [];
this._traverseX(rayList, bounds, offset);
this._traverseY(rayList, bounds, offset);
this._traverseZ(rayList, bounds, offset);
return rayList;
}
private _traverseX(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
@ -144,7 +151,7 @@ export class NormalCorrectedRayVoxeliser extends IVoxeliser {
}
}
}
private _traverseY(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
@ -155,7 +162,7 @@ export class NormalCorrectedRayVoxeliser extends IVoxeliser {
}
}
}
private _traverseZ(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {

View File

@ -2,6 +2,7 @@ import { Bounds } from '../bounds';
import { RGBA, RGBAUtil } from '../colour';
import { AppConfig } from '../config';
import { Mesh } from '../mesh';
import { ProgressManager } from '../progress';
import { Axes, Ray, rayIntersectTriangle } from '../ray';
import { Triangle, UVTriangle } from '../triangle';
import { UV } from '../util';
@ -33,18 +34,24 @@ export class RayVoxeliser extends IVoxeliser {
useMesh.scaleMesh(this._scale);
useMesh.translateMesh(this._offset);
for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
const numTris = useMesh.getTriangleCount();
const taskHandle = ProgressManager.Get.start('Voxelising');
for (let triIndex = 0; triIndex < numTris; ++triIndex) {
ProgressManager.Get.progress(taskHandle, triIndex / numTris);
const uvTriangle = useMesh.getUVTriangle(triIndex);
const material = useMesh.getMaterialByTriangle(triIndex);
this._voxeliseTri(uvTriangle, material);
}
ProgressManager.Get.end(taskHandle);
return this._voxelMesh;
}
private _voxeliseTri(triangle: UVTriangle, materialName: string) {
const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2);
rayList.forEach((ray) => {
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
if (intersection) {
@ -93,7 +100,7 @@ export class RayVoxeliser extends IVoxeliser {
triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
);
return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
}
@ -110,14 +117,14 @@ export class RayVoxeliser extends IVoxeliser {
Math.ceil(Math.max(v0.z, v1.z, v2.z)),
),
);
const rayList: Array<Ray> = [];
this._traverseX(rayList, bounds);
this._traverseY(rayList, bounds);
this._traverseZ(rayList, bounds);
return rayList;
}
private _traverseX(rayList: Array<Ray>, bounds: Bounds) {
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
@ -128,7 +135,7 @@ export class RayVoxeliser extends IVoxeliser {
}
}
}
private _traverseY(rayList: Array<Ray>, bounds: Bounds) {
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
@ -139,7 +146,7 @@ export class RayVoxeliser extends IVoxeliser {
}
}
}
private _traverseZ(rayList: Array<Ray>, bounds: Bounds) {
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {