Skip to content

ENG2-P8-10: Chunked heightmap terrain component #808

Description

@aram-devdocs

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

  • Heightfield data representation: a 2D grid of height samples (from a raster image, a procedural function, or raw float array) per chunk.
  • Mesh generation: turn a chunk's heightfield into a renderable grid mesh with computed vertex normals (for correct lighting).
  • Chunk lifecycle reusing ENG2-P2-11's chunk-loading pattern: chunks load/unload based on camera/view distance, not the whole terrain resident at once.
  • FFI exports: create a heightmap terrain from a data source, query height at (x, z), configure chunk size/resolution.
  • Tests: spec test + unit tests for mesh generation correctness (vertex positions match height samples, normals are correct for a known slope fixture) and height-query accuracy (interpolated height between samples).
  • Docs/rules updates: mdBook page covering heightmap terrain authoring (data format, chunk size tuning) and extend .agents/rules/graphics-patterns.md with the terrain chunk pattern.

Acceptance Criteria

  • A generated terrain chunk's mesh vertices match the input heightfield within float tolerance, with correctly-oriented normals verified against a known-slope fixture.
  • Height-at-world-position queries return correctly bilinearly-interpolated values between sample points.
  • Chunk load/unload follows the ENG2-P2-11 windowing pattern (no full-terrain-resident assumption) verified on a multi-chunk fixture scene.
  • FFI terrain exports have wrappers in all 10 SDKs and pass python codegen/validate_coverage.py.
  • cargo check && cargo fmt --all -- --check && cargo clippy -- -D warnings clean; cargo test green; ./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

  • 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions