Parent
- Program: ENG2 — GoudEngine v2 Rebuild (see the pinned master tracking issue)
- Phase / Milestone: Phase 8 — Capability Gaps (
eng2-p8-capabilities)
- Batch / Group: Batch 8.3 — Big-world, Group B
- Runbook spec:
docs/src/runbook/phases/phase-8.md (committed with the roadmap)
Summary
Add a chunked heightmap terrain component: heightfield-driven mesh generation split into fixed-size chunks, so large terrains render at bounded per-chunk cost and can be culled/streamed chunk-by-chunk.
Architecture Context
Layer: Layer 4 (Engine, libs/graphics/renderer3d/ for mesh generation from heightfield data) with a Layer 3 (Services) component (ecs/components/) describing terrain placement/chunk membership.
Modules/types touched:
goud_engine/src/libs/graphics/renderer3d/terrain.rs (new) — heightfield-to-mesh generation (grid of vertices with height-sampled Y, per-vertex normals), chunked into fixed-size tiles.
goud_engine/src/ecs/components/terrain/ (new) — a TerrainChunk/Heightmap component describing chunk origin, size, and its heightfield data source.
goud_engine/src/ffi/renderer3d/terrain.rs (new) — FFI exports to create a heightmap terrain, query height at a world position, and manage chunk lifecycle.
Boundary constraints (only those that apply):
- Raw GPU calls stay in
libs/graphics/backend/ — chunk mesh upload goes through the existing backend buffer APIs, not a new direct wgpu:: call site.
- FFI exports:
#[no_mangle] extern "C", #[repr(C)], null checks, // SAFETY: comments.
Pattern to follow: The chunking/windowing strategy established by ENG2-P2-11 (chunked/scrollable 3D tilemap-grid primitive) — terrain chunks should reuse that primitive's chunk-loading/unloading and coordinate-to-chunk mapping approach rather than inventing a second chunking scheme for a different large-world use case.
Scope
Acceptance Criteria
Breaking Change & Throne Follow-up
None — additive/internal (new component, new FFI surface).
Blocked By
ENG2-P2-11 (chunked/scrollable 3D tilemap-grid primitive, windowless terrain — this issue's chunk loading/unloading and coordinate-to-chunk mapping must reuse that primitive's windowing strategy rather than building a second, inconsistent chunking scheme).
Files Likely Touched
- New:
goud_engine/src/libs/graphics/renderer3d/terrain.rs, goud_engine/src/ecs/components/terrain/mod.rs, goud_engine/src/ffi/renderer3d/terrain.rs
- Generated: SDK bindings under
sdks/*/ for the new terrain FFI exports
- Modified:
codegen/goud_sdk.schema.json
Agent Notes
- No terrain or heightmap functionality exists in any form today: grep for
heightfield, height_map, and height_data (case-insensitive) across goud_engine/src returns zero matches. The only pre-existing "terrain" hits are incidental: a comment in ecs/components/rigidbody/body_type.rs:46 listing "walls, floors, terrain, static obstacles" as example use cases for a rigidbody type, and a "terrain" string used purely as an example category label in rendering/texture_atlas/atlas.rs:64's doc comment — neither is a real terrain system.
- This is explicitly the big-world capability that depends on
ENG2-P2-11's chunking work landing first: ENG2-P2-11 is described in the roadmap as solving the "windowless terrain" chunking problem generically (the "scrollable 3D tilemap-grid primitive"), and this issue is one concrete consumer of that primitive rather than a second implementation of chunk windowing.
- Watch for confusion with the codebase's existing "LOD" terminology: every current
LOD hit in the tree (libs/graphics/renderer3d/config.rs:80,195,199, core_model_animation/mod.rs:134,195) refers exclusively to animation update-rate LOD (skipping or half-rating skeletal animation evaluation at distance), not geometric mesh LOD or texture LOD. This issue's chunking is a prerequisite for ENG2-P8-11's terrain-specific mesh/texture LOD, which is a distinct, new concept in this codebase.
Verification
cargo check && cargo fmt --all -- --check && cargo clippy -- -D warnings
cargo test
./codegen.sh && git diff --exit-code
Parent
eng2-p8-capabilities)docs/src/runbook/phases/phase-8.md(committed with the roadmap)Summary
Add a chunked heightmap terrain component: heightfield-driven mesh generation split into fixed-size chunks, so large terrains render at bounded per-chunk cost and can be culled/streamed chunk-by-chunk.
Architecture Context
Layer: Layer 4 (Engine,
libs/graphics/renderer3d/for mesh generation from heightfield data) with a Layer 3 (Services) component (ecs/components/) describing terrain placement/chunk membership.Modules/types touched:
goud_engine/src/libs/graphics/renderer3d/terrain.rs(new) — heightfield-to-mesh generation (grid of vertices with height-sampled Y, per-vertex normals), chunked into fixed-size tiles.goud_engine/src/ecs/components/terrain/(new) — aTerrainChunk/Heightmapcomponent describing chunk origin, size, and its heightfield data source.goud_engine/src/ffi/renderer3d/terrain.rs(new) — FFI exports to create a heightmap terrain, query height at a world position, and manage chunk lifecycle.Boundary constraints (only those that apply):
libs/graphics/backend/— chunk mesh upload goes through the existing backend buffer APIs, not a new directwgpu::call site.#[no_mangle] extern "C",#[repr(C)], null checks,// SAFETY:comments.Pattern to follow: The chunking/windowing strategy established by
ENG2-P2-11(chunked/scrollable 3D tilemap-grid primitive) — terrain chunks should reuse that primitive's chunk-loading/unloading and coordinate-to-chunk mapping approach rather than inventing a second chunking scheme for a different large-world use case.Scope
ENG2-P2-11's chunk-loading pattern: chunks load/unload based on camera/view distance, not the whole terrain resident at once..agents/rules/graphics-patterns.mdwith the terrain chunk pattern.Acceptance Criteria
ENG2-P2-11windowing pattern (no full-terrain-resident assumption) verified on a multi-chunk fixture scene.python codegen/validate_coverage.py.cargo check && cargo fmt --all -- --check && cargo clippy -- -D warningsclean;cargo testgreen;./codegen.sh && git diff --exit-code(drift gate)Breaking Change & Throne Follow-up
None — additive/internal (new component, new FFI surface).
Blocked By
ENG2-P2-11 (chunked/scrollable 3D tilemap-grid primitive, windowless terrain — this issue's chunk loading/unloading and coordinate-to-chunk mapping must reuse that primitive's windowing strategy rather than building a second, inconsistent chunking scheme).
Files Likely Touched
goud_engine/src/libs/graphics/renderer3d/terrain.rs,goud_engine/src/ecs/components/terrain/mod.rs,goud_engine/src/ffi/renderer3d/terrain.rssdks/*/for the new terrain FFI exportscodegen/goud_sdk.schema.jsonAgent Notes
heightfield,height_map, andheight_data(case-insensitive) acrossgoud_engine/srcreturns zero matches. The only pre-existing "terrain" hits are incidental: a comment inecs/components/rigidbody/body_type.rs:46listing "walls, floors, terrain, static obstacles" as example use cases for a rigidbody type, and a"terrain"string used purely as an example category label inrendering/texture_atlas/atlas.rs:64's doc comment — neither is a real terrain system.ENG2-P2-11's chunking work landing first:ENG2-P2-11is described in the roadmap as solving the "windowless terrain" chunking problem generically (the "scrollable 3D tilemap-grid primitive"), and this issue is one concrete consumer of that primitive rather than a second implementation of chunk windowing.LODhit in the tree (libs/graphics/renderer3d/config.rs:80,195,199,core_model_animation/mod.rs:134,195) refers exclusively to animation update-rate LOD (skipping or half-rating skeletal animation evaluation at distance), not geometric mesh LOD or texture LOD. This issue's chunking is a prerequisite forENG2-P8-11's terrain-specific mesh/texture LOD, which is a distinct, new concept in this codebase.Verification