Added debug stats to lighting calculations

This commit is contained in:
Lucas Dower 2022-11-13 22:20:34 +00:00
parent 169ad57257
commit c00673339b
No known key found for this signature in database
GPG Key ID: B3EE6B8499593605
2 changed files with 66 additions and 21 deletions

View File

@ -48,9 +48,11 @@ export class BlockMesh {
blockMesh._assignBlocks(blockMeshParams);
//blockMesh._calculateLighting(blockMeshParams.lightThreshold);
blockMesh._lighting.init();
blockMesh._lighting.addSunLightValues();
blockMesh._lighting.addEmissiveBlocks();
blockMesh._lighting.addLightToDarkness(blockMeshParams.lightThreshold);
blockMesh._lighting.dumpInfo();
return blockMesh;
}

View File

@ -1,5 +1,6 @@
import { BlockMesh } from './block_mesh';
import { ASSERT } from './util/error_util';
import { LOG } from './util/log_util';
import { Vector3Hash } from './util/type_util';
import { Vector3 } from './vector';
@ -9,13 +10,20 @@ export type TLightUpdate = TLightLevel & { pos: Vector3 };
export class BlockMeshLighting {
private _owner: BlockMesh;
private _limits: Map<number, { x: number, z: number, minY: number, maxY: number }>;
private _sunLightValues: Map<Vector3Hash, number>;
private _blockLightValues: Map<Vector3Hash, number>;
private _updates: number;
private _skips: number;
public constructor(owner: BlockMesh) {
this._owner = owner;
this._sunLightValues = new Map();
this._blockLightValues = new Map();
this._limits = new Map();
this._updates = 0;
this._skips = 0;
}
public getLightLevel(vec: Vector3): TLightLevel {
@ -73,22 +81,46 @@ export class BlockMeshLighting {
}
}
public addSunLightValues() {
// Calculate the highest block in each column.
const plane = new Map<number, { x: number, z: number }>();
private _calculateLimits() {
this._limits.clear();
const updateLimit = (pos: Vector3) => {
const key = pos.copy();
key.y = 0;
const blockLimit = this._limits.get(key.hash());
if (blockLimit !== undefined) {
blockLimit.maxY = Math.max(blockLimit.maxY, pos.y);
blockLimit.minY = Math.min(blockLimit.minY, pos.y);
} else {
this._limits.set(key.hash(), {
x: pos.x,
z: pos.z,
minY: pos.y,
maxY: pos.y,
});
}
};
this._owner.getBlocks().forEach((block) => {
const pos = block.voxel.position.copy();
pos.y = 0;
plane.set(pos.hash(), pos);
updateLimit(block.voxel.position);
updateLimit(new Vector3(1, 0, 0).add(block.voxel.position));
updateLimit(new Vector3(-1, 0, 0).add(block.voxel.position));
updateLimit(new Vector3(0, 0, 1).add(block.voxel.position));
updateLimit(new Vector3(0, 0, -1).add(block.voxel.position));
});
}
const maxHeight = this._owner.getVoxelMesh().getBounds().max.y;
public init() {
this._calculateLimits();
}
public addSunLightValues() {
// Actually commit the light level changes.
const updates: TLightUpdate[] = [];
plane.forEach((value, key) => {
this._limits.forEach((limit, key) => {
updates.push({
pos: new Vector3(value.x, maxHeight, value.z),
pos: new Vector3(0, 1, 0).add(new Vector3(limit.x, limit.maxY, limit.z)),
sunLightValue: 15,
blockLightValue: 0,
});
@ -120,19 +152,19 @@ export class BlockMeshLighting {
*/
private _handleUpdates(updates: TLightUpdate[]) {
while (updates.length > 0) {
this._updates += 1;
const update = updates.pop()!;
// Only update light values inside the bounds of the block mesh.
// Values outside the bounds are assumed to have sunLightValue of 15
// and blockLightValue of 0.
if (!this._isPosValid(update.pos)) {
this._skips += 1;
continue;
}
const current = this.getLightLevel(update.pos);
const toSet: TLightLevel = { sunLightValue: current.sunLightValue, blockLightValue: current.blockLightValue };
const blockHere = this._owner.getBlockAt(update.pos);
const isBlockHere = blockHere !== undefined;
const hash = update.pos.hash();
// Update sunLight value
@ -147,6 +179,9 @@ export class BlockMeshLighting {
this._blockLightValues.set(hash, toSet.blockLightValue);
}
const blockHere = this._owner.getBlockAt(update.pos);
const isBlockHere = blockHere !== undefined;
const shouldPropagate = isBlockHere ?
this._owner.isTransparentBlock(blockHere) :
true;
@ -161,11 +196,11 @@ export class BlockMeshLighting {
sunLightValue: toSet.sunLightValue - 1,
blockLightValue: toSet.blockLightValue - 1,
};
updates.push({ pos: new Vector3(0, 1, 0).add(update.pos), ...attenuated });
updates.push({ pos: new Vector3(1, 0, 0).add(update.pos), ...attenuated });
updates.push({ pos: new Vector3(0, 0, 1).add(update.pos), ...attenuated });
updates.push({ pos: new Vector3(-1, 0, 0).add(update.pos), ...attenuated });
updates.push({ pos: new Vector3(0, 0, -1).add(update.pos), ...attenuated });
updates.push({ pos: new Vector3(0, 1, 0).add(update.pos), sunLightValue: attenuated.sunLightValue, blockLightValue: attenuated.blockLightValue });
updates.push({ pos: new Vector3(1, 0, 0).add(update.pos), sunLightValue: attenuated.sunLightValue, blockLightValue: attenuated.blockLightValue });
updates.push({ pos: new Vector3(0, 0, 1).add(update.pos), sunLightValue: attenuated.sunLightValue, blockLightValue: attenuated.blockLightValue });
updates.push({ pos: new Vector3(-1, 0, 0).add(update.pos), sunLightValue: attenuated.sunLightValue, blockLightValue: attenuated.blockLightValue });
updates.push({ pos: new Vector3(0, 0, -1).add(update.pos), sunLightValue: attenuated.sunLightValue, blockLightValue: attenuated.blockLightValue });
updates.push({ pos: new Vector3(0, -1, 0).add(update.pos), sunLightValue: toSet.sunLightValue === 15 ? 15 : toSet.sunLightValue - 1, blockLightValue: toSet.blockLightValue - 1 });
}
}
@ -173,10 +208,18 @@ export class BlockMeshLighting {
}
private _isPosValid(vec: Vector3) {
const blocksBounds = this._owner.getVoxelMesh().getBounds(); // TODO: Cache
const xValid = blocksBounds.min.x - 1 <= vec.x && vec.x <= blocksBounds.max.x + 1;
const yValid = blocksBounds.min.y - 1 <= vec.y && vec.y <= blocksBounds.max.y + 1;
const zValid = blocksBounds.min.z - 1 <= vec.z && vec.z <= blocksBounds.max.z + 1;
return xValid && yValid && zValid;
const key = vec.copy();
key.y = 0;
const limit = this._limits.get(key.hash());
if (limit !== undefined) {
return vec.y >= limit.minY - 1 && vec.y <= limit.maxY + 1;
} else {
return false;
}
}
public dumpInfo() {
LOG(`Skipped ${this._skips} out of ${this._updates} (${(100 * this._skips / this._updates).toFixed(4)}%)`);
}
}