Skip to content

ENG2-P8-06: Isometric projection/tile utils (#550) #804

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.2 — Gameplay services, Group B
  • Runbook spec: docs/src/runbook/phases/phase-8.md (committed with the roadmap)

Summary

Add isometric coordinate/projection utilities (tile<->world<->screen conversion, depth/draw-order helpers) as an engine-side math + FFI surface, so isometric games no longer hand-roll this math per SDK. Closes #550.

Architecture Context

Layer: Layer 1/2 (Foundation/Libs, core/math/ or a new libs/graphics/iso/) for the pure coordinate math; Layer 5 (FFI) for the export surface.
Modules/types touched:

  • goud_engine/src/core/math/ or new goud_engine/src/libs/graphics/iso.rs — isometric<->cartesian tile/world/screen conversion functions, and a draw-order/depth-sort helper (row+col -> z ordering) for isometric tile layers.
  • goud_engine/src/ffi/renderer/ — new FFI exports for the conversion functions.

Boundary constraints (only those that apply):

  • No raw GPU calls; this is pure coordinate math.
  • FFI exports: #[no_mangle] extern "C", #[repr(C)], null checks, // SAFETY: comments.

Pattern to follow: Whatever first-class 2D camera transform (ENG2-P6-05) establishes for its view/projection math — the isometric utilities must compose with that camera's world<->screen transform rather than reimplementing screen-space math independently, since ENG2-P6-05's stated goal is moving world->screen math off the SDK/consumer side and onto the engine.

Scope

  • Tile<->world coordinate conversion functions for a standard 2:1 isometric projection (and document if/how other ratios are supported).
  • World<->screen conversion composing with the Phase 6 first-class 2D camera (ENG2-P6-05) rather than assuming an un-transformed viewport.
  • Draw-order/depth helper: given a tile's (row, col) or (x, y) in iso space, produce a stable z/depth value for correct back-to-front sprite sorting.
  • FFI exports for all of the above, taking/returning plain floats (no new #[repr(C)] structs needed if 2-4 floats suffice).
  • Tests: spec test + unit tests for round-trip conversion (world -> iso -> world reproduces the original point) and draw-order monotonicity.
  • Docs/rules updates: mdBook page with a worked isometric tilemap example using TileLayer::get_gid (assets/loaders/tiled_map/layer.rs:31) alongside the new conversion functions.

Acceptance Criteria

  • Round-trip world->iso->world conversion is exact (within float epsilon) for a grid of test points.
  • Draw-order helper produces correct back-to-front ordering for a hand-constructed isometric scene fixture.
  • FFI isometric 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 module, new FFI surface).

Blocked By

ENG2-P6-05 (first-class 2D camera + engine-side 2D culling + coordinate-origin option — the isometric world<->screen conversion must build on the camera's view/projection math, not duplicate it).

Files Likely Touched

  • New: goud_engine/src/libs/graphics/iso.rs (or core/math/iso.rs), goud_engine/src/ffi/renderer/iso.rs
  • Generated: SDK bindings under sdks/*/ for the new isometric FFI exports
  • Modified: codegen/goud_sdk.schema.json

Agent Notes

  • Grep-verified: isometric, iso_to_world, and world_to_iso (case-insensitive) return zero matches anywhere in goud_engine/src — no isometric support exists in any form today. This closes Add isometric coordinate utilities #550 ("Add isometric coordinate utilities"), which is currently open.
  • There is also no first-class Camera2D type today — grep for Camera2D/camera_2d across goud_engine/src returns zero matches, confirming the roadmap's framing in ENG2-P6-05 that 2D world->screen math is currently done ad hoc on the SDK/consumer side (e.g. in C# game code), not in the engine. This is exactly why this issue is blocked on ENG2-P6-05 landing first: building isometric screen-space conversion against a camera abstraction that doesn't exist yet would mean redoing the work once the real camera lands.
  • Tile data with gid (global tile ID) already exists and is real: TileLayer::get_gid(&self, col: u32, row: u32) -> Option<u32> (goud_engine/src/assets/loaders/tiled_map/layer.rs:31) is implemented and tested (layer.rs:86-111). This issue's docs/example should use it directly rather than introducing a second tile-data representation.

Verification

cargo check && cargo fmt --all -- --check && cargo clippy -- -D warnings
cargo test
./codegen.sh && git diff --exit-code

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions