Reverted to hashed voxel keys, ~1.4x faster voxelising

This commit is contained in:
Lucas Dower 2022-10-26 23:38:46 +01:00
parent 872eb9bf9a
commit 05a756a3b7
No known key found for this signature in database
GPG Key ID: B3EE6B8499593605
8 changed files with 24 additions and 29 deletions

6
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "objtoschematic",
"version": "0.6.1",
"version": "0.7.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "objtoschematic",
"version": "0.6.0",
"version": "0.7.0",
"license": "BSD-3-Clause",
"dependencies": {
"bvh-tree": "^1.0.1",
@ -13978,4 +13978,4 @@
"dev": true
}
}
}
}

View File

@ -1,7 +1,7 @@
{
"name": "objtoschematic",
"private": true,
"version": "0.6.1",
"version": "0.7.0",
"description": "A tool to convert .obj files into voxels and then into Minecraft Schematic files",
"main": "./dist/src/main.js",
"engines": {

View File

@ -4,7 +4,6 @@ import { BlockMesh } from '../block_mesh';
import { AppConstants } from '../constants';
import { StatusHandler } from '../status';
import { AppUtil } from '../util';
import { LOG } from '../util/log_util';
import { saveNBT } from '../util/nbt_util';
import { Vector3 } from '../vector';
import { IExporter } from './base_exporter';

View File

@ -29,7 +29,7 @@ export class OcclusionManager {
public getOcclusions(centre: Vector3, voxelMesh: VoxelMesh) {
// Cache local neighbours
const neighbourData = voxelMesh.getNeighbourhoodMap().get(centre.stringify());
const neighbourData = voxelMesh.getNeighbourhoodMap().get(centre.hash());
if (neighbourData === undefined) {
// This voxel has no neighbours within a 1-block radius
return this.getBlankOcclusions();
@ -60,7 +60,7 @@ export class OcclusionManager {
// Convert from occlusion denoting the occlusion factor to the
// attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4
occlusionValue = 1.0 - 0.2 * numNeighbours;
occlusionValue = 1.0 - 0.2 * numNeighbours;
const baseIndex = f * 16 + v;

View File

@ -237,10 +237,7 @@ export class Vector3 implements IHashable {
// Begin IHashable interface
public hash() {
const p0 = 73856093;
const p1 = 19349663;
const p2 = 83492791;
return (this.x * p0) ^ (this.y * p1) ^ (this.z * p2);
return ((this.x + 10_000_000) << 42) + ((this.y + 10_000_000) << 21) + (this.z + 10_000_000);
}
public equals(other: Vector3) {
@ -263,4 +260,4 @@ export const fastCrossYAxis = (vec: Vector3) => {
export const fastCrossZAxis = (vec: Vector3) => {
return new Vector3(-vec.y, vec.x, 0.0);
};
};

View File

@ -20,9 +20,9 @@ export type TVoxelMeshParams = Pick<VoxeliseParams.Input, 'voxelOverlapRule' | '
export class VoxelMesh {
private _voxels: (Voxel & { collisions: number })[];
private _voxelsHash: Map<string, number>;
private _voxelsHash: Map<number, number>;
private _bounds: Bounds;
private _neighbourMap: Map<string, { value: number }>;
private _neighbourMap: Map<number, { value: number }>;
private _voxelMeshParams: TVoxelMeshParams;
public constructor(voxelMeshParams: TVoxelMeshParams) {
@ -39,11 +39,11 @@ export class VoxelMesh {
}
public isVoxelAt(pos: Vector3) {
return this._voxelsHash.has(pos.stringify());
return this._voxelsHash.has(pos.hash());
}
public getVoxelAt(pos: Vector3): TOptional<Voxel> {
const voxelIndex = this._voxelsHash.get(pos.stringify());
const voxelIndex = this._voxelsHash.get(pos.hash());
if (voxelIndex !== undefined) {
const voxel = this._voxels[voxelIndex];
ASSERT(voxel !== undefined);
@ -58,7 +58,7 @@ export class VoxelMesh {
pos.round();
const voxelIndex = this._voxelsHash.get(pos.stringify());
const voxelIndex = this._voxelsHash.get(pos.hash());
if (voxelIndex !== undefined) {
// A voxel at this position already exists
const voxel = this._voxels[voxelIndex];
@ -74,7 +74,7 @@ export class VoxelMesh {
colour: colour,
collisions: 1,
});
this._voxelsHash.set(pos.stringify(), this._voxels.length - 1);
this._voxelsHash.set(pos.hash(), this._voxels.length - 1);
this._bounds.extendByPoint(pos);
this._updateNeighbours(pos);
}
@ -125,15 +125,14 @@ export class VoxelMesh {
}
}
private _stringified: string = '';
public getNeighbours(pos: Vector3) {
ASSERT(this._voxelMeshParams.enableAmbientOcclusion, 'Ambient occlusion is disabled');
this._stringified = pos.stringify();
const neighbours = this._neighbourMap.get(this._stringified);
const hash = pos.hash();
const neighbours = this._neighbourMap.get(hash);
if (neighbours === undefined) {
this._neighbourMap.set(this._stringified, { value: 0 });
return this._neighbourMap.get(this._stringified)!;
this._neighbourMap.set(hash, { value: 0 });
return this._neighbourMap.get(hash)!;
} else {
return neighbours;
}

View File

@ -106,10 +106,10 @@ export class BVHRayVoxeliserPlusThickness extends IVoxeliser {
);
if (voxelColour) {
voxelMesh.addVoxel(position, voxelColour);
if (!depthPosition.equals(position)) {
voxelMesh.addVoxel(depthPosition, voxelColour);
}
voxelMesh.addVoxel(position, voxelColour);
if (!depthPosition.equals(position)) {
voxelMesh.addVoxel(depthPosition, voxelColour);
}
}
}
}

View File

@ -1,7 +1,7 @@
import { ASSERT } from '../util/error_util';
import { IVoxeliser } from './base-voxeliser';
import { BVHRayVoxeliser } from './bvh-ray-voxeliser';
import { BVHRayVoxeliserPlusThickness } from './bvh-ray-voxeliser-plus-thickness'
import { BVHRayVoxeliserPlusThickness } from './bvh-ray-voxeliser-plus-thickness';
import { NormalCorrectedRayVoxeliser } from './normal-corrected-ray-voxeliser';
import { RayVoxeliser } from './ray-voxeliser';
@ -17,7 +17,7 @@ export class VoxeliserFactory {
case 'ray-based':
return new RayVoxeliser();
case 'bvh-ray-plus-thickness':
return new BVHRayVoxeliserPlusThickness()
return new BVHRayVoxeliserPlusThickness();
default:
ASSERT(false, 'Unreachable');
}