Docs/Modules/Renderer

Components

ClassFileRole
SceneRenderersrc/MeshCraft/Renderer/SceneRenderer.cppRenders all MC3 objects, transform gizmos, light/camera icons, edge overlay, and CSG booleans.
GridRenderersrc/MeshCraft/Renderer/GridRenderer.cppDraws 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:

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():

  1. Compute world matrix from Mc3Transform using the pivot-compensated formula:
    world = T(pos + pivot) × R(rotation) × S(scale) × T(-pivot)
  2. Apply animation overrides — if an animation clip is playing, the animOverrides_ map may replace the transform position/rotation/scale and visibility for this object.
  3. Select render path by ObjectType:
    • Box/Cube → scaled unit box
    • Sphere → scaled unit sphere
    • Cylinder → scaled unit cylinder
    • Cone → scaled unit cone
    • Plane → scaled unit plane
    • Extrude → dynamically tessellated sweep mesh (per-frame, cached)
    • Mesh → OBJ loaded via tinyobjloader (loadOrGetMesh(), cached by path)
    • Group → render children recursively
    • Instance → resolve definition, render with overridden material
    • Union/Difference/Intersection → evaluate Manifold CSG, cache result
    • Area → (no visual representation)
  4. Look up material: if the object has a material ID, retrieve Mc3Material.baseColor from the document map. If the material has a baseColorTexture, load/cache the texture.
  5. Render via drawMesh() (flat color) or drawMeshTextured() (texture).
  6. 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 fieldKeyInvalidated by
textureCache_Absolute file pathNever cleared (textures are immutable in the current session)
meshCache_Absolute OBJ file pathNever 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.