docs(design): 3D terrain with a fixed isometric camera (real Z, 2D sprites preserved) #272

Merged
panda merged 34 commits from design/3d-terrain into main 2026-08-05 19:46:50 +02:00
Collaborator

Summary

Design-only. Proposes rendering the terrain as real 3D geometry under a fixed orthographic isometric camera, keeping characters/statics as 2D UO sprites billboarded into that world (the Diablo II Resurrected pattern).

Why, in the owner's words: today we simulate Z; in 3D the Z is real. Every recurring failure of recent cycles — cliffs reading as ramps, iso "diamonds"/right angles, terrain unable to occlude the player, roads that must carve the heightfield, the character "climbing like Messner" — is scaffolding to fake verticality inside a 2-D projection.

The invariant that makes this an evolution, not a new game (owner): "alla fine sono asset applicati a celle; pure sul 3D il concetto è identico." The content model is untouched — one terrain per cell, sparse statics, authored Z. A cell was a screen diamond; now it is a quad in space. Zero conversion of the authored world, tiledata, art or statics.

Kept (an earlier draft over-stated a "big deletion"; the owner pushed back and was right):

  • the mesh machinery (chunking, windowing, buffers) — only the projection moves to the GPU;
  • the display-Z smoothing, which matters MORE in 3D: real lighting is merciless on a raw heightfield's facets (a Minecraft look), so smoothing stays and now also feeds averaged vertex normals;
  • the SDF biome blend + atlas, the UO art and its 5 facings, the server, the map format.

Removed: explicit cliff-wall geometry (already reverted — it produced the diamonds) and the manual anti-occlusion overlay (the depth buffer replaces it).

Owner decisions locked: Z scale raised for imposing mountains (display-only, so walkability is unaffected; exact value picked by eye in the spike via ×4/×8/×12/×16); MapEditor posture B in phases — the 3D terrain is a shared component from the start, the editor's 3D view lands right after the spike; multi-level (stacked surfaces) is Phase 2 with a seam left for it.

Gated by a de-risk spike — a real asterra chunk as a 3D mesh, ortho iso camera, one billboard, depth on. Machine gate: flat Z0 must project pixel-identical to today. Owner gates: does it still look like UO, and which Z scale.

How it was tested

N/A — design document only. check-doc-refs clean.

Checklist

  • Design-first, spike-gated; no implementation started
  • Multi-platform preserved (MonoGame 3D on Win/macOS; SM3 + committed .xnb pattern)
  • Server / map format / content model unchanged; display-only
  • Invariants Check included in the spec
  • Implementation — NOT started; the spike is the next buildable step

Supersedes the rendering half of #268 (pillar 1 retired, pillar 3 fulfilled natively).

