Report renderer progress and detect stalled jobs
This commit is contained in:
@@ -162,9 +162,28 @@ window.buildTerrain = async (snapshot) => {
|
||||
unsupported = new Set();
|
||||
const occupancy = new Map();
|
||||
const distinctStates = new Set();
|
||||
for (const b of snapshot.blocks) {
|
||||
let lastProgress = 0;
|
||||
async function progress(percent, message, force = false) {
|
||||
if (!force && performance.now() - lastProgress < 3000) return;
|
||||
lastProgress = performance.now();
|
||||
// Yield to browser tasks so bindings, cancellation and timers can run.
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
await window.minegeoProgress?.({ percent, message });
|
||||
}
|
||||
await progress(
|
||||
25,
|
||||
`Indexing ${snapshot.blocks.length.toLocaleString()} terrain blocks`,
|
||||
true,
|
||||
);
|
||||
for (let i = 0; i < snapshot.blocks.length; i++) {
|
||||
const b = snapshot.blocks[i];
|
||||
occupancy.set(`${b[0]},${b[1]},${b[2]}`, b[3]);
|
||||
distinctStates.add(b[3]);
|
||||
if (i % 16384 === 0)
|
||||
await progress(
|
||||
25 + (5 * i) / snapshot.blocks.length,
|
||||
`Indexing blocks ${i}/${snapshot.blocks.length}`,
|
||||
);
|
||||
}
|
||||
const stateCache = new Map();
|
||||
async function stateModels(s) {
|
||||
@@ -182,8 +201,15 @@ window.buildTerrain = async (snapshot) => {
|
||||
return variants;
|
||||
}
|
||||
// Preload each distinct model once before constructing batched geometry.
|
||||
for (const s of distinctStates)
|
||||
await progress(30, "Loading block models and textures", true);
|
||||
let modelCount = 0;
|
||||
for (const s of distinctStates) {
|
||||
await stateModels(s);
|
||||
await progress(
|
||||
30 + (5 * ++modelCount) / distinctStates.size,
|
||||
`Loading block model ${modelCount}/${distinctStates.size}`,
|
||||
);
|
||||
}
|
||||
async function emit(block, m, v = {}) {
|
||||
const [bx, by, bz, s] = block;
|
||||
for (const e of m.elements || []) {
|
||||
@@ -284,7 +310,14 @@ window.buildTerrain = async (snapshot) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const b of snapshot.blocks) {
|
||||
await progress(35, "Building terrain geometry", true);
|
||||
for (let i = 0; i < snapshot.blocks.length; i++) {
|
||||
const b = snapshot.blocks[i];
|
||||
if (i % 256 === 0)
|
||||
await progress(
|
||||
35 + (20 * i) / snapshot.blocks.length,
|
||||
`Building blocks ${i}/${snapshot.blocks.length}`,
|
||||
);
|
||||
if (/minecraft:(water|lava)(\[|$)/.test(b[3])) {
|
||||
await emit(b, {
|
||||
textures: {
|
||||
@@ -314,6 +347,8 @@ window.buildTerrain = async (snapshot) => {
|
||||
for (const { m, v } of await stateModels(b[3])) await emit(b, m, v);
|
||||
}
|
||||
occupancy.clear();
|
||||
await progress(55, "Preparing the scene", true);
|
||||
let batchCount = 0;
|
||||
for (const batch of batches.values()) {
|
||||
const g = new THREE.BufferGeometry();
|
||||
g.setAttribute(
|
||||
@@ -340,6 +375,10 @@ window.buildTerrain = async (snapshot) => {
|
||||
batch.normals.length = 0;
|
||||
batch.uvs.length = 0;
|
||||
batch.indices.length = 0;
|
||||
await progress(
|
||||
55 + (5 * ++batchCount) / batches.size,
|
||||
`Preparing geometry ${batchCount}/${batches.size}`,
|
||||
);
|
||||
}
|
||||
window.terrainBounds = snapshot.bounds;
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user