API docs: chrismaughan.com/megacitycode — or generate locally with python scripts/gen_api_docs.py.
MegaCityCode is a cross-platform native 3D viewer with retained font and grid foundations:
- Vulkan on Windows
- Metal on macOS
- SDL3 windowing and input
- a fixed-camera scene path for visualization work
- Fixed-camera 3D plane rendering in the Vulkan backend
- FreeType + HarfBuzz text pipeline with a dynamic glyph atlas
- Font fallback for newer Nerd Font and emoji/plugin glyph coverage
- Runtime font size changes with
Ctrl+=,Ctrl+-, andCtrl+0 - Mouse input support for click, drag, and wheel events
- HiDPI / Retina-aware rendering
- Shared logging with console/file fallback and category filtering
- Thin app layer with separate window, renderer, font, and grid modules
- CMake 3.25+
- Visual Studio 2022
- Vulkan SDK with
glslc
- CMake 3.25+
- Xcode Command Line Tools
All other dependencies are fetched automatically with CMake FetchContent.
Debug:
cmake --preset default
cmake --build build --config Debug --parallelRelease:
cmake --preset release
cmake --build build --config Release --parallelDebug:
cmake --preset mac-debug
cmake --build build --parallelRelease:
cmake --preset mac-release
cmake --build build --parallelDebug:
.\build\Debug\megacitycode.exeRelease:
.\build\Release\megacitycode.exeTo open a console window for logs:
.\build\Release\megacitycode.exe --console./build/megacitycodeMegaCityCode starts directly into the current visualization scene.
Root wrappers:
r.bat
r.bat --console
r.bat release --console
t.bat
t.bat bothsh ./r.sh
sh ./r.sh release
sh ./t.sh
sh ./t.sh bothThe root wrappers delegate to the larger scripts under scripts/.
The repository includes lightweight native tests for config parsing, retained grid storage, renderer helpers, snapshot parsing, and renderer state utilities that are still kept around internally.
Default is Debug:
scripts\run_tests.batOther modes:
scripts\run_tests.bat release
scripts\run_tests.bat both
scripts\run_tests.bat --reconfigureDefault is Debug:
./scripts/run_tests.shOther modes:
./scripts/run_tests.sh release
./scripts/run_tests.sh both
./scripts/run_tests.sh --reconfigureThe test scripts reuse the existing CMake cache when possible and only reconfigure when needed.
The CTest suite also includes:
- an app startup smoke test
- a render snapshot regression test for the fixed plane scene when the platform reference image exists under
tests/render/reference/
MegaCityCode can now run deterministic render-snapshot tests by capturing pixels directly from the renderer output instead of taking a desktop screenshot.
Example compare run:
.\build\Debug\megacitycode.exe --console --render-test D:\dev\megacitycode\tests\render\plane-view.tomlBless a new reference image:
.\build\Debug\megacitycode.exe --console --render-test D:\dev\megacitycode\tests\render\plane-view.toml --bless-render-testUpdate the documentation screenshot for the current platform:
python .\scripts\update_screenshot.pyNotes:
- The deterministic render regression scenario lives under
tests/render/plane-view.toml. - The current render path is scene-driven rather than text/grid-driven.
Behavior:
- the scenario fixes window size and capture tolerances
- MegaCityCode waits briefly for the scene to settle
- the renderer reads back the presented frame
- output is compared against a platform-specific reference image
actualandreportartifacts are written undertests/render/out/
Reference images live under tests/render/reference/ with platform suffixes like plane-view.windows.bmp and plane-view.macos.bmp.
Current scenarios:
plane-view: a low-angle 3D plane view with a visible horizon line
MegaCityCode now uses a shared repo-local logger across the app, RPC/process layer, windowing, font stack, and renderers.
Environment controls:
$env:MEGACITYCODE_LOG = "debug"
$env:MEGACITYCODE_LOG_CATEGORIES = "app,rpc,font"
$env:MEGACITYCODE_LOG_FILE = "logs\\megacitycode.log"Notes:
- Default level is
info. - Categories are comma-separated.
- GUI launches without a console will fall back to a log file automatically.
- The DPI diagnostics in the window layer are now
debug-only instead of always-on.
megacitycode/
├── app/ # App startup and main orchestration
├── libs/
│ ├── megacitycode-types/ # Shared POD types and event structs
│ ├── megacitycode-window/ # Window abstraction and SDL implementation
│ ├── megacitycode-renderer/ # Public renderer API and platform backends
│ ├── megacitycode-font/ # Font loading, shaping, glyph cache
│ └── megacitycode-grid/ # Thin retained cell storage for future text work
├── shaders/ # Vulkan and Metal shader sources
├── fonts/ # Bundled font assets copied next to the app
├── tests/ # Native test executable and fixture helpers
└── scripts/ # Build/test convenience scripts
For a guided human-facing overview of the repo structure, generated diagrams, and validation entry points, see docs/module-map.md.
GitHub Actions builds and tests the project on:
- Windows
- macOS
The workflow uses the same repo-local test scripts as local development, including the startup smoke test.
- Windows uses a multi-config Visual Studio generator through
CMakePresets.json. - The renderer boundary is owned by
megacitycode-renderer; app code should not include backend-private headers. - The font and grid layers are retained for future text work, but the current viewer render path is scene-driven rather than cell-driven.
- Visual regression testing now prefers direct swapchain/drawable readback over desktop screenshots so comparisons stay deterministic across window-manager state.
Regenerate with python scripts/build_docs.py.
The live API reference is published automatically to chrismaughan.com/megacitycode on every push to main.
To generate locally:
python scripts/gen_api_docs.pyThis writes a local Doxygen site to docs/api/index.html.
Reference image:
What the render smoke does:
- launches the fixed 3D plane scene at a deterministic size
- waits briefly for the renderer to settle instead of capturing a half-initialized frame
- reads pixels back from the renderer output directly, not from the desktop compositor
- compares the captured image against a blessed platform reference
- writes
actualandreportartifacts undertests/render/out/
Why this is useful:
- it catches visual regressions that ordinary unit tests miss, such as camera, shading, or material drift
- the
reportgives a mechanical pass/fail threshold instead of relying on guesswork --bless-render-testgives a controlled way to accept intentional visual changes
Why this helps agents:
- agents can change rendering, shaping, fallback fonts, cursor logic, or redraw handling and then immediately check whether the visible UI still matches the expected reference
- it reduces the risk of "looks fine in code review, obviously broken on screen" regressions
- it gives a shared, deterministic artifact for review instead of relying on hand-run screenshots or subjective descriptions


