acdream/tests
Erik a6cd56663f feat(core): terrain surface recipe + cell data packing (Phase 3c.3)
Ports WorldBuilder's full BuildTexture / FillCellData pipeline as
pure CPU functions in TerrainBlending.cs, along with the SurfaceInfo
recipe record and a TerrainBlendingContext input struct that carries
the atlas index lists the algorithm needs.

This is still pure algorithm work — no GL, no shaders, no mesh gen
changes. Visual Phase 3c.4 next commit wires it into LandblockMesh
and rewrites the terrain shaders to consume Data0..3.

Added (all ports of WorldBuilder LandSurfaceManager methods):
  - ExtractTerrainCodes: inverse of GetPalCode terrain bits
  - PseudoRandomIndex: deterministic hash over palette code for alpha
    variant selection; overflow-dependent int math matches WorldBuilder
    byte-for-byte
  - RotateTerrainCode: *2 with wrap (1→2→4→8→1, multi-corner patterns
    handled in tests)
  - GetRoadCodes: decodes the 8-bit road mask into up to two canonical
    road patterns + allRoad flag; magic 0xE/0xD/0xB/0x7 switch kept verbatim
  - FindTerrainAlpha: picks corner vs side alpha map, walks the 4
    rotations looking for a TCode match, returns (alphaLayer, rotation)
    or (255, 0) for "not found"
  - FindRoadAlpha: same idea for road maps, iterates all maps from a
    pseudo-random offset
  - BuildSurface: composes the above into a SurfaceInfo, handling the
    all-road, all-duplicate-terrain, and distinct-terrain cases via
    BuildOverlayLayers + BuildWithDuplicates (ports GetTerrainTextures +
    BuildTerrainCodesWithDuplicates)
  - FillCellData: packs a SurfaceInfo + CellSplitDirection into the 4
    uint32 vertex attributes Data0..Data3. Byte layout documented in
    XML comment and matches WorldBuilder's Landscape.vert uvec4 byte
    unpacking exactly.

SurfaceInfo record carries resolved atlas byte layers directly (base +
3 terrain overlays + 2 road overlays, each with optional alpha layer
and 0-3 rotation). Sentinel 255 = "slot unused".

Tests (14 new, 75/75 total):
  - ExtractTerrainCodes round-trip with GetPalCode
  - RotateTerrainCode single-corner cycle + multi-corner patterns
  - GetRoadCodes: no-road, all-road, single-corner road
  - PseudoRandomIndex: range, count=0 guard, determinism
  - BuildSurface: all-grass → base only; all-road → road as base;
    two-grass-two-dirt → base + overlay
  - FillCellData: full round-trip bit layout with recognizable
    byte values in every slot, plus a no-road1 case that verifies
    the texRd1 slot collapses to 255 when road1 alpha is absent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:53:32 +02:00
..
AcDream.Core.Tests feat(core): terrain surface recipe + cell data packing (Phase 3c.3) 2026-04-11 13:53:32 +02:00
AcDream.Core.Tests.Fixtures.HelloPlugin feat(core): add PluginLoader with collectible ALC 2026-04-10 09:51:16 +02:00