diff --git a/index.js b/index.js index fe2e14f..47889ac 100644 --- a/index.js +++ b/index.js @@ -367,10 +367,63 @@ function castRay(world, origin, direction, maxDistance) { } } +function viewDirection(params) { + const dir = [0, 0, -1, 1.0]; + const camori = params.camera.orientation; + const ori = se3.inverse(se3.rotxyz(-camori[0], -camori[1], -camori[2])); + return se3.apply(ori, dir).slice(0, 3); +} + +function destroySelectedBlock(params) { + const hit = castRay(params.world, params.camera.position, viewDirection(params), params.blockSelectDistance); + if (hit === undefined || hit.block.type === BlockType.UNDEFINED) { + return; + } + + const trimFaces = chunk => { + chunk.faces = chunk.faces.filter(({blockIndex}) => chunk.data[blockIndex] !== BlockType.AIR); + } + + hit.block.chunk.data[hit.block.blockIndex] = BlockType.AIR; + if (hit.block.chunk.buffer !== undefined) { + hit.block.chunk.buffer.delete(); + delete hit.block.chunk.buffer; + } + trimFaces(hit.block.chunk); + + const [bx, by, bz] = hit.block.centerPosition; + + const neighbors = [ + { block: blockLookup(params.world, bx - 1, by, bz), dir: '+x' }, + { block: blockLookup(params.world, bx + 1, by, bz), dir: '-x' }, + { block: blockLookup(params.world, bx, by - 1, bz), dir: '+y' }, + { block: blockLookup(params.world, bx, by + 1, bz), dir: '-y' }, + { block: blockLookup(params.world, bx, by, bz - 1), dir: '+z' }, + { block: blockLookup(params.world, bx, by, bz + 1), dir: '-z' }, + ]; + + neighbors + .filter(({ block }) => block.type !== BlockType.AIR && + block.type !== BlockType.UNDEFINED) + .forEach(({ block, dir }) => { + const blocki = Math.floor(block.blockIndex / (16 * 256)); + const blockj = Math.floor(block.blockIndex / 256) - 16 * blocki; + const blockk = block.blockIndex % 256; + + block.chunk.faces.push(createChunkFace(block, dir)); + trimFaces(block.chunk); + + if (block.chunk.buffer !== undefined) { + block.chunk.buffer.delete(); + delete block.chunk.buffer; + } + }); +} + function markBlock(world, cameraPosition, direction, maxDistance) { const hit = castRay(world, cameraPosition, direction, maxDistance); - if (hit === undefined) { + if (hit === undefined || hit.block.type === BlockType.UNDEFINED) { return; } diff --git a/world.js b/world.js index 9bc25f2..c405c1e 100644 --- a/world.js +++ b/world.js @@ -1,6 +1,7 @@ import { makeBufferFromFaces, makeFace} from "./geometry"; export const BlockType = { + UNDEFINED: 0, AIR: 1, DIRT: 2, GRASS: 3, @@ -87,6 +88,11 @@ function makeChunk(z, x) { } export function blockLookup(world, x, y, z) { + if (y < 0.5 || z > 255.5) { + return { + type: BlockType.UNDEFINED, + } + } const midx = x + 0.5; const midy = y + 0.5; const midz = z + 0.5; @@ -97,8 +103,7 @@ export function blockLookup(world, x, y, z) { const chunk = world.chunkMap.get(chunki, chunkj); if (chunk === undefined) { return { - type: BlockType.STONE, - centerPosition: [x, y, z], + type: BlockType.UNDEFINED, }; } @@ -121,6 +126,9 @@ function makeChunkBuffer(gl, data, z0, x0, blockLookup) { if (i < 0 || j < 0 || i > 15 || j > 15) { return blockLookup(i, j, k); } + if (k < 0 || k > 255) { + return BlockType.UNDEFINED; + } return data[256*(16*i + j) + k]; }; const sideNeighbors = (i, j, k) =>