Docs/Architecture

Subsystem Overview

┌─────────────────────────────────────────────────────────────────┐
│                    MeshCraftApplication                          │
│   (CNA Game subclass — owns all editor state and orchestrates)  │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
│  │ EditorCamera │  │ SelectionMgr │  │   TransformGizmo     │  │
│  └──────────────┘  └──────────────┘  └──────────────────────┘  │
│                                                                 │
│  ┌──────────────────┐   ┌─────────────────────────────────┐    │
│  │   GridRenderer   │   │       SceneRenderer              │    │
│  └──────────────────┘   │  (unit meshes, CSG, textures,   │    │
│                          │   gizmos, edge overlay, anim)   │    │
│                          └─────────────────────────────────┘    │
│                                                                 │
│  ┌──────────────────────┐   ┌───────────────────────────────┐  │
│  │  SceneHierarchyPanel │   │       PropertiesPanel         │  │
│  │  (ImGui left panel)  │   │   (ImGui right panel)         │  │
│  └──────────────────────┘   └───────────────────────────────┘  │
│                                                                 │
│  Timeline Panel (Ctrl+T)   Menu Bar + Toolbar   Status Bar     │
└──────────────────────────┬──────────────────────────────────────┘
                           │ owns
                           ▼
                ┌──────────────────┐
                │   Mc3Document    │   ← pure C++, no graphics
                │  (mc3 library)   │
                │  objects, mats,  │
                │  lights, cameras,│
                │  actions, defs   │
                └──────────────────┘
                           │ serialized by
                           ▼
               ┌────────────────────┐
               │  Mc3XmlParser /    │
               │  Mc3XmlWriter      │
               └────────────────────┘

                           │ exported by (separate binary)
                           ▼
               ┌────────────────────┐
               │   mc3togltf        │
               │  (CLI converter)   │
               │  → glTF 2.0 / GLB  │
               └────────────────────┘

═══════════════ External Frameworks ═══════════════════════════════
  CNA: SDL3 window, GL context, BasicEffect, SpriteBatch, Input
  Dear ImGui v1.91.6: all UI panels (SDL3 + OpenGL ES 3 backends)
  Manifold v3: CSG boolean mesh evaluation
  tinyobjloader: OBJ mesh loading for viewport
  tinyxml2: XML parsing (via sharp-runtime)

Application Layer

MeshCraftApplication (src/MeshCraft/MeshCraftApplication.cpp) is the central class. It subclasses CNA's Microsoft::Xna::Framework::Game and owns:

The Game Loop

MeshCraft uses the CNA game loop model — a fixed-step update/draw cycle:

OverrideWhat happens
LoadContent() Creates renderers, loads Mc3Document from the path given on the command line (or creates an empty scene), initialises ImGui (SDL3 + OpenGL ES 3 backends).
BeginDraw() Calls ImGui::NewFrame() to start an ImGui frame before the 3D scene is rendered.
Update() Polls Keyboard and Mouse; processes shortcuts; handles viewport mouse (orbit, pan, zoom, picking, gizmo drag); advances animation playback clock.
Draw() Clears the frame; evaluates animation overrides; renders the 3D scene via SceneRenderer and grid via GridRenderer; draws the ImGui UI (drawImGuiUi() + drawTimelinePanel()).
EndDraw() Calls ImGui::Render() + ImGui_ImplOpenGL3_RenderDrawData(), optionally writes auto-screenshot, then calls Game::EndDraw().

Scene Data Layer (mc3 Library)

The mc3 sublibrary is entirely pure C++ — no graphics, no windowing, no ImGui. It defines the in-memory representation of a scene and handles XML serialization.

Mc3Document
├── objects: vector<shared_ptr<Mc3Object>>   ← scene graph roots
├── definitions: map<string, shared_ptr<Mc3Object>>
├── materials: map<string, Mc3Material>
├── textures:  map<string, Mc3Texture>
├── lights:    vector<Mc3Light>
├── cameras:   vector<Mc3Camera>
├── actions:   map<string, Mc3Action>        ← animation clips
└── environment: optional<Mc3Environment>

