Warning
🚧 Heavily work in progress. Odyssey Engine is in early, active development.
A custom 3D game engine in C++23 with a separate C#/WPF editor. The editor communicates with the engine over a local socket, allowing the engine to be restarted independently if it crashes without taking down the editor.
A standalone runtime that owns the window, the renderer, and the world.
- Rendering - OpenGL 4.6 core profile via GLAD, windowing through GLFW, math via GLM. A simple forward renderer draws meshes with a per-object model matrix and flat color.
- ECS - a sparse-set entity-component registry. Entities are an index + version pair; components live in packed pools for cache-friendly iteration. The registry exposes
Create,Destroy,Add,Remove,Has,Get, and a templatedView<...>for system queries. - Components & systems -
Transform,MeshRenderer, andSpincomponents, driven by aRenderSystemand aSpinSystem. Systems iterate the world each frame through the registry's view API. - Messaging - a thread-safe
EventBussupporting immediate publish, deferred enqueue/flush, prioritized handlers, and scoped subscriptions. - Editor bridge - a TCP server that speaks a small RPC + event protocol. Requests carry an
id,method, andparams; the engine answers with typed JSON. Outbound and inbound event types are registered through aJsonProxyso payloads serialize automatically.
A native WPF desktop application built on a clean, layered architecture.
- Domain / Application / UI - strict separation of concerns. The Application layer holds framework-agnostic services and interfaces; the UI layer is WPF + MVVM.
- MVVM - view models built on
CommunityToolkit.Mvvm, wired together withMicrosoft.Extensions.Hostingdependency injection. - Panels - a Hierarchy, an Inspector, a Console, a Controls bar, and a Workspace that hosts the embedded engine.
- Services - a logging service with leveled output piped to the in-editor console, and an undo/redo service backed by a command stack.
- Engine connection - an async TCP client with length-prefixed JSON framing, request/response correlation via
TaskCompletionSource, background read loop, and connection retry.
When the workspace opens, the editor:
- Launches the engine process headless (
-hide) on a chosen port. - Connects to the engine's socket and retries until the runtime is listening.
- Sends a
get_viewportrequest and receives the engine window's native handle (HWND). - Reparents that window into a WPF
HwndHost, restyles it as a child window, and keeps it sized to the panel.
The result is a single editor window with the real, live C++ OpenGL viewport rendering inside it.
| Area | Choice |
|---|---|
| Engine language | C++23 |
| Graphics | OpenGL 4.6 core, GLAD, GLFW, GLM |
| Serialization | nlohmann/json |
| Engine build | CMake + Ninja, MSVC 2022 |
| Editor language | C# / .NET 10 |
| Editor UI | WPF, MVVM (CommunityToolkit.Mvvm) |
| DI / hosting | Microsoft.Extensions.Hosting |
| Engine ↔ editor | TCP, length-prefixed JSON (RPC + events) |
| Task runner | just |
Windows-only - the editor uses WPF and native HWND reparenting, and the engine builds with MSVC.
- Visual Studio 2022 Build Tools (MSVC toolchain)
- Ninja -
winget install Ninja-build.Ninja - just -
winget install Casey.Just - .NET 10 SDK (for the editor)
CMake fetches GLFW, GLAD, GLM, and nlohmann/json automatically on first configure.
- Point the editor at the built engine binary in
Editor/OdysseyEditor.UI/appsettings.json(EnginePath,Port). - Set the path to your
VsDevCmd.batinjustconfig.json.
Build the engine:
just build-engineClean engine build artifacts:
just clean-engineThen run the editor from your .NET tooling. It will launch the engine, connect, and embed the viewport.
The engine can also run standalone via the launcher, which accepts:
| Flag | Effect |
|---|---|
-game / -editor |
launch mode |
-hide |
run without showing its own window (used when embedded) |
-port <n> |
editor bridge port |
-width / -height <n> |
window size |
-vsync <0|1> |
toggle vsync |
