CubeMeshRenderer requires CNA link
Easy3D / Data & Batching / CubeMeshRenderer
Easy3D::CubeMeshRenderer is Easy3D's first Roadmap Phase 4 CNA renderer adapter: it uploads a CubeMesh's vertex/index arrays to real GPU buffers once, then Draw() issues indexed TriangleList draw calls on demand. It knows nothing about tiles, gameplay, or cameras — the caller owns and configures the BasicEffect (World/View/Projection/Texture) before calling Draw().
#include <Easy3D/CubeMeshRenderer.hpp>
namespace Easy3D { class CubeMeshRenderer; }
GraphicsDevice::DrawIndexedPrimitives. Everything upstream of it (CubeBatch, CubeMesh) is still plain CPU data.The draw-path decision
Easy3D issues cube/billboard draws with raw VertexBuffer + IndexBuffer + BasicEffect + GraphicsDevice::DrawIndexedPrimitives — the same pattern CNA's own examples/house3d_demo.cpp already proves works (build GPU buffers once, SetVertexBuffer/Indices/DrawIndexedPrimitives per frame inside a pass.Apply() loop). SpriteBatch was considered and rejected: it is 2D-only, not usable for cube/billboard geometry.
Constructor — uploads once
const std::vector<CubeVertex>& vertices,
const std::vector<std::uint32_t>& indices)
vertices/indices to new GPU VertexBuffer/IndexBuffer objects immediately. indices.size() must be a multiple of 3 (whole triangles); otherwise throws std::invalid_argument.Internally, each CubeVertex{Position, Uv} converts 1:1 to CNA's VertexPositionTexture{Position, TextureCoordinate} — the field layouts match exactly, so there is no reordering or reinterpretation, just a straight copy. The index buffer always uses 32-bit indices (IndexElementSize::ThirtyTwoBits), matching CubeMesh's std::uint32_t output.
Draw
effect's current technique: for each pass, calls pass.Apply(), binds the renderer's vertex/index buffers, and issues one DrawIndexedPrimitives(TriangleList, ...) call covering the whole mesh. effect's World/View/Projection and, if texturing is wanted, TextureEnabled/Texture must already be set by the caller before calling Draw().[[nodiscard]] int PrimitiveCount() const noexcept
indices.size() / 3) — handy for stats/debug overlays.Lifecycle — build once, draw many times
Unlike BillboardMeshRenderer, a CubeMeshRenderer's geometry is camera-independent — cube positions don't change when the camera moves. Build it once (on load, or whenever the level's cube batch actually changes) and call Draw() every frame against it:
// On load / level change:
std::vector<Easy3D::CubeVertex> vertices;
std::vector<std::uint32_t> indices;
Easy3D::BuildCubeMesh(terrain, vertices, indices);
Easy3D::CubeMeshRenderer terrainRenderer(graphicsDevice, vertices, indices);
// Each frame:
effect.World = Matrix::Identity;
effect.View = camera.GetViewMatrix();
effect.Projection = camera.GetProjectionMatrix();
effect.TextureEnabled = true;
effect.Texture = tilesTexture; // the CNA texture your TextureAtlas describes
terrainRenderer.Draw(graphicsDevice, effect);
Verification
CubeMeshRenderer's constructor needs a live GraphicsDevice&, which only exists once a real CNA Game has opened a window — something a plain test main() cannot produce. So Easy3D's own test suite only compile-checks it (see Testing); the real runtime verification was done end-to-end against Galaxy Eggbert's actual windowed binary, with a center-screen pixel readback confirming real, non-background pixels were drawn.
vertices/indices this class consumes, and BillboardMeshRenderer for the equivalent adapter for camera-facing quads.