From 6f66e4f131d0d33e6eaafe8b9c5457415221e5bd Mon Sep 17 00:00:00 2001 From: Paul Mathieu Date: Wed, 22 Dec 2021 02:32:08 -0800 Subject: [PATCH] Faster loading & geometry fixes --- game.js | 4 ++-- world.js | 71 +++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/game.js b/game.js index 6e542df..f2cca35 100644 --- a/game.js +++ b/game.js @@ -341,9 +341,9 @@ export function tick(time, gl, params) { // expensive stuff, can take several cycles try { // frame time is typically 16.7ms, so this may lag a bit - let timeLeft = 30; + let timeLeft = 10; const start = performance.now(); - generateMissingChunks(params.world, campos[2], campos[0], 5); + generateMissingChunks(params.world, campos[2], campos[0], timeLeft); timeLeft -= performance.now() - start; updateWorldGeometry(gl, params.world, campos[2], campos[0], timeLeft); diff --git a/world.js b/world.js index 0910889..f238c7c 100644 --- a/world.js +++ b/world.js @@ -250,26 +250,28 @@ export function generateMissingChunks(world, z, x, timeLimit = 10000) { const start = performance.now(); - for (let i = ic - 8; i < ic + 8; i++) { - for (let j = jc - 8; j < jc + 8; j++) { - if (world.chunkMap.has(i, j)) { - continue; - } - const chunk = makeChunk(i * 16, j * 16); - world.chunks.push(chunk); - world.chunkMap.set(i, j, chunk); + for (let radius = 1; radius < 8; radius++) { - invalidateChunkGeometry(world, i - 1, j); - invalidateChunkGeometry(world, i + 1, j); - invalidateChunkGeometry(world, i, j - 1); - invalidateChunkGeometry(world, i, j + 1); + for (let i = ic - radius; i < ic + radius; i++) { + for (let j = jc - radius; j < jc + radius; j++) { + if (world.chunkMap.has(i, j)) { + continue; + } + const chunk = makeChunk(i * 16, j * 16); + world.chunks.push(chunk); + world.chunkMap.set(i, j, chunk); - if (performance.now() - start > timeLimit) { - throw 'timesup'; + invalidateChunkGeometry(world, i - 1, j); + invalidateChunkGeometry(world, i + 1, j); + invalidateChunkGeometry(world, i, j - 1); + invalidateChunkGeometry(world, i, j + 1); + + if (radius > 2 && performance.now() - start > timeLimit) { + return; + } } } } - return world; } @@ -278,6 +280,10 @@ function invalidateChunkGeometry(world, i, j) { if (chunk === undefined) { return; } + if (chunk.faces === undefined) { + return; + } + delete chunk.faces; if (chunk.buffer === undefined) { return; } @@ -285,7 +291,21 @@ function invalidateChunkGeometry(world, i, j) { delete chunk.buffer; } -export function createChunkFace(block, dir) { +function addFace(chunk, block, dir) { + if (block.type === BlockType.WATER) { + const face = createChunkFace(block, dir); + if (dir === '+y') { + face[1] -= 0.15; + } + chunk.transparentFaces.push(face); + + } else { + chunk.faces.push(createChunkFace(block, dir)); + } +} + +export function createChunkFace(block, dir, center = null) { + center = center ?? faceCenter(block.centerPosition, dir); return { dir, blockIndex: block.blockIndex, @@ -306,7 +326,7 @@ export function updateWorldGeometry(gl, world, z, x, timeLimit = 10000) { for (let j = jc - radius; j < jc + radius; j++) { const chunk = world.chunkMap.get(i, j); - if (chunk.buffer !== undefined) { + if (chunk === undefined || chunk.buffer !== undefined) { continue; } @@ -324,8 +344,8 @@ export function updateWorldGeometry(gl, world, z, x, timeLimit = 10000) { chunk.transparentBuffer = makeBufferFromFaces(gl, chunk.transparentFaces.map(f => f.face)); // throttle this for fluidity - if (performance.now() - start > timeLimit) { - throw 'timesup'; + if (radius > 2 && performance.now() - start > timeLimit) { + return; } } } @@ -491,7 +511,9 @@ export function destroyBlock(world, block) { .filter(({ block }) => block.type !== BlockType.AIR && block.type !== BlockType.UNDEFINED) .forEach(({ block, dir }) => { - block.chunk.faces.push(createChunkFace(block, dir)); + // TODO: don't add transparent faces twice + // since we "forget" to trim them + addFace(block.chunk, block, dir); trimFaces(block.chunk); if (block.chunk.buffer !== undefined) { @@ -529,15 +551,16 @@ export function makeBlock(world, position, type) { neighbors .filter(({ block }) => block.type !== BlockType.UNDEFINED) .forEach(({ block: nblock, dir, ndir }) => { - if (nblock.type === BlockType.AIR) { - block.chunk.faces.push(createChunkFace(block, dir)); - } else { + if (nblock.type === BlockType.AIR || + nblock.type === BlockType.WATER) { + addFace(block.chunk, block, dir); + }// else { nblock.chunk.faces = nblock.chunk.faces.filter(f => ( f.blockIndex !== nblock.blockIndex || f.dir !== ndir )); refresh(nblock.chunk); - } + //} }); refresh(block.chunk);