| title | Architecture | ||
|---|---|---|---|
| description | System architecture, layer model, and design rationale | ||
| slug | architecture | ||
| author | rahulmnavneeth | ||
| date | 19 FEB 2026 | ||
| tags |
|
Master of Puppets is structured as a strict four-layer stack. Every dependency points downward. No layer may reference a layer above it.
┌──────────────────────────────┐
│ Application │ examples/showcase.c
├──────────────────────────────┤
│ Viewport Public API │ include/mop/*.h
├──────────────────────────────┤
│ Viewport Core + Interact │ src/core/ + src/interact/
├──────────────────────────────┤
│ Render Hardware Interface │ src/rhi/
├──────────────────────────────┤
│ Backend Implementations │ src/backend/{cpu,opengl,vulkan}/
└──────────────────────────────┘
| Page | Topic |
|---|---|
| Layer Separation | Strict boundary rules between layers |
| Frame Lifecycle | What happens during a single render frame |
| Threading Model | Single-threaded guarantees, future-proofing |
| Memory Ownership | Who allocates, who frees, no implicit transfers |
| Extension Strategy | How to add backends, features, and subsystems |
| Scene Graph | Hierarchical transforms and parent-child meshes |
The application is any program that links against libmop.a. It sees only the public headers in include/mop/. It creates viewports, adds meshes, sets cameras, calls render, reads back pixels.
Defined in include/mop/*.h. Exposes opaque handles (MopViewport *, MopMesh *), value types (MopVec3, MopMat4, MopColor), and free functions. No backend-specific types appear here.
Defined in src/core/ and src/interact/. src/core/ owns the scene graph (flat mesh array), camera state, lighting, overlays, and rendering orchestration. src/interact/ owns the input state machine, gizmo, orbit camera, and undo/redo. Both call the RHI to create buffers, begin frames, issue draw calls, and read back results. Never calls backend APIs directly.
Defined in src/rhi/rhi.h. A function-pointer table (MopRhiBackend) that every backend must populate. The viewport core holds a pointer to this table and calls through it.
Each backend lives in src/backend/<name>/ and implements every function in MopRhiBackend.
| From | May depend on | Must not depend on |
|---|---|---|
| Application | include/mop/ |
src/ (anything internal) |
| Viewport Core | include/mop/, rhi |
Backend internals |
| RHI | include/mop/ |
Backend internals |
| Backend | include/mop/, rhi |
Viewport core, other backends |
| Math | C standard library | Everything else |
Opaque handles provide ABI stability. The application never sees sizeof(MopViewport), so internal fields can change without recompilation.
Function-pointer table enables runtime backend selection. The application chooses MOP_BACKEND_CPU or MOP_BACKEND_OPENGL at viewport creation — no recompilation needed.
Flat mesh array with active flags avoids allocator complexity. The upper bound MOP_MAX_MESHES (4096) can be raised by recompiling.
Column-major matrices match OpenGL and Vulkan conventions. MopMat4.d[col * 4 + row].