feat: multi-region ceilings (tray ceilings, soffits, stepped ceilings)#247
Open
b9llach wants to merge 1 commit intopascalorg:mainfrom
Open
feat: multi-region ceilings (tray ceilings, soffits, stepped ceilings)#247b9llach wants to merge 1 commit intopascalorg:mainfrom
b9llach wants to merge 1 commit intopascalorg:mainfrom
Conversation
Adds support for ceiling regions — sub-areas of a ceiling at a
different height from the main plane. Used to model tray ceilings
(inner region raised above the main ceiling, creating a recessed
well), soffits (inner region dropped below, creating a lowered
panel), and multi-height rooms (e.g. a vaulted wing).
Schema:
- New `CeilingRegion` type: `{ polygon, height, holes }`.
- `CeilingNode.regions` field: `z.array(CeilingRegion).default([])`.
- Backward compatible — existing scenes without regions are unchanged.
Rendering (ceiling-system.tsx):
- Each region polygon is subtracted from the main ceiling shape as a
hole, then drawn as its own flat `ShapeGeometry` at the region's
height. A vertical skirt strip connects the region to the main
ceiling plane so tray wells and soffit drops render as connected 3D
shapes instead of disconnected floating planes. All sub-geometries
(main plane + region planes + skirts) are merged into one
BufferGeometry so the mesh stays single-draw-call.
- Vertex color attribute darkens skirt vertices (~62% brightness) so
tray wells read as shaded under the unlit MeshBasicNodeMaterial
shader. Ceiling renderer wires this via TSL colorNode
(`vec3(baseColor).mul(vec3(attribute('color')))`).
- Hole winding auto-correction: holes whose signed area matches the
outer contour are reversed before triangulation.
Level stacking (level-utils.ts):
- `getLevelHeight` now scans `ceiling.regions` and picks the tallest
surface. An upper level's floor clears the tray automatically.
Wall cavity fill (wall-system.tsx):
- Walls on a level extend to fill the structural cavity if a ceiling
region pushes the effective level height above the main ceiling.
Editor UI (ceiling-panel.tsx + ceiling-region-editor.tsx):
- "Regions" panel section with Add / Edit / Delete / Done + per-region
height slider. Mirrors the existing "Holes" section pattern.
- `CeilingRegionEditor` tool using the generic `PolygonEditor` with
amber handles at the region's own height.
- `editingRegion` state in `useEditor`, parallel to `editingHole`.
Utility:
- `packages/core/src/lib/polygon-uv.ts` — `dominantPolygonAngle` and
`setAxisAlignedPlanarUVs` for axis-aligned UV mapping on slab and
ceiling polygons.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds ceiling regions — sub-areas of a ceiling at a different height from the main plane — to model tray ceilings, soffits, and multi-height rooms. Each region is a polygon with its own height, rendered as a connected 3D shape with vertical skirt walls and vertex-color shading. The feature includes the full stack: schema, rendering system, level-stacking fix, wall-cavity fill, and editor UI.
Schema
New `CeilingRegion` type (`{ polygon, height, holes }`) and `CeilingNode.regions` field (`z.array(CeilingRegion).default([])`). Backward compatible — existing scenes without regions are unchanged.
Rendering
Each region polygon is subtracted from the main ceiling as a hole, then drawn as its own flat `ShapeGeometry` at the region's height. A vertical skirt strip connects the region plane to the main ceiling plane so tray wells and soffit drops render as connected 3D shapes instead of disconnected floating planes. Skirt vertices are darkened (~62% brightness) via a `color` vertex attribute + TSL `colorNode` multiplication, giving a visual depth cue under the unlit `MeshBasicNodeMaterial` shader.
Hole winding auto-correction ensures the triangulator cuts correctly regardless of whether the region polygon winds the same as or opposite to the outer ceiling contour.
Level stacking
`getLevelHeight` now scans `ceiling.regions` and picks the tallest surface (main ceiling or any region). When a tray region extends above the main ceiling, the upper level's floor automatically clears the tray instead of sitting at the main ceiling height and z-fighting with the region.
Wall cavity fill
Walls on a level extend to fill the structural cavity between the ceiling and the next floor's slab. The wall system reads the effective level height (including region heights) and inflates the wall's rendered height to match, closing the visual gap that would otherwise appear in orbit view between floors.
Editor UI
A "Regions" section in the ceiling panel mirrors the existing "Holes" section: Add / Edit / Delete / Done buttons + a per-region height slider. `CeilingRegionEditor` uses the generic `PolygonEditor` component with amber handles positioned at the region's own height. `editingRegion` state in `useEditor` is parallel to `editingHole` — a ceiling can't be in both edit states at once.
Utility
`packages/core/src/lib/polygon-uv.ts` — `dominantPolygonAngle` and `setAxisAlignedPlanarUVs` for axis-aligned UV mapping on slab and ceiling polygons. Used by both the ceiling system and the slab system.
How to test
Checklist