Phase 2: full-voxel chunk storage, greedy mesher, and Babylon 3D viewer
api: chunk_sections table (per 16x16x16 section, base64-encoded u16 blockStateId array) and mesh_pointers table, additive to Phase 1's column-based chunk_columns/tile_pointers — 2D tile rendering keeps using the cheap column path unchanged. New "sections" WS message (backfill on chunk load + delta resend on flush, same "current state, not a diff" philosophy as columns) reuses the existing dirty-chunk Redis event, so one event now triggers the worker to re-render both the 2D tile and any 3D meshes for that chunk. New mesh-serving routes. worker: a from-scratch greedy mesher (per-axis 2D mask sweep + rectangle merge — the standard voxel-meshing technique, reimplemented from its public description, not copied from any codebase) producing a compact custom binary vertex buffer per non-empty section. Verified with unit tests, including one that specifically checks a uniform section collapses to exactly 6 merged quads rather than one quad per voxel face (the decisive signal that merging, not just per-voxel face emission, is actually happening). frontend: a barebones Babylon.js 3D viewer (/3d) that loads a fixed radius of chunks, parses the mesh binary format, and renders each section as its own mesh (no cross-section merging yet, no camera-based streaming yet — both reasonable follow-ups once there's a reason to optimize). End-to-end verified against live containers, including through the real mod-side Java WS client (see MCMapper-Mod's matching commit): a known half-solid section correctly round-trips to exactly 24 vertices / 36 indices at the mesh-serving endpoint, matching the "6 merged outer faces" the unit tests predict.
This commit is contained in:
@@ -14,6 +14,7 @@ html(lang="en")
|
||||
div#app.h-screen.flex.flex-col(x-data="mapmapper()" x-init="init()")
|
||||
header.px-4.py-2.flex.items-center.gap-4.border-b.border-neutral-700
|
||||
h1.text-lg.font-semibold MCMapper
|
||||
a.text-sm.text-neutral-400.underline(href="/3d") 3D view
|
||||
span.text-sm.text-neutral-400(x-show="!loading && server")
|
||||
| Viewing:
|
||||
span(x-text="server?.name")
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
meta(name="viewport" content="width=device-width, initial-scale=1")
|
||||
title MCMapper — 3D
|
||||
link(rel="stylesheet" href="/css/tailwind.css")
|
||||
script(src="https://cdn.babylonjs.com/babylon.js")
|
||||
style.
|
||||
html, body, #renderCanvas { height: 100%; margin: 0; touch-action: none; outline: none; }
|
||||
body.bg-neutral-900.text-neutral-100
|
||||
div.h-screen.flex.flex-col
|
||||
header.px-4.py-2.flex.items-center.gap-4.border-b.border-neutral-700
|
||||
h1.text-lg.font-semibold MCMapper — 3D
|
||||
a.text-sm.text-neutral-400.underline(href="/") back to 2D map
|
||||
span#status.text-sm.text-neutral-500 loading…
|
||||
canvas#renderCanvas.flex-1
|
||||
script(src="/js/mesh.js")
|
||||
Reference in New Issue
Block a user