fix: fix rendering issues with water by correctly specifying render order

fix: show chunks border now works without chunks reload
This commit is contained in:
Vitaly 2023-11-11 09:53:27 +03:00
commit 5e788e0fa0
5 changed files with 49 additions and 8 deletions

View file

@ -72,7 +72,7 @@ You can also drag and drop any .dat file into the browser window to see it's con
- `F3` - Toggle debug overlay
- `F3 + A` - Reload all chunks (these that are loaded from the server)
<!-- <!-- - `F3 + N` - Restart local server (basically resets the world!) -->
- `F3 + G` - Toggle chunk sections (geometries) border visibility (aka Three.js geometry helpers) - most probably need to reload chunks after toggling
- `F3 + G` - Toggle chunk sections (geometries) border visibility (aka Three.js geometry helpers)
### Notable Things that Power this Project

View file

@ -118,6 +118,10 @@ export class Viewer {
this.setBlockStateId(new Vec3(pos.x, pos.y, pos.z), stateId)
})
emitter.on('chunkPosUpdate', ({ pos }) => {
this.world.updateViewerPosition(pos)
})
emitter.emit('listening')
this.domElement.addEventListener('pointerdown', (evt) => {

View file

@ -18,7 +18,7 @@ export class WorldDataEmitter extends EventEmitter {
private eventListeners: Record<string, any> = {};
private emitter: WorldDataEmitter
constructor (public world: import('prismarine-world').world.World | typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) {
constructor(public world: import('prismarine-world').world.World | typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) {
super()
this.loadedChunks = {}
this.lastPos = new Vec3(0, 0, 0).update(position)
@ -91,6 +91,7 @@ export class WorldDataEmitter extends EventEmitter {
}
async init (pos: Vec3) {
this.emitter.emit('chunkPosUpdate', { pos })
const [botX, botZ] = chunkPos(pos)
const positions = generateSpiralMatrix(this.viewDistance).map(([x, z]) => new Vec3((botX + x) * 16, 0, (botZ + z) * 16))
@ -138,6 +139,7 @@ export class WorldDataEmitter extends EventEmitter {
const [lastX, lastZ] = chunkPos(this.lastPos)
const [botX, botZ] = chunkPos(pos)
if (lastX !== botX || lastZ !== botZ || force) {
this.emitter.emit('chunkPosUpdate', { pos })
const newView = new ViewRect(botX, botZ, this.viewDistance)
const chunksToUnload: Vec3[] = []
for (const coords of Object.keys(this.loadedChunks)) {

View file

@ -32,6 +32,7 @@ export class WorldRenderer {
downloadedBlockStatesData = undefined as any
downloadedTextureImage = undefined as any
workers: any[] = []
viewerPosition?: Vec3
texturesVersion?: string
@ -69,13 +70,16 @@ export class WorldRenderer {
const mesh = new THREE.Mesh(geometry, this.material)
mesh.position.set(data.geometry.sx, data.geometry.sy, data.geometry.sz)
mesh.name = 'mesh'
object = new THREE.Group()
object.add(mesh)
if (this.showChunkBorders) {
const boxHelper = new THREE.BoxHelper(mesh, 0xffff00)
object.add(boxHelper)
const boxHelper = new THREE.BoxHelper(mesh, 0xffff00)
boxHelper.name = 'helper'
object.add(boxHelper)
if (!this.showChunkBorders) {
boxHelper.visible = false
}
// should not it compute once
// should not compute it once
if (Object.keys(data.geometry.signs).length) {
for (const [posKey, { isWall, rotation }] of Object.entries(data.geometry.signs)) {
const [x, y, z] = posKey.split(',')
@ -85,6 +89,7 @@ export class WorldRenderer {
}
}
this.sectionObjects[data.key] = object
this.updatePosDataChunk(data.key)
this.scene.add(object)
} else if (data.type === 'sectionFinished') {
this.sectionsOutstanding.delete(data.key)
@ -96,6 +101,26 @@ export class WorldRenderer {
}
}
/**
* Optionally update data that are depedendent on the viewer position
*/
updatePosDataChunk (key: string) {
if (!this.viewerPosition) return
const [x, y, z] = key.split(',').map(x => Math.floor(+x / 16))
const [xPlayer, yPlayer, zPlayer] = this.viewerPosition.toArray().map(x => Math.floor(x / 16))
// sum of distances: x + y + z
const chunkDistance = Math.abs(x - xPlayer) + Math.abs(y - yPlayer) + Math.abs(z - zPlayer)
const section = this.sectionObjects[key].children.find(child => child.name === 'mesh')!
section.renderOrder = 500 - chunkDistance
}
updateViewerPosition (pos: Vec3) {
this.viewerPosition = pos
for (const key of Object.keys(this.sectionObjects)) {
this.updatePosDataChunk(key)
}
}
renderSign (position: Vec3, rotation: number, isWall: boolean, blockEntity) {
const PrismarineChat = PrismarineChatLoader(this.version!)
const canvas = renderSign(blockEntity, PrismarineChat)
@ -126,6 +151,17 @@ export class WorldRenderer {
return group
}
updateShowChunksBorder (value: boolean) {
this.showChunkBorders = value
for (const object of Object.values(this.sectionObjects)) {
for (const child of object.children) {
if (child.name === 'helper') {
child.visible = value;
}
}
}
}
resetWorld () {
this.active = false
for (const mesh of Object.values(this.sectionObjects)) {

View file

@ -244,9 +244,8 @@ document.addEventListener('keydown', (e) => {
void reloadChunks()
}
if (e.code === 'KeyG') {
// todo make it work without reload
options.showChunkBorders = !options.showChunkBorders
void reloadChunks()
viewer.world.updateShowChunksBorder(options.showChunkBorders)
}
return
}