diff --git a/Client/README.md b/Client/README.md index 6bdb2f1..02b9515 100644 --- a/Client/README.md +++ b/Client/README.md @@ -17,6 +17,21 @@ A `MeshInstance3D` created per chunk by the server, which then calls `RenderChun placed by their footprint and carry their full height internally. - **Backface rendering.** `CullMode` is disabled, so the world is still visible from underneath or from inside terrain. +- **Water at rest** (task 13). `BuildWaterSurface` adds a second `MeshInstance3D` as a child, a flat + sheet at each cell's water level, from the per-column water data the server read out of the + blueprint. Skipped entirely for chunks with no water. + + **Why a separate mesh rather than a water block.** The terrain is a Marching-Cubes iso-surface + over the density field. Putting water into that field would not lay a sheet on top of the seabed — + it would move the iso-surface, fusing the sea into the terrain as if it were solid ground. A + second surface is the only way water can sit at *its* level independent of the ground beneath it. + + That also makes translucency nearly free: a distinct `MeshInstance3D` carries its own + `StandardMaterial3D`, so alpha is one flag and Godot sorts transparent surfaces after opaque ones + itself. Colour and alpha both ramp with depth (shallow teal and clearer → deep navy and near + opaque), so the shelved coast stays readable. + + Water is **flat and static** — no waves, no displacement, no animation. Those are Phase C2+. ## Notes diff --git a/Core/Scripts/README.md b/Core/Scripts/README.md index d645894..d0187ef 100644 --- a/Core/Scripts/README.md +++ b/Core/Scripts/README.md @@ -11,7 +11,11 @@ never track live game events — who is online, which chunks are loaded, what ti ### Voxel materials - **`BlockData.cs`** — struct describing one block type (ID, name, IsSolid, BaseColor). - **`BlockRegistry.cs`** — the byte-ID master list (`AIR` 0, `BEDROCK`, `STONE`, `DIRT`, `SAND`, the - three grasses, `SNOW`, `WASTELAND_DIRT`, `ASPHALT`) with a safe `GetBlock` lookup. + three grasses, `SNOW`, `WASTELAND_DIRT`, `ASPHALT`, `WATER`) with a safe `GetBlock` lookup. + **Block IDs are never serialized** — the blueprint stores heights, biome ordinals and water data, + never block IDs, and chunks are not persisted — so appending to this table is wire-safe. + `WATER` is a registry identity only: it is not written into `ChunkData.BlockIDs`, because water is + drawn as its own surface rather than as part of the terrain iso-surface (see `Client/README.md`). - **`BiomePalette.cs`** — decides which material sits where, given biome, depth, and whether the column is roadbed. Two paths on purpose: an **integer** classification that decides what is stored in each voxel, and a **float-depth** version used for rendering that returns the two materials @@ -43,11 +47,17 @@ rendering. flag, and the optional water-bodies data: `WaterBodyIds`, `WaterBodies` table, `WaterSurfaceQ`). Dispatches on the first byte: v2 tagged-section files get validation (version gate, size bounds, section-length and ordinal range checks); legacy v1 files still load, intact, with a - deprecation warning. Nothing at runtime consumes the water data yet. + deprecation warning. **The water sections are consumed at runtime since task 13** — the server + reads them per column and the client draws the result (see `Server/README.md`). - **`ChunkData.cs`** — one chunk's density and block-ID fields, `+1` padded on every axis so the - mesher can reach into the neighbouring chunk, plus the per-column data the renderer needs. + mesher can reach into the neighbouring chunk, plus the per-column data the renderer needs — + including `WaterSurfaceY` (world Y of the water surface, or `Constants.NO_WATER`), `WaterDepthM` + (true depth from blueprint heights) and `HasAnyWater`. - **`Constants.cs`** — chunk dimensions, `ISO_LEVEL`, `VOXEL_SCALE`, and the visual/road tunables - (material blend band; per-tier road width, shoulder, grade smoothing and surface). + (material blend band; per-tier road width, shoulder, grade smoothing and surface), plus the + water-at-rest tunables: `HEIGHT_SCALE` (the one raw-height→metres mapping, shared by the terrain + surface and the water sheet so they cannot drift apart), `NO_WATER`, and the depth-shading + colour/alpha ramp. ### Maths - **`MarchingCubes.cs`** — density field → `ArrayMesh`, with analytical normals and deterministic diff --git a/Server/README.md b/Server/README.md index 789c64f..2caac8b 100644 --- a/Server/README.md +++ b/Server/README.md @@ -27,6 +27,15 @@ vector ends up parallel to the view direction, so camera roll is undefined and G - **Road culling first.** Only the road segments whose bounding box reaches this chunk are kept, each tagged with its `RoadTier`. The padding is derived from the widest shoulder any tier has plus a margin, so widening a road cannot silently truncate it at chunk edges. +- **Water per column** (task 13) — the blueprint is the **authority** on where water is; the server + only reads it. `WBID` decides presence (it is the water stage's own classification output, the + same set the biome grid's Ocean/Lake pixels form by construction), `WSRF` gives the surface level + per pixel, and the `WBTB` body table is the fallback when a column is flagged wet but carries the + `WSRF` no-water sentinel. A body the table does not know leaves the column **dry** rather than + guessing a level. The level is scaled by the same `HEIGHT_SCALE` as the terrain, so the sheet and + the seabed cannot drift apart. Depth for shading is taken from **blueprint** heights, not rendered + geometry — the terrain render clamps its floor at `Y = 2`, which would otherwise flatten every + deep-ocean column to one value. Each run logs what it drew (`[Server] Water at rest: …`). - **Surface height per column** (`GetExactSurface`) — the blueprint height scaled into the chunk's usable vertical band, then modified by any road carving. - **Density per voxel** — `(y − surfaceY)` normalised by the local slope, giving a signed distance to