Repository navigation
Conversation
A roof now cuts everything in its building at its underside (the bottom of the deck): - walls get one extra CSG subtraction of a heightfield solid above the roof underside, separate from the opening union, so their top follows the slope; - every other mesh of a level (posts, furniture, fences, pipes, ceilings) is clipped geometrically against convex prisms above the underside, whatever its material; roofs and the nodes they host are left alone; - a column under a roof reaches its underside, measured from its slab lift. The underside planes come from the same faces the roof renders (`getRoofSegmentVolumeFaces`, extracted from the `getVol` closure, and `getRoofSegmentUndersidePolygons`, honouring segment trim). A roof edit only rebuilds the walls whose roof cover changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit eadf6de. Configure here.
| const level = elevations.get(levelId) | ||
| if (!levelObject || !level) continue | ||
| const patches = patchesByBuilding.get(level.buildingId) | ||
| if (!patches?.length) continue |
There was a problem hiding this comment.
Clipped meshes never restore
High Severity
runRoofClipFrame returns as soon as no building has underside patches, and skips a level when that building’s patch list is empty. Those paths never walk existing meshes, so a deleted or emptied roof leaves furniture, pipes, fences and ceilings permanently cut until remount.
Reviewed by Cursor Bugbot for commit eadf6de. Configure here.
| const regions = buildingRegions.map((region) => | ||
| region.map((plane) => plane.clone().applyMatrix4(toLocal)), | ||
| ) | ||
| clipped = clipGeometryByRegions(source, regions) |
There was a problem hiding this comment.
Lower roofs clip storeys above
High Severity
Mesh clipping treats every roof in the building as an unbounded upward prism and, once any patch AABB hits, subtracts all of them. A mesh that sits entirely above a lower roof (room over a porch, split-level wing, garage with a storey above) is removed inside that roof’s outline instead of being left alone. Walls already skip roofs below their base via capPatchAt; this path does not.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit eadf6de. Configure here.


What does this PR do?
Walls, posts and other meshes ignore the roof today: a full-storey wall under a low roof (eaves below the storey height) pokes through the roof and its overhang, and so do posts, furniture or a pipe placed under it. This PR makes a roof cut everything in its building at its underside (the bottom of the deck):
wall-roof-fit.ts), kept separate from the opening union, so the wall top follows the slope with a closed, flat-shaded top. Walls never grow towards a roof.roof-clip.ts), whatever its material or loader. The cut face sits against the deck underside and is not visible. Roofs and the nodes they host (chimneys, skylights) are left alone; skinned and instanced meshes are skipped.getFloorStackedPosition), so posts of a terrace or porch meet the roof.The underside planes come from the same faces the roof renders: the
getVolclosure ingetRoofSegmentBrushesis extracted asgetRoofSegmentVolumeFaces, andgetRoofSegmentUndersidePolygonsreturns the deck-bottom faces clipped by the segment trim (roof-underside.ts). Only 3D geometry changes: plans, stored heights, the spatial grid and the roof elevation that follows wall tops keep reading the storey height. A roof edit rebuilds only the walls whose roof cover changed; a mesh is re-clipped only when its geometry, placement or the building's roofs change.How to test
bun test packages/viewer/src/systems/wall/wall-roof-fit.test.ts packages/viewer/src/systems/roof/roof-clip.test.ts— walls cut by a low roof (full-height, partition and half walls), walls outside a roof untouched, roof edit marks only affected walls, posts reach the underside up or down and from a slab, mesh clipping keeps material groups.bun dev, draw a room with full-height walls, add a shed roof whose eave is below the storey height: the walls follow the roof slope instead of poking through.Screenshots / screen recording
Before/after screenshots will be added in a comment (tested on a real house plan with a split-level shed roof).
Checklist
bun dev(tested in our fork's editor on a production house plan; on this branch: unit tests andtscfor viewer)bun checkto verify)mainbranch🤖 Generated with Claude Code
Note
Medium Risk
Touches core wall CSG and a per-frame mesh clip over the scene graph; incorrect patches or transforms could mis-cut geometry or add frame cost, though invalidation and tests limit blast radius.
Overview
Building content no longer pierces roofs: the viewer derives roof underside patches from the same segment volume data used for roof brushes, then uses them in three paths.
Walls under a roof get an extra CSG subtraction (
wall-roof-fit) so the extruded top follows the sloped underside without changing stored storey height; roof edits mark only walls whose cover signature changed.Other level meshes (furniture, ceilings, etc.) are clipped each frame in
runRoofClipFrameagainst convex regions above those patches; roofs, wall meshes, and skinned/instanced geometry are skipped.Columns override rendered height via
resolveColumnRoofHeight(from slab lift throughgetFloorStackedPosition) so posts meet the underside; taller geometry can still be trimmed by the mesh clip pass.getRoofSegmentVolumeFaces/getRoofSegmentUndersidePolygonscentralize underside planes; tests cover wall fitting, column height, andclipGeometryByRegions.Reviewed by Cursor Bugbot for commit eadf6de. Bugbot is set up for automated code reviews on this repo. Configure here.