GETerrainRenderer

Builds one cube per non-air block from a World, split into static and animated meshes.

Overview

Builds its meshes from a Worlds::World with cna-engine's MeshBuilder and keeps them as std::unique_ptr<CnaEngine::Graphics::GpuMesh> members: a static mesh for non-animated non-air blocks (built once), and an animated-subset mesh rebuilt whenever Update(device, animPhase) sees a new phase. Until 2026-10-20 these were Easy3D::CubeMeshRenderer instances.

Sources: src/GalaxyEggbertCNA/Game/GETerrainRenderer.hpp and .cpp.

Construction

Triple-nested loop over the world's full blocksPerAxis() cube. For every non-air block:

worldX = x - kWorldCenterX;  worldZ = z - kWorldCenterZ;   // Y unshifted
if (BlockTypes::tileAnimBase(block.type()) is animated)
    m_animBlocks.push_back({worldX, y, worldZ, baseIcon});
else
    AddCenteredBox(mesh, center=(worldX, y, worldZ), size=(1, 1, 1), faces);   // MeshBuilder::AddBox
    // faces: one BoxFaceStyle{visible, uv} per BoxFace, uv = tileAtlas.GetTileUv(block.type())

Also accumulates centroid sums (exposed as CentroidX/Y/Z()) — used as a camera look-at target since the spawn tile may be open air. The builder holds the vertex/index data directly (24 vertices + 36 indices per full cube — the same data easy-3d's BuildCubeMesh produced); UploadTexturedMesh(device, mesh) uploads it once to CNA VertexBuffer/IndexBuffer as a GpuMesh. Special shapes use the same builder: AddPlate, AddCrossedPlates (3 planes), and the game's own AddPyramidTip() for the teleporter's tip.

Animated Tile Groups (ported from mobile-eggbert Tables.cpp)

TileFrames
Lava8
Spike16
Crusher10
Saw6
Water1 / Water26 each
Temp20 (2 invisible frames)
Fan ×4 directions3 each
Marine11

AnimIcon(base, phase) looks up the current icon; IsAnimated(base) gates classification.

Update(device, animPhase)

No-op if the phase hasn't changed. Otherwise rebuilds the animated mesh from the current frame's icons. If the phase yields zero visible animated cubes (e.g. Temp's blank frames), the animated renderer is reset to null rather than uploading empty data.

Draw

staticRenderer->Draw(device, effect);                       // GpuMesh::Draw(device, effect)
if (animatedRenderer) animatedRenderer->Draw(device, effect);

Known Limitations

Dependencies

cna-engine (MeshBuilder, GpuMesh, UvRect, via src/GalaxyEggbert/Game/TexturedMesh.hpp), GETileAtlas, Worlds::World, BlockTypes. Until 2026-10-20: easy-3d (CubeBatch, CubeMesh, CubeMeshRenderer).