← Back to Projects
Personal project · Active development

PlanetExplorer

C++17VulkanCMake / NinjaEngine-agnostic C ABIMarching cubes · LODGoogleTest

PlanetExplorer is a voxel-based procedural-planet engine I'm building from scratch in C++. It began as a Unity (URP) prototype; I've since retired the engine host entirely and am rebuilding it as a standalone C++ engine — for full control of the render and memory model, and the freedom to run outside any engine. The core is deliberately kept engine-agnostic, so it can still be embedded in Unreal or Unity later if I ever want to, without recompilation coupling.

What it does

Architecture — three hard-walled layers

The design principle is a narrow, well-specified boundary between layers, so each can evolve (or be swapped) independently.

flowchart TD
  subgraph HOST[host — thin platform shell]
    H[window · input · main loop
standalone today, swappable] end subgraph REND[renderer — our own, adapter seam] G[GraphicsBackend interface] --> VK[VulkanBackend
device · swapchain · pipelines] end subgraph CORE[core — pure C++, flat C ABI, zero deps] C[voxel density · marching cubes
transvoxel LOD · chunk streaming · world state] end H --> G H -->|C ABI| C G -->|meshes / buffers| C CORE -. embeddable later .-> UE[Unreal native module] CORE -. embeddable later .-> UN[Unity native plugin]

Engineering discipline

It also runs headless

Beyond the interactive views above, the engine runs headless for CI — a bounded smoke check brings up a validated Vulkan device and meshes terrain, then exits:

PlanetExplorer engine core v0.3.0
renderer: Vulkan backend on "NVIDIA GeForce RTX 3080" (validation on)
presenter: 3 images, 1280x720, format=44
terrain mesh: 34770 vertices
world created (seed=42 radius=1000.0 chunk=32); entering loop (smoke)
WIP — the engine already renders full procedural planets with live biome editing, occlusion culling, and chunk streaming (above). Ongoing work: transvoxel LOD, Hi-Z occlusion refinement, and broader platform coverage. Source is private for now.

Why it's here: it's the C++/engine-level and native-embedding counterpart to my SDK work — the same discipline of a flat, well-specified boundary that lets independent layers move without breaking each other.