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:
@@ -2,15 +2,18 @@ import { Elysia } from "elysia";
|
||||
import pug from "pug";
|
||||
import { join } from "path";
|
||||
|
||||
// Phase 1: a barebones Leaflet 2D viewer (see public/js/map.js). Babylon 3D canvas, chat box,
|
||||
// marker tool, and admin panel land in later phases per the plan's phased delivery.
|
||||
// Phase 1: a barebones Leaflet 2D viewer (see public/js/map.js). Phase 2 adds the Babylon 3D
|
||||
// viewer (see public/js/mesh.js). Chat box, marker tool, and admin panel land in later phases.
|
||||
const renderIndex = pug.compileFile(join(import.meta.dir, "views/index.pug"));
|
||||
const renderScene3d = pug.compileFile(join(import.meta.dir, "views/scene3d.pug"));
|
||||
|
||||
const app = new Elysia()
|
||||
.get("/", () => new Response(renderIndex({}), { headers: { "Content-Type": "text/html" } }))
|
||||
.get("/3d", () => new Response(renderScene3d({}), { headers: { "Content-Type": "text/html" } }))
|
||||
.get("/health", () => ({ status: "ok" }))
|
||||
.get("/css/tailwind.css", () => Bun.file(join(import.meta.dir, "public/css/tailwind.css")))
|
||||
.get("/js/map.js", () => Bun.file(join(import.meta.dir, "public/js/map.js")))
|
||||
.get("/js/mesh.js", () => Bun.file(join(import.meta.dir, "public/js/mesh.js")))
|
||||
.listen(Number(process.env.PORT ?? 3001));
|
||||
|
||||
console.log(`[frontend] listening on :${app.server?.port}`);
|
||||
|
||||
Reference in New Issue
Block a user