## Summary Design-only. Proposes rendering the **terrain as real 3D geometry** under a **fixed orthographic isometric camera**, keeping characters/statics as **2D UO sprites** billboarded into that world (the Diablo II Resurrected pattern). **Why, in the owner's words:** *today we simulate Z; in 3D the Z is real.* Every recurring failure of recent cycles — cliffs reading as ramps, iso "diamonds"/right angles, terrain unable to occlude the player, roads that must carve the heightfield, the character "climbing like Messner" — is scaffolding to fake verticality inside a 2-D projection. **The invariant that makes this an evolution, not a new game** (owner): *"alla fine sono asset applicati a celle; pure sul 3D il concetto è identico."* The content model is untouched — one terrain per cell, sparse statics, authored Z. A cell was a screen diamond; now it is a quad in space. **Zero conversion** of the authored world, tiledata, art or statics. **Kept (an earlier draft over-stated a "big deletion"; the owner pushed back and was right):** - the mesh machinery (chunking, windowing, buffers) — only the projection moves to the GPU; - **the display-Z smoothing, which matters MORE in 3D**: real lighting is merciless on a raw heightfield's facets (a Minecraft look), so smoothing stays and now also feeds **averaged vertex normals**; - the SDF biome blend + atlas, the UO art and its 5 facings, the server, the map format. **Removed:** explicit cliff-wall geometry (already reverted — it produced the diamonds) and the manual anti-occlusion overlay (the depth buffer replaces it). **Owner decisions locked:** Z scale **raised** for imposing mountains (display-only, so walkability is unaffected; exact value picked by eye in the spike via ×4/×8/×12/×16); MapEditor posture **B in phases** — the 3D terrain is a **shared component from the start**, the editor's 3D view lands right after the spike; multi-level (stacked surfaces) is **Phase 2** with a seam left for it. **Gated by a de-risk spike** — a real asterra chunk as a 3D mesh, ortho iso camera, one billboard, depth on. Machine gate: flat Z0 must project **pixel-identical** to today. Owner gates: does it still look like UO, and which Z scale. ## How it was tested N/A — design document only. `check-doc-refs` clean. ## Checklist - [x] Design-first, spike-gated; no implementation started - [x] Multi-platform preserved (MonoGame 3D on Win/macOS; SM3 + committed `.xnb` pattern) - [x] Server / map format / content model unchanged; display-only - [x] Invariants Check included in the spec - [ ] Implementation — NOT started; the spike is the next buildable step Supersedes the rendering half of #268 (pillar 1 retired, pillar 3 fulfilled natively).
docs(design): 3D terrain with a fixed isometric camera — real Z instead of simulated, 2D sprites preserved
All checks were successful
ci / Lua content lint (pull_request) Successful in 13s
ci / Lint & Test (pull_request) Successful in 4m54s
dbfbd4d65d
docs(plan): 3D terrain de-risk spike — shared camera + mesh maths, real map, Z-scale gate
All checks were successful
ci / Lua content lint (pull_request) Successful in 11s
ci / Lint & Test (pull_request) Successful in 5m41s
171001d2f5
docs(design): 3D terrain gate PASSED — real verticality confirmed, owner picks Z scale x16
Some checks failed
ci / Lua content lint (pull_request) Successful in 9s
ci / Lint & Test (pull_request) Failing after 1m9s
d1800b0c43
spike(render): 3D terrain textured with the real biome art from the asset pack
Some checks failed
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Failing after 1m11s
04ef006d19
docs(design): enumerate the existing visual refinements as a Phase 1 carry-over checklist
Some checks failed
ci / Lua content lint (pull_request) Successful in 13s
ci / Lint & Test (pull_request) Failing after 1m16s
9bcbb5ead5
feat(render): 3D terrain in the client — unified projection at Z scale 16, real-normal lighting, height-aware picking
Some checks failed
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Failing after 1m12s
450f08818d
fix(render): ray-march tile picking + movement test suite over procedural terrain with peaks
Some checks failed
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Failing after 1m14s
51c79fee37
docs(design): real Z exposes a walkability gap — steepness/gradient, not just per-step height
Some checks failed
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Failing after 1m16s
b0c5e9be00
feat(movement): sustained-climb budget — a route's steepness is limited, not just one step
Some checks failed
ci / Lua content lint (pull_request) Successful in 13s
ci / Lint & Test (pull_request) Failing after 1m7s
dcbc8c3758
feat(render): entities test the terrain depth buffer — a cliff now hides what is behind it
Some checks failed
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Failing after 1m5s
dd290df964
fix(roads): grade roads to the sustainable gradient, not the single-step limit — they were unwalkable by construction
All checks were successful
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Successful in 5m9s
8be3067764
feat(editor): DEBUG automation channel — script the real editing tools reproducibly; rebuild the test mountain and its spiral road
All checks were successful
ci / Lua content lint (pull_request) Successful in 17s
ci / Lint & Test (pull_request) Successful in 4m50s
f19032b58c
fix(editor): densify the road stroke — a fast drag painted disconnected pits instead of a road
All checks were successful
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Successful in 4m44s
a2d99472ec
docs(design): landform editor — parametric terrain tools, rotatable/switchable views, editable traces
Some checks failed
ci / Lua content lint (pull_request) Successful in 13s
ci / Lint & Test (pull_request) Has been cancelled
74d1575e28
docs(plan): landform editor — picking-first, then views, landforms, traces, naturalisation
All checks were successful
ci / Lua content lint (pull_request) Successful in 31s
ci / Lint & Test (pull_request) Successful in 5m21s
650a69e9e5
feat(editor): MeshPicker — ray-cast picking correct at any camera rotation
All checks were successful
ci / Lua content lint (pull_request) Successful in 18s
ci / Lint & Test (pull_request) Successful in 6m33s
d7d33b9a31
feat(editor): switchable top-down / orbiting 3D view, with the height window read in bulk
All checks were successful
ci / Lua content lint (pull_request) Successful in 11s
ci / Lint & Test (pull_request) Successful in 4m46s
8c5379763a
perf(editor): pick by testing only the cells the view ray crosses — exact, and bounded by the ray not the viewport
All checks were successful
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Successful in 4m55s
ba1c1418e0
perf(editor): keep the terrain mesh on the GPU and stop rebuilding it while orbiting
All checks were successful
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Successful in 5m21s
5756508f9f
feat(editor): roads become re-bakeable Traces, shared by the GUI and the automation channel
All checks were successful
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Successful in 4m51s
699cb57f97
feat(editor): warn on exit with unsaved chunks instead of discarding them
All checks were successful
ci / Lua content lint (pull_request) Successful in 10s
ci / Lint & Test (pull_request) Successful in 6m32s
1e09538dc9
fix(editor): landform is one placement per click, with a live preview of footprint and profile
Some checks failed
ci / Lua content lint (pull_request) Successful in 20s
ci / Lint & Test (pull_request) Has been cancelled
8f36192daa
feat(editor): --tool flag for scripted capture; ASCII-safe UI strings (ImGui has no em-dash glyph)
All checks were successful
ci / Lua content lint (pull_request) Successful in 14s
ci / Lint & Test (pull_request) Successful in 5m7s
761dda86ce
panda merged commit cc8f2a0b0b into main 2026-08-05 19:46:50 +02:00
panda deleted branch design/3d-terrain 2026-08-05 19:46:50 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!272
No description provided.