From 7607096e69dc4fde8c83ebb1bbe914d4adca50b1 Mon Sep 17 00:00:00 2001 From: Ian Trowbridge Date: Mon, 17 Apr 2023 21:47:01 -0500 Subject: [PATCH 1/6] Added select logic, highlighting, and adding removing blocks temporarily --- src/minecraft/App.ts | 60 ++++++++++++++++++++++++ src/minecraft/Chunk.ts | 98 ++++++++++++++++++++++++++++++++++++++++ src/minecraft/Gui.ts | 35 ++++++++++++-- src/minecraft/Shaders.ts | 43 ++++++++++++------ 4 files changed, 218 insertions(+), 18 deletions(-) diff --git a/src/minecraft/App.ts b/src/minecraft/App.ts index 004f43a..a826e67 100644 --- a/src/minecraft/App.ts +++ b/src/minecraft/App.ts @@ -16,6 +16,8 @@ export class Config { public static CHUNK_SIZE: number = 64.0; + public static SELECT_RADIUS: number = 3.0; + // Number of chunks to render outside of the player's chunk // 1 --> 3 x 3, 2 -> 5 x 5, ... n -> 2n+1 x 2n+1 public static BORDER_CHUNKS: number = 1.0; @@ -51,6 +53,13 @@ export class MinecraftAnimation extends CanvasAnimation { private cubeGeometry: Cube; private blankCubeRenderPass: RenderPass; + /* Cube Selection */ + private selectedCubeF32: Float32Array; + private highlightSelected: boolean; + public highlightOn: boolean; + private removeCube: boolean; + private modificationLog: number[][]; + /* Global Rendering Info */ private lightPosition: Vec4; private backgroundColor: Vec4; @@ -91,6 +100,9 @@ export class MinecraftAnimation extends CanvasAnimation { this.lightPosition = new Vec4([-1000, 1000, -1000, 1]); this.backgroundColor = new Vec4([0.0, 0.37254903, 0.37254903, 1.0]); + this.highlightSelected = false; + this.highlightOn = false; + this.modificationLog = []; } private chunkKey(x: number, z: number): string { @@ -336,6 +348,11 @@ export class MinecraftAnimation extends CanvasAnimation { 'aOffset', this.chunks[chunk].cubePositions()); this.blankCubeRenderPass.drawInstanced(this.chunks[chunk].numCubes()); } + if (this.highlightSelected && this.highlightOn) { + this.blankCubeRenderPass.updateAttributeBuffer( + 'aOffset', this.selectedCubeF32); + this.blankCubeRenderPass.drawInstanced(1); + } } public getGUI(): GUI { @@ -349,6 +366,49 @@ export class MinecraftAnimation extends CanvasAnimation { this.verticalVelocity = new Vec3([0.0, Config.JUMP_VELOCITY, 0.0]); } } + + public updateSelectedCube(selectedCube: Vec3) { + this.selectedCubeF32 = new Float32Array(4 * 1); + this.selectedCubeF32[0] = selectedCube.x; + this.selectedCubeF32[1] = selectedCube.y; + this.selectedCubeF32[2] = selectedCube.z; + this.selectedCubeF32[3] = 2.0; + + let isRemovingCube = false; + for (let chunk in this.chunks) { + isRemovingCube = isRemovingCube || this.chunks[chunk].updateSelected(this.highlightOn, selectedCube); + } + this.removeCube = isRemovingCube; + this.highlightSelected = true; + } + + public modifyLandscape(selectedCube: Vec3) { + const x = selectedCube.x; + const y = selectedCube.y; + const z = selectedCube.z; + // See if the selected cube is already in the modification log + let newLog: number[][] = []; + let cubeInLog = false; + for (let i = 0; i < this.modificationLog.length; ++i) { + if (this.modificationLog[i][0] == x && + this.modificationLog[i][1] == y && + this.modificationLog[i][2] == z) { + cubeInLog = true; + } else { + newLog.push(this.modificationLog[i]); + } + } + // Remove the cube if it already exists (reverting to original chunk), + // otherwise add it + if (!cubeInLog) { + newLog.push([x, y, z]); + } + this.modificationLog = newLog; + for (let chunk in this.chunks) { + this.chunks[chunk].updateLandscape(this.removeCube, selectedCube); + } + this.removeCube = !this.removeCube; + } } export function initializeCanvas(): void { diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index 002caa3..3589f83 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -16,6 +16,8 @@ export class Chunk { private maxHeight: number = 100; private unitVecs: Object; + private highlightedCubePos: number; + constructor(centerX: number, centerY: number, size: number) { this.x = centerX; this.y = centerY; @@ -24,6 +26,7 @@ export class Chunk { this.heightMap = new Float32Array(this.size * this.size); this.unitVecs = {}; this.generateCubes(); + this.highlightedCubePos = 0; } public verticalCollision(cameraLocation: Vec3, upwards: boolean): number { @@ -382,6 +385,18 @@ export class Chunk { return c * 0.5; } + private gen2DZeros(size: number) : number[] { + const arr: number[] = []; + for (let i = 0; i < size * size; i++) { + if (i != Math.floor(size * size / 2)) { + arr.push(50); + } else { + arr.push(51); + } + } + return arr; +} + private generateCubes() { // Coordinate of heightmap's top-left corner const topleftx = this.x - this.size / 2; @@ -408,6 +423,8 @@ export class Chunk { }); } + // this.heightMap = new Float32Array(this.gen2DZeros(this.size)); + // Generate density map for chunk let densityMap = {}; @@ -488,6 +505,87 @@ export class Chunk { } } + public updateSelected(highlightOn: boolean, selectedCube: Vec3): boolean { + const topleftx = this.x - this.size / 2; + const toplefty = this.y - this.size / 2; + const bottomrightx = this.x + this.size / 2; + const bottomrighty = this.y + this.size / 2; + // Reset the previously highlighted box + if (this.highlightedCubePos < this.cubes) { + this.cubePositionsF32[4 * this.highlightedCubePos + 3] = 0; + } + // Do not highlight if highlighting is turned off + if (!highlightOn) { + return false; + } + // See if the selected box is in the current chunk + if (topleftx > selectedCube.x || + selectedCube.x >= bottomrightx || + toplefty > selectedCube.z || + selectedCube.z >= bottomrighty) { + return false; + } + // Find if the cube is rendered in the current chunk and highlight if so + for (let i = 0; i < this.cubes; ++i) { + if (this.cubePositionsF32[4 * i] == selectedCube.x && + this.cubePositionsF32[4 * i + 1] == selectedCube.y && + this.cubePositionsF32[4 * i + 2] == selectedCube.z) { + this.cubePositionsF32[4 * i + 3] = 3; + this.highlightedCubePos = i; + return true; + } + } + return false; + } + + public updateLandscape(removeCube: boolean, selectedCube: Vec3) { + const topleftx = this.x - this.size / 2; + const toplefty = this.y - this.size / 2; + const bottomrightx = this.x + this.size / 2; + const bottomrighty = this.y + this.size / 2; + // See if the selected box is in the current chunk + if (topleftx > selectedCube.x || + selectedCube.x >= bottomrightx || + toplefty > selectedCube.z || + selectedCube.z >= bottomrighty) { + return false; + } + // Update number of cubes + let updatedCubes = this.cubes; + if (removeCube) { + updatedCubes -= 1; + } else { + updatedCubes += 1; + } + // Copy cube positions into updated array with the selected cube either + // added or removed + let updatedPositionsF32 = new Float32Array(4 * updatedCubes); + let j = 0; + for (let i = 0; i < this.cubes; ++i) { + if (removeCube && this.cubePositionsF32[4 * i] == selectedCube.x && + this.cubePositionsF32[4 * i + 1] == selectedCube.y && + this.cubePositionsF32[4 * i + 2] == selectedCube.z) { + continue; + } + updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; + updatedPositionsF32[4 * j + 1] = this.cubePositionsF32[4 * i + 1]; + updatedPositionsF32[4 * j + 2] = this.cubePositionsF32[4 * i + 2]; + updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; + ++j; + } + if (!removeCube) { + updatedPositionsF32[4 * j] = selectedCube.x; + updatedPositionsF32[4 * j + 1] = selectedCube.y; + updatedPositionsF32[4 * j + 2] = selectedCube.z; + updatedPositionsF32[4 * j + 3] = 3; + this.highlightedCubePos = j; + } + + // Update internal data structures + this.cubePositionsF32 = updatedPositionsF32; + this.cubes = updatedCubes; + } + public cubePositions(): Float32Array { return this.cubePositionsF32; } diff --git a/src/minecraft/Gui.ts b/src/minecraft/Gui.ts index 36e8abc..dff5856 100644 --- a/src/minecraft/Gui.ts +++ b/src/minecraft/Gui.ts @@ -45,6 +45,8 @@ export class GUI implements IGUI { private SpaceDown: boolean; private ShiftLeftDown: boolean; + private selectedCube: Vec3; + /** * * @param canvas required to get the width and height of the canvas @@ -102,9 +104,13 @@ export class GUI implements IGUI { } public dragStart(mouse: MouseEvent): void { - this.prevX = mouse.screenX; - this.prevY = mouse.screenY; - this.dragging = true; + if (mouse.buttons == 1) { + this.prevX = mouse.screenX; + this.prevY = mouse.screenY; + this.dragging = true; + } else { + this.animation.modifyLandscape(this.selectedCube); + } } public dragEnd(mouse: MouseEvent): void { this.dragging = false; @@ -127,6 +133,25 @@ export class GUI implements IGUI { this.camera.rotate(new Vec3([0, 1, 0]), -GUI.rotationSpeed * dx); this.camera.rotate(this.camera.right(), -GUI.rotationSpeed * dy); } + + const mouseNDC = new Vec4([(x/this.width) * 2 - 1, 1 - (y/this.height) * 2, -1, 1]); + const mouseProjection = this.projMatrix().inverse().multiplyVec4(mouseNDC); + let mouseWorld = this.viewMatrix().inverse().multiplyVec4(mouseProjection); + mouseWorld.scale(1 / mouseWorld.w); + + const ray = Vec3.difference(new Vec3(mouseWorld.xyz), this.camera.pos()).normalize(); + const origin = this.camera.pos(); + // console.log(ray.xyz, origin.xyz); + // Get the next block from the players current position. + let t = Config.SELECT_RADIUS; + ray.scale(t); + const selectedCube = Vec3.sum(origin, ray); + this.selectedCube = new Vec3([Math.round(selectedCube.x), Math.round(selectedCube.y), Math.round(selectedCube.z)]); + this.animation.updateSelectedCube(this.selectedCube); + // console.log(ray.xyz, origin.xyz, selectedBox.xyz, t) + // for (let chunkKey in this.animation.chunks) { + // this.animation.chunks[chunkKey].intersection(ray, origin); + // } } public walkDir(): Vec3 { @@ -166,6 +191,10 @@ export class GUI implements IGUI { this.Ddown = true; break; } + case 'KeyH': { + this.animation.highlightOn = !this.animation.highlightOn; + break; + } case 'KeyR': { this.animation.reset(); break; diff --git a/src/minecraft/Shaders.ts b/src/minecraft/Shaders.ts index c54d959..a759079 100644 --- a/src/minecraft/Shaders.ts +++ b/src/minecraft/Shaders.ts @@ -13,10 +13,12 @@ export const blankCubeVSText = ` varying vec4 normal; varying vec4 wsPos; varying vec2 uv; + varying float highlight; void main () { - - gl_Position = uProj * uView * (aVertPos + aOffset); + vec4 offset = vec4(aOffset.x, aOffset.y, aOffset.z, 0.0); + highlight = aOffset.w; + gl_Position = uProj * uView * (aVertPos + offset); wsPos = aVertPos + aOffset; normal = normalize(aNorm); uv = aUV; @@ -32,6 +34,7 @@ export const blankCubeFSText = ` varying vec4 normal; varying vec4 wsPos; varying vec2 uv; + varying float highlight; float smoothmix(float a0, float a1, float w) { return (a1 - a0) * (3.0 - w * 2.0) * w * w + a0; @@ -159,6 +162,7 @@ export const blankCubeFSText = ` float seed = 10.0; vec3 kd = vec3(1.0, 1.0, 1.0); vec3 ka = vec3(0.3, 0.3, 0.3); + float epsilon = 0.1; /* Compute light fall off */ vec4 lightDirection = uLightPos - wsPos; @@ -166,20 +170,29 @@ export const blankCubeFSText = ` dot_nl = clamp(dot_nl, 0.0, 1.0); // Lava/Magma only generates on low locations - if(wsPos.y < 20.5) { - vec3 magma = perlinMagma(uv, seed); - gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* magma, 1.0); - } - // Snow only generates on high locations - else if(wsPos.y > 55.0){ - vec3 snow = perlinSnow(uv, seed); - gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* snow, 1.0); - } - // Stone - else{ - vec3 stone = perlinStone(uv, seed); - gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* stone, 1.0); + if (highlight >= 2.0 - epsilon) { + if (highlight >= 2.0 - epsilon && highlight <= 2.0 + epsilon) { + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + } else { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + } else { + if(wsPos.y < 20.5) { + vec3 magma = perlinMagma(uv, seed); + gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* magma, 1.0); + } + // Snow only generates on high locations + else if(wsPos.y > 55.0){ + vec3 snow = perlinSnow(uv, seed); + gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* snow, 1.0); + } + // Stone + else{ + vec3 stone = perlinStone(uv, seed); + gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* stone, 1.0); + } } + } From a0f32db25b81917dab83533c60443d317a4545b8 Mon Sep 17 00:00:00 2001 From: Ian Trowbridge Date: Mon, 17 Apr 2023 22:12:27 -0500 Subject: [PATCH 2/6] Added logic to make changes persist between chunks --- src/minecraft/App.ts | 3 +- src/minecraft/Chunk.ts | 68 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/minecraft/App.ts b/src/minecraft/App.ts index a826e67..3fc0803 100644 --- a/src/minecraft/App.ts +++ b/src/minecraft/App.ts @@ -138,6 +138,7 @@ export class MinecraftAnimation extends CanvasAnimation { newChunks[key] = this.cache[key]; } else { newChunks[key] = new Chunk(xCoords[i], zCoords[i], Config.CHUNK_SIZE); + newChunks[key].updateFromLog(this.modificationLog); } if (i == Math.floor(((1 + 2 * Config.BORDER_CHUNKS) ** 2) / 2)) { this.chunk = newChunks[key]; @@ -401,7 +402,7 @@ export class MinecraftAnimation extends CanvasAnimation { // Remove the cube if it already exists (reverting to original chunk), // otherwise add it if (!cubeInLog) { - newLog.push([x, y, z]); + newLog.push([x, y, z, this.removeCube ? -1 : 1]); } this.modificationLog = newLog; for (let chunk in this.chunks) { diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index 3589f83..19484eb 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -586,6 +586,74 @@ export class Chunk { this.cubes = updatedCubes; } + public updateFromLog(modificationLog: number[][]) { + const topleftx = this.x - this.size / 2; + const toplefty = this.y - this.size / 2; + const bottomrightx = this.x + this.size / 2; + const bottomrighty = this.y + this.size / 2; + // Get the modifications for the current the current chunk + let removeCubes = {}; + let addCubes: number[][] = []; + let modification = false; + let updatedCubes = this.cubes; + for (let i = 0; i < modificationLog.length; ++i) { + const x = modificationLog[i][0]; + const y = modificationLog[i][1]; + const z = modificationLog[i][2]; + if (topleftx <= x && x < bottomrightx && + toplefty <= z && z < bottomrighty) { + modification = true; + if (modificationLog[i][3] < 0) { + if (!(x in removeCubes)) { + removeCubes[x] = {}; + } + if (!(y in removeCubes[x])) { + removeCubes[x][y] = {}; + } + if (!(z in removeCubes[x][y])) { + removeCubes[x][y][z] = modificationLog[i][3]; + updatedCubes += modificationLog[i][3]; + } + } else { + addCubes.push([x, y, z]); + } + + } + } + if (!modification) { + return; + } + + // Copy cube positions into updated array with the selected cube either + // added or removed + let updatedPositionsF32 = new Float32Array(4 * updatedCubes); + let j = 0; + for (let i = 0; i < this.cubes; ++i) { + const x = this.cubePositionsF32[4 * i]; + const y = this.cubePositionsF32[4 * i + 1]; + const z = this.cubePositionsF32[4 * i + 2]; + if (x in removeCubes && y in removeCubes[x] && z in removeCubes[x][y]) { + continue; + } + updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; + updatedPositionsF32[4 * j + 1] = this.cubePositionsF32[4 * i + 1]; + updatedPositionsF32[4 * j + 2] = this.cubePositionsF32[4 * i + 2]; + updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; + ++j; + } + for (let i = 0; i < addCubes.length; ++i) { + updatedPositionsF32[4 * j] = addCubes[i][0]; + updatedPositionsF32[4 * j + 1] = addCubes[i][1]; + updatedPositionsF32[4 * j + 2] = addCubes[i][2]; + updatedPositionsF32[4 * j + 3] = 0; + ++j; + } + // Update internal data structures + this.cubePositionsF32 = updatedPositionsF32; + this.cubes = updatedCubes; + + } + public cubePositions(): Float32Array { return this.cubePositionsF32; } From 464ae30869a38bcf7031af1c122530e8658fa833 Mon Sep 17 00:00:00 2001 From: Causality-C Date: Tue, 18 Apr 2023 11:59:17 -0500 Subject: [PATCH 3/6] Fixed Collisions in block placement --- src/minecraft/App.ts | 14 ++++++++-- src/minecraft/Chunk.ts | 62 +++++++++++++++++++++--------------------- src/minecraft/Gui.ts | 7 ++--- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/minecraft/App.ts b/src/minecraft/App.ts index 3fc0803..8cefd07 100644 --- a/src/minecraft/App.ts +++ b/src/minecraft/App.ts @@ -16,6 +16,7 @@ export class Config { public static CHUNK_SIZE: number = 64.0; + // How far you can select a cube from the player public static SELECT_RADIUS: number = 3.0; // Number of chunks to render outside of the player's chunk @@ -138,6 +139,8 @@ export class MinecraftAnimation extends CanvasAnimation { newChunks[key] = this.cache[key]; } else { newChunks[key] = new Chunk(xCoords[i], zCoords[i], Config.CHUNK_SIZE); + + // When loading chunks, we need to update the chunk's state based on modified blocks newChunks[key].updateFromLog(this.modificationLog); } if (i == Math.floor(((1 + 2 * Config.BORDER_CHUNKS) ** 2) / 2)) { @@ -260,7 +263,7 @@ export class MinecraftAnimation extends CanvasAnimation { if (!Config.CREATIVE_MODE) { let position: Vec3 = new Vec3(this.playerPosition.xyz); let chunks: Chunk[] = this.collisionChunks(this.playerPosition); - position.add(this.gui.walkDir()); + position.add(this.gui.walkDir().scale(0.5)); if (!position.equals(this.playerPosition)) { let safe: boolean = true; for (let i = 0; i < chunks.length; i++) { @@ -301,7 +304,7 @@ export class MinecraftAnimation extends CanvasAnimation { } this.gui.getCamera().setPos(this.playerPosition); } else { - this.playerPosition.add(this.gui.walkDir()); + this.playerPosition.add(this.gui.walkDir().scale(0.5)); this.gui.getCamera().setPos(this.playerPosition); this.gravityTime = Date.now(); } @@ -349,6 +352,7 @@ export class MinecraftAnimation extends CanvasAnimation { 'aOffset', this.chunks[chunk].cubePositions()); this.blankCubeRenderPass.drawInstanced(this.chunks[chunk].numCubes()); } + // We draw a sillouette of the selected cube on top of everything else. if (this.highlightSelected && this.highlightOn) { this.blankCubeRenderPass.updateAttributeBuffer( 'aOffset', this.selectedCubeF32); @@ -373,8 +377,9 @@ export class MinecraftAnimation extends CanvasAnimation { this.selectedCubeF32[0] = selectedCube.x; this.selectedCubeF32[1] = selectedCube.y; this.selectedCubeF32[2] = selectedCube.z; - this.selectedCubeF32[3] = 2.0; + this.selectedCubeF32[3] = 2.0; // We use 2.0 to indicate that the cube should be highlighted, as seen in the shader + // We globally determine the block selected and if it should be removed (ie with this.removeCube) let isRemovingCube = false; for (let chunk in this.chunks) { isRemovingCube = isRemovingCube || this.chunks[chunk].updateSelected(this.highlightOn, selectedCube); @@ -391,6 +396,7 @@ export class MinecraftAnimation extends CanvasAnimation { let newLog: number[][] = []; let cubeInLog = false; for (let i = 0; i < this.modificationLog.length; ++i) { + // Checks if the cube is already in the log if (this.modificationLog[i][0] == x && this.modificationLog[i][1] == y && this.modificationLog[i][2] == z) { @@ -404,6 +410,8 @@ export class MinecraftAnimation extends CanvasAnimation { if (!cubeInLog) { newLog.push([x, y, z, this.removeCube ? -1 : 1]); } + + // Update log and all chunks this.modificationLog = newLog; for (let chunk in this.chunks) { this.chunks[chunk].updateLandscape(this.removeCube, selectedCube); diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index 19484eb..00a754a 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -12,7 +12,7 @@ export class Chunk { private y: number; private size: number; // Number of cubes along each side of the chunk private heightMap: Float32Array; - private densityMap: Object; + private densityMap: Object; // Used for 3D perlin noise private maxHeight: number = 100; private unitVecs: Object; @@ -25,6 +25,7 @@ export class Chunk { this.cubes = size * size; this.heightMap = new Float32Array(this.size * this.size); this.unitVecs = {}; + // Cube generation logic called on initialization this.generateCubes(); this.highlightedCubePos = 0; } @@ -262,21 +263,7 @@ export class Chunk { return retArray; } - // Lookup the number of cubes to draw at a given x y coordinate - private numCubesDrawn(arr: Float32Array, i: number, j: number): number { - const idx = this.size * i + j; - // up - - const idxUp = this.size * (i - 1) + j; - const idxDown = this.size * (i + 1) + j; - const idxLeft = this.size * i + j - 1; - const idxRight = this.size * i + j + 1; - const heightNeigh = - [arr[idx], arr[idxUp], arr[idxDown], arr[idxLeft], arr[idxRight]]; - const minNeigh = Math.min(...heightNeigh); - - return Math.floor(arr[idx] - minNeigh + 1); - } + private shouldDrawBasedOnDensity(i: number, j: number, k: number): boolean { // TODO: Should be within bounds let idx = this.size * i + j; @@ -385,18 +372,6 @@ export class Chunk { return c * 0.5; } - private gen2DZeros(size: number) : number[] { - const arr: number[] = []; - for (let i = 0; i < size * size; i++) { - if (i != Math.floor(size * size / 2)) { - arr.push(50); - } else { - arr.push(51); - } - } - return arr; -} - private generateCubes() { // Coordinate of heightmap's top-left corner const topleftx = this.x - this.size / 2; @@ -423,9 +398,6 @@ export class Chunk { }); } - // this.heightMap = new Float32Array(this.gen2DZeros(this.size)); - - // Generate density map for chunk let densityMap = {}; let totalCubes = 0; @@ -505,6 +477,7 @@ export class Chunk { } } + // Returns if a cube is in the chunk and highlights it if it is public updateSelected(highlightOn: boolean, selectedCube: Vec3): boolean { const topleftx = this.x - this.size / 2; const toplefty = this.y - this.size / 2; @@ -557,28 +530,55 @@ export class Chunk { } else { updatedCubes += 1; } + // Copy cube positions into updated array with the selected cube either // added or removed let updatedPositionsF32 = new Float32Array(4 * updatedCubes); let j = 0; for (let i = 0; i < this.cubes; ++i) { + // If cube is set to be removed, we skip it if (removeCube && this.cubePositionsF32[4 * i] == selectedCube.x && this.cubePositionsF32[4 * i + 1] == selectedCube.y && this.cubePositionsF32[4 * i + 2] == selectedCube.z) { + // Remove the cube + let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); + this.densityMap[idx][selectedCube.y] = -1.0; + console.log(idx,this.densityMap[idx]); continue; } + // Else we copy the cube position into the updated array updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; updatedPositionsF32[4 * j + 1] = this.cubePositionsF32[4 * i + 1]; updatedPositionsF32[4 * j + 2] = this.cubePositionsF32[4 * i + 2]; updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; ++j; } + // We add a new cube if (!removeCube) { updatedPositionsF32[4 * j] = selectedCube.x; updatedPositionsF32[4 * j + 1] = selectedCube.y; updatedPositionsF32[4 * j + 2] = selectedCube.z; updatedPositionsF32[4 * j + 3] = 3; this.highlightedCubePos = j; + // Update height map and density map if we add a cube + let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); + let height = this.heightMap[idx]; + console.log(selectedCube.y,height); + // This is the case where we add a cube on top of the current height + if(selectedCube.y >= height) { + // We're building even higher than the current height + let densArr = [...this.densityMap[idx]]; + for(let i = 0; i < selectedCube.y - height; ++i){ + densArr.push(-1.0); + } + densArr.push(1.0); + this.densityMap[idx] = new Float32Array(densArr); + this.heightMap[idx] = densArr.length; + } + else{ + this.densityMap[idx][selectedCube.y] = 1.0; + } + console.log(this.densityMap[idx]); } // Update internal data structures diff --git a/src/minecraft/Gui.ts b/src/minecraft/Gui.ts index dff5856..6cef972 100644 --- a/src/minecraft/Gui.ts +++ b/src/minecraft/Gui.ts @@ -109,6 +109,7 @@ export class GUI implements IGUI { this.prevY = mouse.screenY; this.dragging = true; } else { + // Called whenever mouse 2 is clicked this.animation.modifyLandscape(this.selectedCube); } } @@ -141,17 +142,13 @@ export class GUI implements IGUI { const ray = Vec3.difference(new Vec3(mouseWorld.xyz), this.camera.pos()).normalize(); const origin = this.camera.pos(); - // console.log(ray.xyz, origin.xyz); + // Get the next block from the players current position. let t = Config.SELECT_RADIUS; ray.scale(t); const selectedCube = Vec3.sum(origin, ray); this.selectedCube = new Vec3([Math.round(selectedCube.x), Math.round(selectedCube.y), Math.round(selectedCube.z)]); this.animation.updateSelectedCube(this.selectedCube); - // console.log(ray.xyz, origin.xyz, selectedBox.xyz, t) - // for (let chunkKey in this.animation.chunks) { - // this.animation.chunks[chunkKey].intersection(ray, origin); - // } } public walkDir(): Vec3 { From 59802a11463ed8904a1a15308b84dac85b33c039 Mon Sep 17 00:00:00 2001 From: Causality-C Date: Tue, 18 Apr 2023 14:59:58 -0500 Subject: [PATCH 4/6] Persistence fixed --- src/minecraft/Chunk.ts | 72 ++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index 00a754a..4589fa4 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -371,7 +371,7 @@ export class Chunk { // Add bias towards lower heights so we dont fall through the ground return c * 0.5; } - + private generateCubes() { // Coordinate of heightmap's top-left corner const topleftx = this.x - this.size / 2; @@ -397,7 +397,7 @@ export class Chunk { return value + something[index]; }); } - + // Generate density map for chunk let densityMap = {}; let totalCubes = 0; @@ -524,17 +524,12 @@ export class Chunk { return false; } // Update number of cubes - let updatedCubes = this.cubes; - if (removeCube) { - updatedCubes -= 1; - } else { - updatedCubes += 1; - } + let updatedCubes = this.cubes + (removeCube ? -1 : 1); // Copy cube positions into updated array with the selected cube either // added or removed let updatedPositionsF32 = new Float32Array(4 * updatedCubes); - let j = 0; + let blockIdx = 0; for (let i = 0; i < this.cubes; ++i) { // If cube is set to be removed, we skip it if (removeCube && this.cubePositionsF32[4 * i] == selectedCube.x && @@ -547,19 +542,20 @@ export class Chunk { continue; } // Else we copy the cube position into the updated array - updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; - updatedPositionsF32[4 * j + 1] = this.cubePositionsF32[4 * i + 1]; - updatedPositionsF32[4 * j + 2] = this.cubePositionsF32[4 * i + 2]; - updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; - ++j; + updatedPositionsF32[4 * blockIdx] = this.cubePositionsF32[4 * i]; + updatedPositionsF32[4 * blockIdx + 1] = this.cubePositionsF32[4 * i + 1]; + updatedPositionsF32[4 * blockIdx + 2] = this.cubePositionsF32[4 * i + 2]; + updatedPositionsF32[4 * blockIdx + 3] = this.cubePositionsF32[4 * i + 3]; + ++blockIdx; } // We add a new cube if (!removeCube) { - updatedPositionsF32[4 * j] = selectedCube.x; - updatedPositionsF32[4 * j + 1] = selectedCube.y; - updatedPositionsF32[4 * j + 2] = selectedCube.z; - updatedPositionsF32[4 * j + 3] = 3; - this.highlightedCubePos = j; + updatedPositionsF32[4 * blockIdx] = selectedCube.x; + updatedPositionsF32[4 * blockIdx + 1] = selectedCube.y; + updatedPositionsF32[4 * blockIdx + 2] = selectedCube.z; + updatedPositionsF32[4 * blockIdx + 3] = 3; + + this.highlightedCubePos = blockIdx; // Update height map and density map if we add a cube let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); let height = this.heightMap[idx]; @@ -616,8 +612,9 @@ export class Chunk { } } else { addCubes.push([x, y, z]); + updatedCubes += modificationLog[i][3]; } - + } } if (!modification) { @@ -628,11 +625,17 @@ export class Chunk { // added or removed let updatedPositionsF32 = new Float32Array(4 * updatedCubes); let j = 0; + // Render cubes that are not removed for (let i = 0; i < this.cubes; ++i) { - const x = this.cubePositionsF32[4 * i]; - const y = this.cubePositionsF32[4 * i + 1]; - const z = this.cubePositionsF32[4 * i + 2]; + let x = this.cubePositionsF32[4 * i]; + let y = this.cubePositionsF32[4 * i + 1]; + let z = this.cubePositionsF32[4 * i + 2]; + // Removed Cubes if (x in removeCubes && y in removeCubes[x] && z in removeCubes[x][y]) { + // Update collision logic to remove cube + let idx = (x - topleftx) * this.size + (z - toplefty); + this.densityMap[idx][y] = -1.0; + console.log(idx,this.densityMap[idx]); continue; } updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; @@ -641,12 +644,35 @@ export class Chunk { updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; ++j; } + // Cubes to add for (let i = 0; i < addCubes.length; ++i) { updatedPositionsF32[4 * j] = addCubes[i][0]; updatedPositionsF32[4 * j + 1] = addCubes[i][1]; updatedPositionsF32[4 * j + 2] = addCubes[i][2]; updatedPositionsF32[4 * j + 3] = 0; ++j; + + // Update collision logic to add cube + const x = Math.round(addCubes[i][0] - topleftx); + const z = Math.round(addCubes[i][2] - toplefty); + let idx = x * this.size + z; + + const y = addCubes[i][1]; + let height = this.heightMap[idx]; + // This is the case where we add a cube on top of the current height + if(y >= height) { + // We're building even higher than the current height + let densArr = [...this.densityMap[idx]]; + for(let i = 0; i < y - height; ++i){ + densArr.push(-1.0); + } + densArr.push(1.0); + this.densityMap[idx] = new Float32Array(densArr); + this.heightMap[idx] = densArr.length; + } + else{ + this.densityMap[idx][y] = 1.0; + } } // Update internal data structures this.cubePositionsF32 = updatedPositionsF32; From e3d36e3bbfb2513680970a7bd485ca8a45d13d88 Mon Sep 17 00:00:00 2001 From: Causality-C Date: Tue, 18 Apr 2023 15:11:18 -0500 Subject: [PATCH 5/6] Removed log statements --- src/minecraft/App.ts | 1 - src/minecraft/Chunk.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/minecraft/App.ts b/src/minecraft/App.ts index 8cefd07..ed38b39 100644 --- a/src/minecraft/App.ts +++ b/src/minecraft/App.ts @@ -168,7 +168,6 @@ export class MinecraftAnimation extends CanvasAnimation { Math.abs(cameraLocation.x) % Config.CHUNK_SIZE - Config.CHUNK_SIZE / 2); const zMod = Math.abs( Math.abs(cameraLocation.z) % Config.CHUNK_SIZE - Config.CHUNK_SIZE / 2); - // console.log(cameraLocation.x + " " + cameraLocation.z); if (xMod <= 2.0) { candidates.push( this.chunks[this.chunkKey(center.x + Config.CHUNK_SIZE, center.z)]); diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index 4589fa4..a1dfd74 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -538,7 +538,6 @@ export class Chunk { // Remove the cube let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); this.densityMap[idx][selectedCube.y] = -1.0; - console.log(idx,this.densityMap[idx]); continue; } // Else we copy the cube position into the updated array @@ -559,7 +558,6 @@ export class Chunk { // Update height map and density map if we add a cube let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); let height = this.heightMap[idx]; - console.log(selectedCube.y,height); // This is the case where we add a cube on top of the current height if(selectedCube.y >= height) { // We're building even higher than the current height @@ -574,7 +572,6 @@ export class Chunk { else{ this.densityMap[idx][selectedCube.y] = 1.0; } - console.log(this.densityMap[idx]); } // Update internal data structures @@ -635,7 +632,6 @@ export class Chunk { // Update collision logic to remove cube let idx = (x - topleftx) * this.size + (z - toplefty); this.densityMap[idx][y] = -1.0; - console.log(idx,this.densityMap[idx]); continue; } updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; From 95e1d8fa8143675267137cfce97c04ce3a908c66 Mon Sep 17 00:00:00 2001 From: Causality-C Date: Tue, 18 Apr 2023 15:48:54 -0500 Subject: [PATCH 6/6] More quality of life fixes --- src/minecraft/App.ts | 4 +- src/minecraft/Chunk.ts | 98 +++++++++++++++++----------------------- src/minecraft/Gui.ts | 2 +- src/minecraft/Shaders.ts | 5 +- 4 files changed, 48 insertions(+), 61 deletions(-) diff --git a/src/minecraft/App.ts b/src/minecraft/App.ts index ed38b39..131dac0 100644 --- a/src/minecraft/App.ts +++ b/src/minecraft/App.ts @@ -262,7 +262,7 @@ export class MinecraftAnimation extends CanvasAnimation { if (!Config.CREATIVE_MODE) { let position: Vec3 = new Vec3(this.playerPosition.xyz); let chunks: Chunk[] = this.collisionChunks(this.playerPosition); - position.add(this.gui.walkDir().scale(0.5)); + position.add(this.gui.walkDir().scale(GUI.walkSpeed)); if (!position.equals(this.playerPosition)) { let safe: boolean = true; for (let i = 0; i < chunks.length; i++) { @@ -303,7 +303,7 @@ export class MinecraftAnimation extends CanvasAnimation { } this.gui.getCamera().setPos(this.playerPosition); } else { - this.playerPosition.add(this.gui.walkDir().scale(0.5)); + this.playerPosition.add(this.gui.walkDir().scale(GUI.walkSpeed)); this.gui.getCamera().setPos(this.playerPosition); this.gravityTime = Date.now(); } diff --git a/src/minecraft/Chunk.ts b/src/minecraft/Chunk.ts index a1dfd74..3fc1da2 100644 --- a/src/minecraft/Chunk.ts +++ b/src/minecraft/Chunk.ts @@ -10,6 +10,10 @@ export class Chunk { // coordinates private x: number; // Center of the chunk private y: number; + private topleftx:number; + private toplefty:number; + private bottomrightx:number; + private bottomrighty:number; private size: number; // Number of cubes along each side of the chunk private heightMap: Float32Array; private densityMap: Object; // Used for 3D perlin noise @@ -22,6 +26,10 @@ export class Chunk { this.x = centerX; this.y = centerY; this.size = size; + this.topleftx = this.x - this.size / 2; + this.toplefty = this.y - this.size / 2; + this.bottomrightx = this.x + this.size / 2; + this.bottomrighty = this.y + this.size / 2; this.cubes = size * size; this.heightMap = new Float32Array(this.size * this.size); this.unitVecs = {}; @@ -29,14 +37,16 @@ export class Chunk { this.generateCubes(); this.highlightedCubePos = 0; } + private isInChunkBounds(x: number, y: number): boolean { + return this.topleftx <= x && x < this.bottomrightx && + this.toplefty <= y && y < this.bottomrighty + } public verticalCollision(cameraLocation: Vec3, upwards: boolean): number { - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; const base: number = Math.round(cameraLocation.y - Config.PLAYER_HEIGHT); const top: number = Math.round(cameraLocation.y); - const x = Math.round(cameraLocation.x - topleftx); - const y = Math.round(cameraLocation.z - toplefty); + const x = Math.round(cameraLocation.x - this.topleftx); + const y = Math.round(cameraLocation.z - this.toplefty); if (x >= 0 && y >= 0 && x < this.size && y < this.size) { let idx = x * this.size + y; if (upwards) { @@ -59,9 +69,6 @@ export class Chunk { } public sideCollision(cameraLocation: Vec3): boolean { - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; - const base: number = cameraLocation.y - Config.PLAYER_HEIGHT; const top: number = Math.round(cameraLocation.y); for (let i = -1; i <= 1; i++) { for (let j = -1; j <= 1; j++) { @@ -73,8 +80,8 @@ export class Chunk { let distance = Vec2.distance( point, new Vec2([cameraLocation.x, cameraLocation.z])); if (distance < Config.PLAYER_RADIUS) { - const x = Math.round(cameraLocation.x - topleftx) + i; - const y = Math.round(cameraLocation.z - toplefty) + j; + const x = Math.round(cameraLocation.x - this.topleftx) + i; + const y = Math.round(cameraLocation.z - this.toplefty) + j; if (x >= 0 && y >= 0 && x < this.size && y < this.size) { let idx = x * this.size + y; for (let k = 0; k <= Config.PLAYER_HEIGHT; k++) { @@ -373,10 +380,6 @@ export class Chunk { } private generateCubes() { - // Coordinate of heightmap's top-left corner - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; - // TODO: The real landscape-generation logic. The example code below shows // you how to use the pseudorandom number generator to create a few cubes. this.cubes = this.size * this.size; @@ -409,7 +412,7 @@ export class Chunk { densityMap[idx] = new Float32Array(height); for (let k = 0; k < height; k++) { // Single octave 3D perlin noise - let curPos = new Vec3([topleftx + i, toplefty + j, k]); + let curPos = new Vec3([this.topleftx + i, this.toplefty + j, k]); densityMap[idx][k] = Config.PERLIN_3D ? this.perlinDensity(32, curPos) : 1; // Add a bias towrds lower heights being less likely to be air @@ -456,9 +459,9 @@ export class Chunk { j !== this.size - 1 && k !== height - 1 && k !== 0) { let shouldDraw = this.shouldDrawBasedOnDensity(i, j, k); if (shouldDraw) { - this.cubePositionsF32[4 * pos] = topleftx + i; + this.cubePositionsF32[4 * pos] = this.topleftx + i; this.cubePositionsF32[4 * pos + 1] = k; - this.cubePositionsF32[4 * pos + 2] = toplefty + j; + this.cubePositionsF32[4 * pos + 2] = this.toplefty + j; this.cubePositionsF32[4 * pos + 3] = 0; pos++; } @@ -466,9 +469,9 @@ export class Chunk { // Only draw if the cube is not air else if (densityMap[idx][k] >= 0) { - this.cubePositionsF32[4 * pos] = topleftx + i; + this.cubePositionsF32[4 * pos] = this.topleftx + i; this.cubePositionsF32[4 * pos + 1] = k; - this.cubePositionsF32[4 * pos + 2] = toplefty + j; + this.cubePositionsF32[4 * pos + 2] = this.toplefty + j; this.cubePositionsF32[4 * pos + 3] = 0; pos++; } @@ -479,10 +482,6 @@ export class Chunk { // Returns if a cube is in the chunk and highlights it if it is public updateSelected(highlightOn: boolean, selectedCube: Vec3): boolean { - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; - const bottomrightx = this.x + this.size / 2; - const bottomrighty = this.y + this.size / 2; // Reset the previously highlighted box if (this.highlightedCubePos < this.cubes) { this.cubePositionsF32[4 * this.highlightedCubePos + 3] = 0; @@ -492,10 +491,7 @@ export class Chunk { return false; } // See if the selected box is in the current chunk - if (topleftx > selectedCube.x || - selectedCube.x >= bottomrightx || - toplefty > selectedCube.z || - selectedCube.z >= bottomrighty) { + if (!this.isInChunkBounds(selectedCube.x,selectedCube.z)) { return false; } // Find if the cube is rendered in the current chunk and highlight if so @@ -503,7 +499,7 @@ export class Chunk { if (this.cubePositionsF32[4 * i] == selectedCube.x && this.cubePositionsF32[4 * i + 1] == selectedCube.y && this.cubePositionsF32[4 * i + 2] == selectedCube.z) { - this.cubePositionsF32[4 * i + 3] = 3; + this.cubePositionsF32[4 * i + 3] = 3; // Highlight this.highlightedCubePos = i; return true; } @@ -512,15 +508,8 @@ export class Chunk { } public updateLandscape(removeCube: boolean, selectedCube: Vec3) { - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; - const bottomrightx = this.x + this.size / 2; - const bottomrighty = this.y + this.size / 2; // See if the selected box is in the current chunk - if (topleftx > selectedCube.x || - selectedCube.x >= bottomrightx || - toplefty > selectedCube.z || - selectedCube.z >= bottomrighty) { + if (!this.isInChunkBounds(selectedCube.x,selectedCube.z)) { return false; } // Update number of cubes @@ -536,7 +525,7 @@ export class Chunk { this.cubePositionsF32[4 * i + 1] == selectedCube.y && this.cubePositionsF32[4 * i + 2] == selectedCube.z) { // Remove the cube - let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); + let idx = (selectedCube.x - this.topleftx) * this.size + (selectedCube.z - this.toplefty); this.densityMap[idx][selectedCube.y] = -1.0; continue; } @@ -556,7 +545,7 @@ export class Chunk { this.highlightedCubePos = blockIdx; // Update height map and density map if we add a cube - let idx = (selectedCube.x - topleftx) * this.size + (selectedCube.z - toplefty); + let idx = (selectedCube.x - this.topleftx) * this.size + (selectedCube.z - this.toplefty); let height = this.heightMap[idx]; // This is the case where we add a cube on top of the current height if(selectedCube.y >= height) { @@ -580,10 +569,6 @@ export class Chunk { } public updateFromLog(modificationLog: number[][]) { - const topleftx = this.x - this.size / 2; - const toplefty = this.y - this.size / 2; - const bottomrightx = this.x + this.size / 2; - const bottomrighty = this.y + this.size / 2; // Get the modifications for the current the current chunk let removeCubes = {}; let addCubes: number[][] = []; @@ -593,8 +578,7 @@ export class Chunk { const x = modificationLog[i][0]; const y = modificationLog[i][1]; const z = modificationLog[i][2]; - if (topleftx <= x && x < bottomrightx && - toplefty <= z && z < bottomrighty) { + if (this.isInChunkBounds(x,z)) { modification = true; if (modificationLog[i][3] < 0) { if (!(x in removeCubes)) { @@ -621,7 +605,7 @@ export class Chunk { // Copy cube positions into updated array with the selected cube either // added or removed let updatedPositionsF32 = new Float32Array(4 * updatedCubes); - let j = 0; + let blockIdx = 0; // Render cubes that are not removed for (let i = 0; i < this.cubes; ++i) { let x = this.cubePositionsF32[4 * i]; @@ -630,27 +614,27 @@ export class Chunk { // Removed Cubes if (x in removeCubes && y in removeCubes[x] && z in removeCubes[x][y]) { // Update collision logic to remove cube - let idx = (x - topleftx) * this.size + (z - toplefty); + let idx = (x - this.topleftx) * this.size + (z - this.toplefty); this.densityMap[idx][y] = -1.0; continue; } - updatedPositionsF32[4 * j] = this.cubePositionsF32[4 * i]; - updatedPositionsF32[4 * j + 1] = this.cubePositionsF32[4 * i + 1]; - updatedPositionsF32[4 * j + 2] = this.cubePositionsF32[4 * i + 2]; - updatedPositionsF32[4 * j + 3] = this.cubePositionsF32[4 * i + 3]; - ++j; + updatedPositionsF32[4 * blockIdx] = this.cubePositionsF32[4 * i]; + updatedPositionsF32[4 * blockIdx + 1] = this.cubePositionsF32[4 * i + 1]; + updatedPositionsF32[4 * blockIdx + 2] = this.cubePositionsF32[4 * i + 2]; + updatedPositionsF32[4 * blockIdx + 3] = this.cubePositionsF32[4 * i + 3]; + ++blockIdx; } // Cubes to add for (let i = 0; i < addCubes.length; ++i) { - updatedPositionsF32[4 * j] = addCubes[i][0]; - updatedPositionsF32[4 * j + 1] = addCubes[i][1]; - updatedPositionsF32[4 * j + 2] = addCubes[i][2]; - updatedPositionsF32[4 * j + 3] = 0; - ++j; + updatedPositionsF32[4 * blockIdx] = addCubes[i][0]; + updatedPositionsF32[4 * blockIdx + 1] = addCubes[i][1]; + updatedPositionsF32[4 * blockIdx + 2] = addCubes[i][2]; + updatedPositionsF32[4 * blockIdx + 3] = 0; + ++blockIdx; // Update collision logic to add cube - const x = Math.round(addCubes[i][0] - topleftx); - const z = Math.round(addCubes[i][2] - toplefty); + const x = Math.round(addCubes[i][0] - this.topleftx); + const z = Math.round(addCubes[i][2] - this.toplefty); let idx = x * this.size + z; const y = addCubes[i][1]; diff --git a/src/minecraft/Gui.ts b/src/minecraft/Gui.ts index 6cef972..2ca5785 100644 --- a/src/minecraft/Gui.ts +++ b/src/minecraft/Gui.ts @@ -24,7 +24,7 @@ interface IGUI { export class GUI implements IGUI { private static readonly rotationSpeed: number = 0.01; - private static readonly walkSpeed: number = 1; + public static readonly walkSpeed: number = 0.5; private static readonly rollSpeed: number = 0.1; private static readonly panSpeed: number = 0.1; diff --git a/src/minecraft/Shaders.ts b/src/minecraft/Shaders.ts index a759079..317792f 100644 --- a/src/minecraft/Shaders.ts +++ b/src/minecraft/Shaders.ts @@ -169,14 +169,17 @@ export const blankCubeFSText = ` float dot_nl = dot(normalize(lightDirection), normalize(normal)); dot_nl = clamp(dot_nl, 0.0, 1.0); - // Lava/Magma only generates on low locations + // Highlight logic for the block if (highlight >= 2.0 - epsilon) { if (highlight >= 2.0 - epsilon && highlight <= 2.0 + epsilon) { + // Green gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); } else { + // Red gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } } else { + // Lava/Magma only generates on low locations if(wsPos.y < 20.5) { vec3 magma = perlinMagma(uv, seed); gl_FragColor = vec4(clamp(ka + dot_nl * kd, 0.0, 1.0)* magma, 1.0);