minecraft-renderer 0.1.41 → 0.1.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mesher.js +52 -52
- package/dist/mesher.js.map +3 -3
- package/dist/mesherWasm.js +68 -68
- package/dist/minecraft-renderer.js +7 -7
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +18 -18
- package/package.json +1 -1
- package/src/lib/worldrendererCommon.ts +1 -0
- package/src/mesher-legacy/mesher.ts +10 -1
- package/src/mesher-shared/models.ts +41 -0
- package/src/mesher-shared/shared.ts +2 -0
- package/src/three/modules/sciFiWorldReveal.ts +6 -0
- package/src/three/worldRendererThree.ts +1 -1
- package/src/wasm-mesher/runtime-build/wasm_mesher.d.ts +66 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher.js +248 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm.d.ts +4 -0
- package/src/wasm-mesher/worker/mesherWasm.ts +194 -2
|
@@ -519,6 +519,167 @@ const meshColumnFromParsedV16V17 = (
|
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
// Fused multi-column helpers.
|
|
524
|
+
// Zero-alloc: reuse existing TypedArray buffers from caches, no concat.
|
|
525
|
+
// ---------------------------------------------------------------------------
|
|
526
|
+
|
|
527
|
+
const meshMultiColumnsFromRawV18Plus = (
|
|
528
|
+
chunksToUse: Array<{ x: number, z: number, chunk: any }>,
|
|
529
|
+
x: number,
|
|
530
|
+
z: number,
|
|
531
|
+
worldMinY: number,
|
|
532
|
+
worldMaxY: number,
|
|
533
|
+
meta: ReturnType<typeof getBlockMeta>
|
|
534
|
+
): any | null => {
|
|
535
|
+
if (!wasm || !(wasm as any).generateGeometryFromMapChunkV18PlusMulti) return null
|
|
536
|
+
const chunkCount = chunksToUse.length
|
|
537
|
+
if (chunkCount === 0) return null
|
|
538
|
+
|
|
539
|
+
const rawPackets: Uint8Array[] = []
|
|
540
|
+
const numSectionsList = new Uint32Array(chunkCount)
|
|
541
|
+
const chunkXs = new Int32Array(chunkCount)
|
|
542
|
+
const chunkZs = new Int32Array(chunkCount)
|
|
543
|
+
let protocol = 0
|
|
544
|
+
|
|
545
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
546
|
+
const raw = rawMapChunkCache.get(rawCacheKey(chunksToUse[i].x, chunksToUse[i].z))
|
|
547
|
+
if (!raw || raw.protocol < 757) return null
|
|
548
|
+
rawPackets.push(raw.rawPacket)
|
|
549
|
+
numSectionsList[i] = raw.numSections
|
|
550
|
+
chunkXs[i] = chunksToUse[i].x
|
|
551
|
+
chunkZs[i] = chunksToUse[i].z
|
|
552
|
+
if (i === 0) protocol = raw.protocol
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const columnHeight = worldMaxY - worldMinY
|
|
556
|
+
try {
|
|
557
|
+
return (wasm as any).generateGeometryFromMapChunkV18PlusMulti(
|
|
558
|
+
rawPackets,
|
|
559
|
+
numSectionsList,
|
|
560
|
+
MAX_BITS_PER_BLOCK,
|
|
561
|
+
MAX_BITS_PER_BIOME,
|
|
562
|
+
protocol,
|
|
563
|
+
chunkXs,
|
|
564
|
+
chunkZs,
|
|
565
|
+
x, worldMinY, z, columnHeight,
|
|
566
|
+
worldMinY, worldMaxY,
|
|
567
|
+
worldMinY,
|
|
568
|
+
meta.invisibleBlocks,
|
|
569
|
+
meta.transparentBlocks,
|
|
570
|
+
meta.noAoBlocks,
|
|
571
|
+
meta.cullIdenticalBlocks,
|
|
572
|
+
meta.occludingBlocks,
|
|
573
|
+
config?.enableLighting !== false,
|
|
574
|
+
config?.smoothLighting !== false,
|
|
575
|
+
config?.skyLight || 15
|
|
576
|
+
)
|
|
577
|
+
} catch (err) {
|
|
578
|
+
console.warn('[WASM Mesher] generateGeometryFromMapChunkV18PlusMulti failed:', err)
|
|
579
|
+
return null
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const meshMultiColumnsFromParsedV16V17 = (
|
|
584
|
+
chunksToUse: Array<{ x: number, z: number, chunk: any }>,
|
|
585
|
+
x: number,
|
|
586
|
+
z: number,
|
|
587
|
+
worldMinY: number,
|
|
588
|
+
worldMaxY: number,
|
|
589
|
+
meta: ReturnType<typeof getBlockMeta>
|
|
590
|
+
): any | null => {
|
|
591
|
+
if (!wasm || !(wasm as any).generateGeometryFromParsedV16V17Multi) return null
|
|
592
|
+
const chunkCount = chunksToUse.length
|
|
593
|
+
if (chunkCount === 0) return null
|
|
594
|
+
|
|
595
|
+
// Determine which cache family owns all columns. Homogeneity is
|
|
596
|
+
// guaranteed by the server protocol version: v16 and v17 caches are
|
|
597
|
+
// never populated simultaneously within a session.
|
|
598
|
+
let family: 'v17' | 'v16' | null = null
|
|
599
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
600
|
+
const key = rawCacheKey(chunksToUse[i].x, chunksToUse[i].z)
|
|
601
|
+
if (parsedV17Cache.has(key)) {
|
|
602
|
+
if (family === 'v16') return null
|
|
603
|
+
family = 'v17'
|
|
604
|
+
} else if (parsedV16Cache.has(key)) {
|
|
605
|
+
if (family === 'v17') return null
|
|
606
|
+
family = 'v16'
|
|
607
|
+
} else {
|
|
608
|
+
return null
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (!family) return null
|
|
612
|
+
|
|
613
|
+
const chunkDataList: Uint8Array[] = []
|
|
614
|
+
const biomesList: Int32Array[] = []
|
|
615
|
+
const skyLightList: Uint8Array[] = []
|
|
616
|
+
const blockLightList: Uint8Array[] = []
|
|
617
|
+
const numSectionsList = new Uint32Array(chunkCount)
|
|
618
|
+
const chunkXs = new Int32Array(chunkCount)
|
|
619
|
+
const chunkZs = new Int32Array(chunkCount)
|
|
620
|
+
const bitMapLoHi = new Uint32Array(chunkCount * 2)
|
|
621
|
+
let maxBitsPerBlock = 15
|
|
622
|
+
|
|
623
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
624
|
+
const key = rawCacheKey(chunksToUse[i].x, chunksToUse[i].z)
|
|
625
|
+
if (family === 'v17') {
|
|
626
|
+
const entry = parsedV17Cache.get(key)!
|
|
627
|
+
chunkDataList.push(entry.chunkData)
|
|
628
|
+
biomesList.push(entry.biomes ?? new Int32Array(0))
|
|
629
|
+
numSectionsList[i] = entry.numSections
|
|
630
|
+
bitMapLoHi[i * 2] = entry.bitMapLoHi[0]
|
|
631
|
+
bitMapLoHi[i * 2 + 1] = entry.bitMapLoHi[1]
|
|
632
|
+
if (i === 0) maxBitsPerBlock = entry.maxBitsPerBlock
|
|
633
|
+
const light = updateLightV17Cache.get(key)
|
|
634
|
+
skyLightList.push(light?.skyLight ?? new Uint8Array(0))
|
|
635
|
+
blockLightList.push(light?.blockLight ?? new Uint8Array(0))
|
|
636
|
+
} else {
|
|
637
|
+
const entry = parsedV16Cache.get(key)!
|
|
638
|
+
chunkDataList.push(entry.chunkData)
|
|
639
|
+
biomesList.push(entry.biomes ?? new Int32Array(0))
|
|
640
|
+
numSectionsList[i] = 16
|
|
641
|
+
const bm = entry.bitMap >>> 0
|
|
642
|
+
bitMapLoHi[i * 2] = bm
|
|
643
|
+
bitMapLoHi[i * 2 + 1] = 0
|
|
644
|
+
const light = updateLightV16Cache.get(key)
|
|
645
|
+
skyLightList.push(light?.skyLight ?? new Uint8Array(0))
|
|
646
|
+
blockLightList.push(light?.blockLight ?? new Uint8Array(0))
|
|
647
|
+
}
|
|
648
|
+
chunkXs[i] = chunksToUse[i].x
|
|
649
|
+
chunkZs[i] = chunksToUse[i].z
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
const columnHeight = worldMaxY - worldMinY
|
|
653
|
+
try {
|
|
654
|
+
return (wasm as any).generateGeometryFromParsedV16V17Multi(
|
|
655
|
+
chunkDataList,
|
|
656
|
+
bitMapLoHi,
|
|
657
|
+
numSectionsList,
|
|
658
|
+
maxBitsPerBlock,
|
|
659
|
+
biomesList,
|
|
660
|
+
1,
|
|
661
|
+
skyLightList,
|
|
662
|
+
blockLightList,
|
|
663
|
+
chunkXs,
|
|
664
|
+
chunkZs,
|
|
665
|
+
x, worldMinY, z, columnHeight,
|
|
666
|
+
worldMinY, worldMaxY,
|
|
667
|
+
worldMinY,
|
|
668
|
+
meta.invisibleBlocks,
|
|
669
|
+
meta.transparentBlocks,
|
|
670
|
+
meta.noAoBlocks,
|
|
671
|
+
meta.cullIdenticalBlocks,
|
|
672
|
+
meta.occludingBlocks,
|
|
673
|
+
config?.enableLighting !== false,
|
|
674
|
+
config?.smoothLighting !== false,
|
|
675
|
+
config?.skyLight || 15
|
|
676
|
+
)
|
|
677
|
+
} catch (err) {
|
|
678
|
+
console.warn('[WASM Mesher] generateGeometryFromParsedV16V17Multi failed:', err)
|
|
679
|
+
return null
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
522
683
|
const handleMessage = async (data: any) => {
|
|
523
684
|
const globalVar: any = globalThis
|
|
524
685
|
|
|
@@ -885,6 +1046,8 @@ function processColumnTick() {
|
|
|
885
1046
|
let t1 = 0
|
|
886
1047
|
let usedFusedPath = false
|
|
887
1048
|
|
|
1049
|
+
const meta = getBlockMeta(version)
|
|
1050
|
+
|
|
888
1051
|
// ------------------------------------------------------------------
|
|
889
1052
|
// Fused fast-path: for single-column meshing (no neighbours), parse
|
|
890
1053
|
// and mesh in ONE WASM call so no typed arrays leave Rust memory.
|
|
@@ -894,7 +1057,6 @@ function processColumnTick() {
|
|
|
894
1057
|
const rawEntry = rawMapChunkCache.get(rawCacheKey(x, z))
|
|
895
1058
|
const v17Entry = parsedV17Cache.get(rawCacheKey(x, z))
|
|
896
1059
|
const v16Entry = parsedV16Cache.get(rawCacheKey(x, z))
|
|
897
|
-
const meta = getBlockMeta(version)
|
|
898
1060
|
|
|
899
1061
|
if (rawEntry) {
|
|
900
1062
|
wasmResult = meshColumnFromRawV18Plus(rawEntry, x, z, worldMinY, worldMaxY, meta)
|
|
@@ -922,7 +1084,23 @@ function processColumnTick() {
|
|
|
922
1084
|
t1 = performance.now()
|
|
923
1085
|
wasmPhase = t1 - t0
|
|
924
1086
|
preTargetConvert = wasmPhase
|
|
925
|
-
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// ------------------------------------------------------------------
|
|
1091
|
+
// Fused multi-column fast-path: parse+mesh all columns in one WASM
|
|
1092
|
+
// call with zero JS typed-array allocation.
|
|
1093
|
+
// Falls back to the old two-step path when the cache is incomplete
|
|
1094
|
+
// or any helper returns null.
|
|
1095
|
+
// ------------------------------------------------------------------
|
|
1096
|
+
if (!wasmResult && chunkCount > 1) {
|
|
1097
|
+
wasmResult = meshMultiColumnsFromRawV18Plus(chunksToUse, x, z, worldMinY, worldMaxY, meta)
|
|
1098
|
+
?? meshMultiColumnsFromParsedV16V17(chunksToUse, x, z, worldMinY, worldMaxY, meta)
|
|
1099
|
+
if (wasmResult) {
|
|
1100
|
+
usedFusedPath = true
|
|
1101
|
+
t1 = performance.now()
|
|
1102
|
+
wasmPhase = t1 - t0
|
|
1103
|
+
preTargetConvert = wasmPhase
|
|
926
1104
|
}
|
|
927
1105
|
}
|
|
928
1106
|
|
|
@@ -1169,6 +1347,20 @@ function processColumnTick() {
|
|
|
1169
1347
|
//@ts-ignore
|
|
1170
1348
|
geometry.indices?.buffer,
|
|
1171
1349
|
].filter(Boolean)
|
|
1350
|
+
|
|
1351
|
+
if (exported.geometry.indices.length > 0 && config.computeWireframeEdges) {
|
|
1352
|
+
try {
|
|
1353
|
+
const wireframeF32 = geometry.indices instanceof Uint32Array
|
|
1354
|
+
? wasm!.computeWireframeEdges(geometry.positions as Float32Array, geometry.indices)
|
|
1355
|
+
: wasm!.computeWireframeEdgesU16(geometry.positions as Float32Array, geometry.indices as Uint16Array)
|
|
1356
|
+
if (wireframeF32.length > 0) {
|
|
1357
|
+
geometry.wireframePositions = wireframeF32
|
|
1358
|
+
transferable.push(wireframeF32.buffer)
|
|
1359
|
+
}
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
// Fall through — sciFiWorldReveal will fall back to main-thread computation
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1172
1364
|
} else {
|
|
1173
1365
|
geometry = makeEmptyColumnGeometry(sx, sy, sz, sectionHeight, false)
|
|
1174
1366
|
// Still attach block entity metadata so the main thread sees
|