Phase 7 start checkpoint
This commit is contained in:
@@ -5786,33 +5786,167 @@ boarding-standoff snap on NPC 1099511627776 and no rotation.
|
||||
stats and persistence layers exist; architecture can be
|
||||
designed earlier).
|
||||
|
||||
### Phase 7 — CellGrid stair generation - before interiors
|
||||
### Phase 7 — CellGrid stair generation — before interiors
|
||||
|
||||
Multi-storey CellGrid buildings (`height` > 1) generate stacked floors
|
||||
with no connection between them — interiors above ground level are
|
||||
unreachable. Add stairs to the CellGrid generator (engine-level, not
|
||||
taxi-specific):
|
||||
**Goal.** Multi-storey CellGrid buildings (`height` > 1) currently
|
||||
generate stacked floors with no connection between them, so interiors
|
||||
above ground level are unreachable. Add stairs to the CellGrid
|
||||
generator — **engine-level, not taxi-specific** — so that both the
|
||||
player (Jolt character) and NPCs (Recast navmesh) can travel between
|
||||
every floor. Phase 8's interior generator consumes the result.
|
||||
|
||||
- Stair cell: a cell flag (like the existing door/window flags) marking
|
||||
a stairwell; the generator cuts the matching opening in the
|
||||
floor/ceiling above and emits a stair mesh (steps sized within the
|
||||
Jolt character's and Recast's climb limits) plus walkable colliders.
|
||||
- Placement rules: stairwell position comes from the room layout
|
||||
(RoomLayoutSystem integration) or an explicit cell flag in
|
||||
hand-authored grids; a stairwell column stacks through all floors.
|
||||
- Navmesh: stairs rasterize as walkable (Recast step/slope limits), so
|
||||
NPCs can path between floors; verify doorway-area costs and door
|
||||
obstacles still behave.
|
||||
- should support stairwells and explicit floor connections between rooms where a room has stair in it which connects to above location. Like single-floor stairwell. Floors and ceilings are removed for the stair to pass. The space between floors should be hidden by geometry to avoid gaps.
|
||||
- should support exterior stairs outside walls (like in many motels)
|
||||
- should support procedural material the same as walls/floors, using squares for walls and floors by default, depending on surface.
|
||||
- Editor + serialization + Lua binding, per the component rules
|
||||
(serialized flag, Cell Grid editor toggle, `cellgrid_door_test`-style
|
||||
headless coverage).
|
||||
- Headless: multi-floor grid with a stairwell — character walks from
|
||||
ground floor to the top floor (physics), navmesh query finds a
|
||||
ground->top path; grids without stair flags are unchanged.
|
||||
- from DSL and scene components point of view, the easiest way to create stairwell would be to create a room with type of stairwell. However sometimes for lobby rooms we want a large stair which leads to next floor, like in some hotels, theatres, administrative buildings... Needs research.
|
||||
**Status:** planned (decomposed 2026-10-30); nothing implemented yet.
|
||||
|
||||
**How to read this phase.** 7.1 is the vertical slice: one hand-
|
||||
authored grid, one stairwell, real geometry. 7.2 proves traversal.
|
||||
7.3 adds the authoring paths (rooms, DSL, editor, Lua). 7.4 and 7.5
|
||||
are independent extensions. Every slice ends buildable with headless
|
||||
verification, and every slice keeps the global invariant:
|
||||
|
||||
> **Invariant:** grids without stair flags produce bit-identical
|
||||
> geometry to what they produce today.
|
||||
|
||||
**What the code already gives us (verified 2026-10-30):**
|
||||
|
||||
- `CellFlags` bits 0-25 are used (`components/CellGrid.hpp`); bits
|
||||
26-63 are free. Cell flags serialize as a raw `uint64` per cell, so
|
||||
a new flag needs **no JSON schema change** and old scenes keep
|
||||
loading. `LayoutLib::PlanFlags` is bit-identical to `CellFlags`
|
||||
(static_asserted in `TownGenSystem.cpp`) — a new bit must be
|
||||
mirrored there with a new assert.
|
||||
- Openings are free: `buildFloorsAndCeilings` only emits a floor/
|
||||
ceiling plane for cells carrying the `Floor`/`Ceiling` flag, so
|
||||
clearing those flags on stair cells cuts the hole with no special
|
||||
mesh surgery. Roofs are separate (`RoofComponent` children).
|
||||
- Colliders follow the mesh lists in `buildPhysicsColliders` — a new
|
||||
stair mesh added there gets its static collider automatically.
|
||||
- Recast limits (`NavMeshComponent` defaults): `agentMaxClimb` 1.0 m
|
||||
(5 voxels at `cellHeight` 0.2), `agentMaxSlope` 20 deg,
|
||||
`agentRadius` 0.5 m. Stepped treads rasterize walkable; a smooth
|
||||
ramp does **not** help (4 m of rise at 20 deg needs an 11 m run).
|
||||
- Jolt character: no explicit step-height knob (supporting-volume
|
||||
plane at -0.2 m). The proven climbing envelope is the existing
|
||||
entrance stairs (`TownGenSystem::createStairs`: rise 0.18 / tread
|
||||
0.30 / width 1.4 m boxes with box colliders). Step size for
|
||||
interior stairs starts from those numbers and is tuned empirically
|
||||
in 7.2 — do not assume Recast's 1.0 m climb means the character can
|
||||
climb 1.0 m steps.
|
||||
- Navmesh geometry collection drops mesh names containing
|
||||
"ceiling"/"frame"/"furniture" (`isNavMeshGeometry`) — stair meshes
|
||||
must avoid those substrings.
|
||||
- Default cell is 4 x 4 m with `cellHeight` 4 m; the floor surface
|
||||
sits at `floorSurfaceY()` = 0.2 m above the cell base, so a
|
||||
floor-to-floor connection rises exactly `cellHeight`.
|
||||
|
||||
**Shared geometry contract (all slices):**
|
||||
|
||||
- A **stair connection** between level y and y+1 occupies one or more
|
||||
cells at the same (x, z) on both levels: the generator clears
|
||||
`Ceiling` at level y and `Floor` at level y+1 on those cells and
|
||||
fills the opening with a stepped stair mesh plus walkable
|
||||
colliders. A **stairwell column** chains connections upward through
|
||||
consecutive floors at the same (x, z).
|
||||
- Steps: tread 0.30 m, rise 0.18-0.25 m (exact value settled in 7.2),
|
||||
flight width >= 1.2 m (twice the Recast agent radius plus margin).
|
||||
- One 4 x 4 m cell fits a **dogleg** (two flights + mid-landing);
|
||||
a **straight flight** needs two or more cells in a row. The
|
||||
generator picks the layout from the stair cell run's shape.
|
||||
- The space between floors around the opening is closed by geometry
|
||||
(shaft sides and top cap): no visible void, no gaps at slab edges.
|
||||
How the top cap interacts with the per-row-run roofs of cut
|
||||
footprints is settled in 7.1.
|
||||
- Stairs use the grid's procedural material like walls/floors:
|
||||
treads default to the floor rect, shaft sides to the wall rect
|
||||
(square UV mapping per surface), with a serialized `stairRectName`
|
||||
override.
|
||||
|
||||
#### Phase 7.1 — Core stairwell cells (vertical slice)
|
||||
|
||||
Hand-authored grids only; no DSL, no RoomLayoutSystem yet.
|
||||
|
||||
- New `CellFlags::StairWell` bit (mirrored `PlanFlags` bit + static
|
||||
assert). A stair cell marks "a stair passes through here"; the
|
||||
column/run shape comes from the flagged cells themselves.
|
||||
- `buildCellGrid` pass: cut the openings per the geometry contract,
|
||||
emit straight-flight and dogleg stair meshes + shaft closure, add
|
||||
them to the collider lists, apply the procedural-material UV
|
||||
mapping. Serialized `stairRectName` field (empty = floor/wall
|
||||
rect defaults).
|
||||
- Serialization: flags ride the existing raw-uint64 cell format;
|
||||
`stairRectName` round-trips like the other rect names.
|
||||
|
||||
Verify:
|
||||
- `cellgrid_door_test`-style case: flag + `stairRectName` round trip,
|
||||
old scenes load with defaults.
|
||||
- New terrain-tests step (`TERRAIN_TEST_FILTER=cellGridStairs`):
|
||||
multi-floor grid with a stairwell builds openings, stair mesh and
|
||||
colliders; a grid without stair flags is unchanged.
|
||||
|
||||
#### Phase 7.2 — Traversal acceptance (physics + navmesh)
|
||||
|
||||
- Character physics: tune rise/tread inside the proven envelope so
|
||||
the Jolt character climbs without snagging; verify headroom under
|
||||
landings and at the top opening.
|
||||
- Navmesh: stairs rasterize walkable (per the Recast limits above);
|
||||
doorway-area costs and locked-door obstacles keep behaving (the
|
||||
`navMeshDoors` step stays green).
|
||||
|
||||
Verify:
|
||||
- Headless: a character walks from the ground floor to the top floor
|
||||
over the stairs (physics), and a navmesh query finds a
|
||||
ground-to-top path. No-stair grids: no path between floors, as
|
||||
today.
|
||||
|
||||
#### Phase 7.3 — Authoring paths (rooms, DSL, editor, Lua)
|
||||
|
||||
- **RoomLayoutSystem:** a room of type `stairwell` marks its cells;
|
||||
single-floor stairwells connect a room to the level directly above
|
||||
it (floors/ceilings removed for the stair to pass, per the shared
|
||||
contract). A stairwell room column stacks through all floors it
|
||||
spans. `processRoom` must not re-stamp `Floor`/`Ceiling` over the
|
||||
openings it just cut.
|
||||
- **Layout DSL:** `(room ... :type stairwell)` records the same
|
||||
cells in `BuildingPlan` (rooms-first claims skip the opening
|
||||
flags; filled-shell mode stays metadata + flags). `fillBuildingCells`
|
||||
needs no change — flags flow through verbatim.
|
||||
- **Editor:** Cell Grid editor per-cell stair toggle (next to the
|
||||
door/window toggles) plus the `stairRectName` widget.
|
||||
- **Lua:** stair flag/rect exposed per the component rules.
|
||||
- Docs (`editScene/AGENTS.md`, this file) updated with the slice.
|
||||
|
||||
Verify:
|
||||
- DSL grammar probes in `road_geometry_overlap_test`; Lua round trip
|
||||
in `component_lua_test`; a DSL-authored two-storey stairwell
|
||||
building passes the 7.1/7.2 checks.
|
||||
|
||||
#### Phase 7.4 — Exterior stairs (motel-style)
|
||||
|
||||
- Stairs outside the shell walls: exterior corridors/galleries on
|
||||
upper floors reached by an external flight (as in many motels).
|
||||
Reuses the 7.1 step geometry and materials; placement is driven by
|
||||
authored cells/DSL, not by a town-wide rule.
|
||||
|
||||
Verify:
|
||||
- Headless: character climbs from terrain level to the upper
|
||||
gallery and enters through its exterior door; navmesh connects
|
||||
terrain to the gallery.
|
||||
|
||||
#### Phase 7.5 — Grand / lobby stairs (research, then implement)
|
||||
|
||||
Open design question carried over from the original phase notes:
|
||||
typing a room `stairwell` is the easiest DSL/component authoring
|
||||
path, but lobbies of hotels, theatres and administrative buildings
|
||||
want a **large stair inside an ordinary room** — wide flights,
|
||||
possibly curved or branching, not a utilitarian shaft. Research
|
||||
first: how a wide multi-cell flight is authored (room option vs.
|
||||
dedicated cells), whether the 7.1 straight/dogleg layouts suffice
|
||||
when scaled up, and what railing/balustrade geometry is needed.
|
||||
Only then implement.
|
||||
|
||||
**Explicitly out of scope for Phase 7:** interior scene generation
|
||||
and door wiring (Phase 8), spiral stairs, elevators, and town-wide
|
||||
rules for where stairwells go (layouts decide; default layouts get
|
||||
stairwells when Phase 8 makes upper floors enterable).
|
||||
|
||||
### Phase 8 — Enterable buildings (on-the-fly interiors)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user