Is your feature request related to a problem? Please describe.
#428 (PR #468) wired Jolt HeightFieldShape collision into single-tile terrain, built once at OnPhysics3DStart from the terrain's CPU height field. Two cases are deliberately out of scope there and remain gaps:
- Streamed terrain (
TerrainComponent::m_StreamingEnabled / TerrainStreamer) gets no collision — BuildTerrainCollisionBody early-returns for streaming terrains. Tiles add/remove their visual mesh as the camera moves, but no collision body is created/destroyed in step, so bodies fall through streamed worlds.
- Sculpt / erosion edits (
TerrainBrush / TerrainErosion, which mutate TerrainData::m_Heights and report a DirtyRegion) update the GPU heightmap and chunk meshes but not the collision shape — the static heightfield body keeps the pre-edit surface.
Describe the solution you'd like
- Streaming: create/destroy a static
HeightFieldShape body per loaded tile, keyed on tile grid coords, hooked into the TerrainStreamer load (ProcessCompletedLoads → BuildGPUResources) and unload/evict (EvictOverBudget) lifecycle. Each tile's body uses its WorldOrigin (gridX·tileWorldSize, 0, gridZ·tileWorldSize) + per-tile TerrainData. Reuse JoltShapes::CreateTerrainHeightFieldShape + JoltScene::CreateTerrainBody/DestroyTerrainBody (already keyed by UUID — may need a per-tile key scheme).
- Sculpt/erosion: on a
DirtyRegion edit, update the affected collision region via JPH::HeightFieldShape::SetHeights(inX, inY, sizeX, sizeY, …). Note Jolt requires the region to be block-aligned (inX % mBlockSize == 0), so snap the dirty rect outward to the block grid. Debounce so a brush drag doesn't rebuild every frame.
Acceptance criteria
- A character controller / vehicle rests on and traverses streamed terrain without falling through; collision tiles add/remove in step with the visual load/unload.
- After a sculpt or erosion edit, a body dropped on the edited region rests on the new surface (collision matches the edited mesh).
Additional context
Foundation: #428 / PR #468. Conventions (scale/origin/padding, block-alignment for partial updates) are documented in that PR's JoltShapes::CreateTerrainHeightFieldShape and the JoltScene terrain-body lifecycle.
Score
capability: 5
craft: 3
stability: 3
decay: 1
effort: 5
confidence: 0.8
learning: 2
fun: 3
kano: table-stakes
blocked_by: []
blocks: []
Rated per issue-scoring · score = confidence × (capability + craft + stability + decay) / effort, derived by the picker.
Is your feature request related to a problem? Please describe.
#428 (PR #468) wired Jolt
HeightFieldShapecollision into single-tile terrain, built once atOnPhysics3DStartfrom the terrain's CPU height field. Two cases are deliberately out of scope there and remain gaps:TerrainComponent::m_StreamingEnabled/TerrainStreamer) gets no collision —BuildTerrainCollisionBodyearly-returns for streaming terrains. Tiles add/remove their visual mesh as the camera moves, but no collision body is created/destroyed in step, so bodies fall through streamed worlds.TerrainBrush/TerrainErosion, which mutateTerrainData::m_Heightsand report aDirtyRegion) update the GPU heightmap and chunk meshes but not the collision shape — the static heightfield body keeps the pre-edit surface.Describe the solution you'd like
HeightFieldShapebody per loaded tile, keyed on tile grid coords, hooked into theTerrainStreamerload (ProcessCompletedLoads→BuildGPUResources) and unload/evict (EvictOverBudget) lifecycle. Each tile's body uses itsWorldOrigin(gridX·tileWorldSize, 0, gridZ·tileWorldSize) + per-tileTerrainData. ReuseJoltShapes::CreateTerrainHeightFieldShape+JoltScene::CreateTerrainBody/DestroyTerrainBody(already keyed by UUID — may need a per-tile key scheme).DirtyRegionedit, update the affected collision region viaJPH::HeightFieldShape::SetHeights(inX, inY, sizeX, sizeY, …). Note Jolt requires the region to be block-aligned (inX % mBlockSize == 0), so snap the dirty rect outward to the block grid. Debounce so a brush drag doesn't rebuild every frame.Acceptance criteria
Additional context
Foundation: #428 / PR #468. Conventions (scale/origin/padding, block-alignment for partial updates) are documented in that PR's
JoltShapes::CreateTerrainHeightFieldShapeand the JoltScene terrain-body lifecycle.Score
Rated per issue-scoring · score = confidence × (capability + craft + stability + decay) / effort, derived by the picker.