diff --git a/prismarine-viewer/viewer/lib/mesher/models.ts b/prismarine-viewer/viewer/lib/mesher/models.ts index bfb96d114..460c0317b 100644 --- a/prismarine-viewer/viewer/lib/mesher/models.ts +++ b/prismarine-viewer/viewer/lib/mesher/models.ts @@ -300,6 +300,15 @@ function renderElement (world: World, cursor: Vec3, element, doAO: boolean, attr const maxy = element.to[1] const maxz = element.to[2] + const isConnectedWithTheBlock = ( + (face === 'up' && maxy === 16) || + (face === 'down' && miny === 0) || + (face === 'north' && minz === 0) || + (face === 'south' && maxz === 16) || + (face === 'west' && minx === 0) || + (face === 'east' && maxx === 16) + ) + const u = eFace.texture.u const v = eFace.texture.v const su = eFace.texture.su @@ -349,7 +358,7 @@ function renderElement (world: World, cursor: Vec3, element, doAO: boolean, attr const aos: number[] = [] const neighborPos = position.plus(new Vec3(...dir)) - const baseLight = world.getLight(neighborPos) / 15 + const baseLight = world.getLight(isConnectedWithTheBlock ? neighborPos : position) / 15 for (const pos of corners) { let vertex = [ (pos[0] ? maxx : minx), diff --git a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts index 22e3a7b2b..9284a10e3 100644 --- a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts +++ b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts @@ -1,43 +1,44 @@ import { test, expect } from 'vitest' import { setup } from './mesherTester' +import { BlockNames } from '../../../../../src/mcDataTypes' const version = '1.18.1' const addPositions = [ - // [[0, 0, 0], 'diamond_block'], - [[1, 0, 0], 'stone'], - [[-1, 0, 0], 'stone'], - [[0, 1, 0], 'stone'], - [[0, -1, 0], 'stone'], - [[0, 0, 1], 'stone'], - [[0, 0, -1], 'stone'], + // [[0, 0, 0], 'diamond_block'], + [[1, 0, 0], 'stone'], + [[-1, 0, 0], 'stone'], + [[0, 1, 0], 'stone'], + [[0, -1, 0], 'stone'], + [[0, 0, 1], 'stone'], + [[0, 0, -1], 'stone'], ] as const test('Known blocks are not rendered', () => { - const { mesherWorld, getGeometry, pos, mcData } = setup(version, addPositions as any) + const { mesherWorld, getGeometry, pos, mcData } = setup(version, addPositions as any) - let time = 0 - let times = 0 - const invalidBlocks = {}/* as {[number, number]} */ - for (const block of mcData.blocksArray) { - if (block.maxStateId! - block.minStateId! > 100) continue - for (let i = block.minStateId!; i <= block.maxStateId!; i++) { - if (block.transparent) continue - mesherWorld.setBlockStateId(pos, i) - const start = performance.now() - const { centerFaces, totalTiles, centerTileNeighbors } = getGeometry() - time += performance.now() - start - times++ - if (centerFaces === 0 && centerTileNeighbors !== 0) { - if (invalidBlocks[block.name]) continue - invalidBlocks[block.name] = [i - block.minStateId!, centerTileNeighbors] - // console.log('INVALID', block.name, centerTileNeighbors, i - block.minStateId) - } - } + let time = 0 + let times = 0 + const invalidBlocks = {}/* as {[number, number]} */ + for (const block of mcData.blocksArray) { + if (block.maxStateId! - block.minStateId! > 100) continue + for (let i = block.minStateId!; i <= block.maxStateId!; i++) { + if (block.transparent) continue + mesherWorld.setBlockStateId(pos, i) + const start = performance.now() + const { centerFaces, totalTiles, centerTileNeighbors } = getGeometry() + time += performance.now() - start + times++ + if (centerFaces === 0 && centerTileNeighbors !== 0) { + if (invalidBlocks[block.name]) continue + invalidBlocks[block.name] = [i - block.minStateId!, centerTileNeighbors] + // console.log('INVALID', block.name, centerTileNeighbors, i - block.minStateId) + } } - console.log('Average time', time / times) - // Fully expected - expect(invalidBlocks).toMatchInlineSnapshot(` + } + console.log('Average time', time / times) + // Fully expected + expect(invalidBlocks).toMatchInlineSnapshot(` { "creeper_head": [ 0, @@ -94,3 +95,51 @@ test('Known blocks are not rendered', () => { } `) }) + + +test('Light calculated correctly', () => { + const result = {} as Record + for (const block of ['oak_fence', 'oak_slab', 'soul_sand'] as BlockNames[]) { + const positions = [ + [[0, 0, 0], block] + ] + const { getLights, setLight, reload } = setup('1.20.2', positions as any) + setLight(0, 0, 0, 5) + setLight(0, -1, 0, 10) + setLight(0, 1, 0, 10) + setLight(1, 0, 0, 10) + setLight(-1, 0, 0, 10) + setLight(0, 0, 1, 10) + setLight(0, 0, -1, 10) + reload() + result[block] = getLights() + } + expect(result).toMatchInlineSnapshot(` + { + "oak_fence": { + "down": 10, + "east": 5, + "north": 5, + "south": 5, + "up": 10, + "west": 5, + }, + "oak_slab": { + "down": 10, + "east": 10, + "north": 10, + "south": 10, + "up": 5, + "west": 10, + }, + "soul_sand": { + "down": 10, + "east": 10, + "north": 10, + "south": 10, + "up": 10, + "west": 10, + }, + } + `) +}) diff --git a/prismarine-viewer/viewer/lib/mesher/world.ts b/prismarine-viewer/viewer/lib/mesher/world.ts index 9a4f0ab3e..8f52ec68a 100644 --- a/prismarine-viewer/viewer/lib/mesher/world.ts +++ b/prismarine-viewer/viewer/lib/mesher/world.ts @@ -44,17 +44,18 @@ export class World { // if (lightsCache.has(key)) return lightsCache.get(key) const column = this.getColumnByPos(pos) if (!column || !hasChunkSection(column, pos)) return 15 + const posChunk = posInChunk(pos) let result = Math.min( 15, Math.max( - column.getBlockLight(posInChunk(pos)), - Math.min(skyLight, column.getSkyLight(posInChunk(pos))) + column.getBlockLight(posChunk), + Math.min(skyLight, column.getSkyLight(posChunk)) ) + 2 ) // lightsCache.set(key, result) - if (result === 2 && this.getBlock(pos)?.name.match(/_stairs|slab/)) { // todo this is obviously wrong - result = this.getLight(pos.offset(0, 1, 0)) - } + // if (result === 2 && this.getBlock(pos)?.name.match(/_stairs|slab/)) { // todo this is obviously wrong + // result = this.getLight(pos.offset(0, 1, 0)) + // } if (isNeighbor && result === 2) result = 15 // TODO return result } @@ -128,7 +129,8 @@ export class World { } // todo export in chunk instead -const hasChunkSection = (column, pos) => { +export const hasChunkSection = (column, pos) => { + pos = posInChunk(pos) if (column._getSection) return column._getSection(pos) if (column.skyLightSections) { return column.skyLightSections[getLightSectionIndex(pos, column.minY)] || column.blockLightSections[getLightSectionIndex(pos, column.minY)]