Renderer Module
SceneRenderer and GridRenderer — the 3D viewport rendering layer.
Components
| Class | File | Role |
|---|---|---|
SceneRenderer | src/MeshCraft/Renderer/SceneRenderer.cpp | Renders all MC3 objects, transform gizmos, light/camera icons, edge overlay, and CSG booleans. |
GridRenderer | src/MeshCraft/Renderer/GridRenderer.cpp | Draws the infinite XYZ reference grid using CNA BasicEffect and a VertexBuffer. |
SceneRenderer Overview
SceneRenderer is initialized once in LoadContent(). During initialization it builds all pre-computed unit meshes (a 1×1×1 box, unit sphere, unit cylinder, unit cone, unit plane) as VertexBuffer + IndexBuffer pairs. Each mesh is stored in a RenderMesh struct that holds:
- A
VertexPositionColorVB+IB pair for flat-colored rendering - A
VertexPositionNormalTextureVB+IB pair for lit+textured rendering - A
WireShapefor edge overlay (line-list geometry)
Each frame, SceneRenderer::draw() is called with the Mc3Document, view and projection matrices, and the current selection list.
Draw Traversal
The renderer traverses the scene graph recursively via drawObject():
- Compute world matrix from
Mc3Transformusing the pivot-compensated formula:world = T(pos + pivot) × R(rotation) × S(scale) × T(-pivot) - Apply animation overrides — if an animation clip is playing, the
animOverrides_map may replace the transform position/rotation/scale and visibility for this object. - Select render path by
ObjectType:Box/Cube→ scaled unit boxSphere→ scaled unit sphereCylinder→ scaled unit cylinderCone→ scaled unit conePlane→ scaled unit planeExtrude→ dynamically tessellated sweep mesh (per-frame, cached)Mesh→ OBJ loaded via tinyobjloader (loadOrGetMesh(), cached by path)Group→ render children recursivelyInstance→ resolve definition, render with overridden materialUnion/Difference/Intersection→ evaluate Manifold CSG, cache resultArea→ (no visual representation)
- Look up material: if the object has a material ID, retrieve
Mc3Material.baseColorfrom the document map. If the material has abaseColorTexture, load/cache the texture. - Render via
drawMesh()(flat color) ordrawMeshTextured()(texture). - Wireframe highlight: if the object is selected, draw a white wire box around its AABB.
Key Data Structures
struct RenderMesh {
unique_ptr<VertexBuffer> vb; // VertexPositionColor
unique_ptr<IndexBuffer> ib;
unique_ptr<VertexBuffer> texVB; // VertexPositionNormalTexture
unique_ptr<IndexBuffer> texIB;
int primitiveCount, texPrimitiveCount;
vector<Vector3> positions; // for AABB picking
};
struct AnimOverride {
optional<array<float,3>> position;
optional<array<float,3>> rotation;
optional<array<float,3>> scale;
optional<bool> visible;
};
Caches
| Cache field | Key | Invalidated by |
|---|---|---|
textureCache_ | Absolute file path | Never cleared (textures are immutable in the current session) |
meshCache_ | Absolute OBJ file path | Never cleared |
csgMeshCache_ | const Mc3Object* | clearCsgCache() — called from pushUndo() on every document mutation |
Animation Overrides
Before each draw() call, MeshCraftApplication::evaluateAndPushAnimOverrides() evaluates all channels of the currently playing action at the current time, building an unordered_map<string, AnimOverride> keyed by object name. This is then injected into the renderer via SceneRenderer::setAnimOverrides().
GridRenderer
Draws a flat reference grid in the XZ plane centered at the origin, plus colored X (red), Y (green), and Z (blue) axis lines. Uses CNA's BasicEffect with vertex color enabled. The grid vertex buffer is built once and reused each frame.