Mc3Object (scene graph node)
├── type: ObjectType   (Box, Sphere, Cylinder, Cone, Plane,
│                       Mesh, Extrude, Group, Instance,
│                       Union, Difference, Intersection, Area)
├── transform: Mc3Transform   (position, rotation, scale, pivot)
├── material: string          (IDREF into Mc3Document.materials)
├── primitive: optional<Mc3Primitive>
├── extrude:   optional<Mc3Extrude>
├── csgOperation: optional<Mc3CsgOperation>
└── children: vector<shared_ptr<Mc3Object>>

Rendering Layer

SceneRenderer traverses the Mc3Document.objects tree recursively. For each node it:

  1. Computes a world matrix from the object's transform (with pivot compensation)
  2. Applies animation overrides if a clip is playing
  3. Selects the appropriate pre-built unit mesh (box, sphere, cylinder, cone, plane)
  4. For CSG nodes, evaluates real boolean geometry via Manifold and caches the result
  5. For <mesh> nodes, loads the OBJ via tinyobjloader and caches it
  6. Applies the material color or texture if available
  7. Calls BasicEffect to render with lighting

The EditorCamera provides view and projection matrices; these are passed into every render call.

Editor Interaction Layer

ComponentRole
EditorCameraOrbit/pan/zoom model. Computes view + projection matrices and screen-ray directions for picking.
SelectionManagerHolds a set of shared_ptr<Mc3Object>. Supports single and multi-select (Ctrl+click, box-drag, Ctrl+A).
TransformGizmoTracks which gizmo mode (Move/Scale/Rotate) and which axis is active. Drag state is resolved in MeshCraftApplication::handleMouseInput().

UI Layer (Dear ImGui)

All UI is drawn with Dear ImGui (v1.91.6) using the SDL3 + OpenGL ES 3 backends. SDL events are forwarded to ImGui via SDL_AddEventWatch.

PanelLocationNotes
Menu BarTopFile, Edit, Add, View menus
ToolbarBelow menuTool switching + add-primitive buttons + edge overlay toggle
Hierarchy PanelLeft (220 px)Recursive object tree, visibility toggle, drag-and-drop reparenting, inline rename
Properties PanelRight (220 px)Name, position/rotation/scale, material, collision, tags; tabs for Lights / Cameras / Textures / Materials / Defs
ViewportCenter3D scene + gizmos; uses raw GL viewport/scissor for proper clipping
Timeline PanelBottom (190 px, toggle)Action dropdown, play/pause/stop, time scrubber, per-channel keyframe rows
Status BarBottom (22 px)Object count, selection count, timed status messages

Important Invariants

⚠️
Key constraints to preserve
  • Mc3Document.materials is std::map<string, Mc3Material> — iterate with structured bindings.
  • Mc3Material uses baseColor (float[4]), not diffuse.
  • ImGui panels use NoMove | NoResize | NoBringToFrontOnFocus flags — do not make them floating.
  • Viewport rect is [kLeftPanelW, imguiTopH_] to [W - kRightPanelW, H - kStatusH].
  • pendingScreenshot_ flag is set in Draw() and consumed in EndDraw() after ImGui renders.
  • Color (CNA type) has no default constructor — always init with 4 args: Color(r, g, b, a).
  • Call pushUndo() before any mutation of document_.
  • Do not add ${meta-gl_SOURCE_DIR}/include to CMakeLists.txt — triggers a full CNA recompile.
  • Do not change Mc3Document public API without checking mc3togltf and all test XMLs.

External Dependency Graph

MeshCraft (executable)
├── CNA                 ← sibling repo ../cna
│   └── SHARP_RUNTIME   ← sibling repo ../sharp-runtime
│       └── tinyxml2    (bundled)
├── Mc3                 ← mc3/ sublibrary
│   └── tinyxml2        (same instance, guarded by CMake alias)
├── ImGui v1.91.6       (FetchContent)
├── Manifold v3         (FetchContent)
└── tinyobjloader v2    (FetchContent)

mc3togltf (separate executable)
├── Mc3XmlParser        (local copy of mc3 parser)
├── GltfExporter
└── MeshBuilder
    └── (no CNA, no ImGui, no Manifold)