A modern, ECS-based 3D game engine built with C++ and Metal for macOS
Features β’ Architecture β’ Getting Started β’ Building β’ Usage β’ Documentation
AsterEditor - Full-featured game editor with hierarchy, inspector, and project panels
Real-time 3D scene rendering with transform gizmos and debug visualization
- Pure ECS Architecture - Entity Component System for data-driven game development
- Metal Rendering Backend - High-performance graphics via Apple's Metal API
- Real-time 3D Rendering - Modern rendering pipeline with PBR material support
- Scene Management - Complete scene serialization and deserialization system
- Asset Management - Automatic asset discovery and import system
- Transform Hierarchy - Parent-child entity relationships with world-space transformations
- Camera System - Free-look camera with WASD movement and mouse controls
- Visual Editor - Native macOS editor built with AppKit
- Hierarchy Panel - Tree view of scene entities with drag-and-drop support
- Inspector Panel - Component-based property editing
- Project Panel - Asset browser with import functionality
- Transform Gizmos - Interactive 3D manipulation of entities
- Debug Overlay - Real-time performance metrics and statistics
- Welcome Window - Project management (create, open, recent projects)
- Mesh Import - Universal 3D model loader supporting:
- OBJ format (with Assimp)
- FBX, GLTF, COLLADA (extensible)
- Texture Import - Image loading via STB Image
- Procedural Primitives - Built-in mesh generation:
- Cube, Sphere, Plane
- Cylinder, Cone, Torus, Capsule
- Transform - Position, rotation, scale with hierarchical support
- Mesh - Geometry reference (primitive or imported)
- Material - PBR properties (albedo, metallic, roughness)
- MeshRenderer - Visibility and rendering control
- Name - Entity naming for editor display
AsterEngine follows a modular, layered architecture designed for maintainability and extensibility:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Applications β
β ββββββββββββββββββ ββββββββββββββββββββ β
β β AsterEditor β β Game Runtime β β
β β (AppKit UI) β β (Custom Client) β β
β ββββββββββββββββββ ββββββββββββββββββββ β
ββββββββββββββββββββββββ¬ββββββββββββββββββββ¬βββββββββββββββ
β β
ββββββββββββββββββββββββ΄ββββββββββββββββββββ΄βββββββββββββββ
β Engine Runtime β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β ECS Core (Registry, Components, Systems) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β Scene Management & Serialization β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β Asset Manager (Meshes, Textures, Materials) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β Rendering System (Camera, Debug Draw, Gizmos) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β Editor Bridge (C API for UI interop) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββ
β Rendering Hardware Interface (RHI) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Abstract Interface (Device, Pipeline, Buffer) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Metal Backend (DeviceMetal, BufferMetal, etc.) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The engine uses a sparse-set based ECS for optimal performance:
// Entities are lightweight IDs
using EntityId = uint32_t;
// Components are pure data (no logic)
struct Transform {
Vec3 position, rotationEuler, scale;
Mat4 worldMatrix;
EntityId parent;
};
// Systems operate on component combinations
for (EntityId entity : registry.GetEntitiesWith<MeshRenderer>()) {
const Transform* transform = registry.Get<Transform>(entity);
const Mesh* mesh = registry.Get<Mesh>(entity);
const Material* material = registry.Get<Material>(entity);
// Render entity...
}Key Benefits:
- O(1) component lookup
- Cache-friendly iteration
- Data-driven design
- Easy to extend with new components
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Scene Query: Get entities with MeshRenderer component β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β 2. Component Gather: Collect Transform, Mesh, Material β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β 3. Resource Binding: Load meshes/textures on-demand β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β 4. Metal Draw Calls: Indexed rendering with instancing β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β 5. Debug Overlay: Gizmos, grid, statistics β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The Rendering Hardware Interface (RHI) provides a clean abstraction over graphics APIs:
namespace aster::rhi {
struct Device; // GPU device management
struct Swapchain; // Present surface
struct Pipeline; // Shader program + state
struct Buffer; // GPU buffer (vertex/index/uniform)
struct Texture; // 2D/3D textures
struct CommandList; // Command recording
}Current Implementation: Metal (macOS)
Future Targets: Vulkan (cross-platform), DirectX 12 (Windows)
AsterEngine/
βββ src/
β βββ engine/
β β βββ ecs/ # Entity Component System
β β β βββ Entity.h # Entity ID type definitions
β β β βββ Registry.h # Component storage & queries
β β β βββ Components.h # Component definitions
β β βββ scene/ # Scene management
β β β βββ Scene.h # Scene container
β β β βββ SceneSerializer.h # Save/load scenes
β β βββ runtime/ # Core engine systems
β β β βββ Engine.h # Main engine class
β β β βββ Camera.h # Camera controller
β β β βββ AssetManager.h # Asset loading
β β β βββ MeshLoader.h # Mesh import (OBJ, etc.)
β β β βββ PrimitiveAssets.h # Procedural meshes
β β βββ render/ # Rendering utilities
β β β βββ DebugDraw.h # Debug line rendering
β β β βββ GizmoAxis.h # Transform gizmos
β β βββ rhi/ # Graphics abstraction
β β β βββ Pipeline.h # RHI interface
β β βββ editor/ # Editor-engine bridge
β β β βββ EditorBridge.h # C API for UI
β β βββ platform_macos/ # Platform layer
β β βββ AppHost.mm # Window & event handling
β βββ rhi/
β β βββ metal/ # Metal implementation
β β βββ DeviceMetal.mm
β β βββ CommandListMetal.mm
β β βββ ...
β βββ apps/
β β βββ editor/ # Editor application
β β βββ EditorApp.mm # Editor entry point
β β βββ ui/ # UI panels (AppKit)
β βββ main.cpp # Game runtime entry
βββ third_party/ # External dependencies
β βββ stb_image.h # Image loading
β βββ assimp/ # 3D model import
βββ resources/ # App resources
βββ docs/ # Documentation
βββ CMakeLists.txt # Build configuration
- macOS 11.0+ (Big Sur or later)
- Xcode 13+ with Command Line Tools
- CMake 4.0+
- Homebrew (for dependencies)
Install required libraries via Homebrew:
brew install cmake assimp-
Clone the repository:
git clone https://github.com/N3ur0sis/AsterEngine.git cd AsterEngine -
Create build directory:
mkdir build && cd build
-
Configure with CMake:
cmake ..
-
Build the project:
cmake --build . -
Run the editor:
open AsterEditor.app
The project produces three targets:
- AsterEditor - Full-featured game editor
- AsterEngine - Minimal game runtime
- engine_runtime / engine_rhi_metal - Static libraries
# Debug build (default)
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build .
# Release build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .set(CMAKE_CXX_STANDARD 23) # C++23 features
set(CMAKE_CXX_STANDARD_REQUIRED ON)build/
βββ AsterEditor.app/ # Editor application bundle
βββ AsterEngine.app/ # Game runtime bundle
βββ libengine_runtime.a # Core engine library
βββ libengine_rhi_metal.a # Metal rendering backend
- Launch AsterEditor.app
- Click "Create New Project"
- Choose a name and location
- The editor creates:
MyProject/ βββ Assets/ β βββ Meshes/ βββ Scenes/ β βββ SampleScene.json βββ MyProject.aproj
Method 1: Drag & Drop
- Drag
.obj,.fbx, or image files into the Project Panel
Method 2: Import Menu
- Right-click in Project Panel β "Import Asset..."
- Select files to import
Creating Entities:
- Right-click in Hierarchy β "Create Empty" or "Create Primitive"
- Entities are created with Transform component by default
Adding Components:
- Select an entity
- Click "Add Component" in Inspector
- Choose: Mesh, Material, or MeshRenderer
Transform Manipulation:
- W - Translate gizmo
- E - Rotate gizmo
- R - Scale gizmo
Camera Controls:
- Right-click + drag - Look around
- WASD - Move camera
- Q/E - Move up/down
- Scroll - Adjust speed
Create a custom game client:
#include "runtime/AppHost.h"
#include "runtime/Engine.h"
class MyGame : public AppClient {
aster::Engine engine;
void OnStartup() override {
// Initialize engine
engine.Initialize(surface, 1920, 1080);
engine.LoadScene("Assets/Scenes/MainScene.json");
// Create entities programmatically
aster::Scene* scene = engine.GetScene();
auto entity = scene->CreateEntity("Player");
scene->AddComponent(entity, aster::Mesh{aster::PrimitiveMeshType::Sphere});
scene->AddComponent(entity, aster::MeshRenderer{});
}
void OnUpdate(double dt) override {
engine.Update(dt);
}
void OnRender() override {
engine.Render();
}
};
int main() {
MyGame game;
AppConfig cfg{"My Game", 1920, 1080};
return RunApp(game, cfg);
}- Component System Architecture - ECS design and patterns
- Mesh Import System - Asset pipeline details
class Engine {
bool Initialize(const PlatformSurface& surface, int w, int h);
void Update(double dt);
void Render();
Scene* GetScene();
Camera* GetCamera();
AssetManager* GetAssetManager();
void NewScene(const std::string& name = "New Scene");
bool LoadScene(const std::filesystem::path& path);
bool SaveScene(const std::filesystem::path& path);
};class Scene {
EntityId CreateEntity(const char* name = nullptr);
void DestroyEntity(EntityId entity);
template<typename T>
T& AddComponent(EntityId entity, T&& component);
template<typename T>
T* GetComponent(EntityId entity);
Registry& GetRegistry();
};class Registry {
EntityId CreateEntity();
void DestroyEntity(EntityId entity);
template<typename T>
T& Add(EntityId entity, T&& component);
template<typename T>
T* Get(EntityId entity);
template<typename T>
bool Has(EntityId entity);
template<typename... Components>
std::vector<EntityId> GetEntitiesWith();
};- β ECS architecture with sparse-set storage
- β Metal rendering backend
- β Scene serialization (JSON)
- β OBJ mesh import via Assimp
- β Native macOS editor
- β Transform gizmos
- β Project management
- β Asset browser and import
- π§ PBR material system
- π§ Texture import and management
- π§ FBX/GLTF model support
- π Physics system (RigidBody, Collider components)
- π Lighting system (Point, Directional, Spot lights)
- π Shadow mapping
- π Post-processing stack
- π Audio system (3D spatial audio)
- π Animation system
- π Particle system
- π Scripting (Lua/Python integration)
- π Vulkan backend (Windows/Linux support)
- π Scene runtime (playmode)
- π Build pipeline (game export)
Contributions are welcome! Please feel free to submit a Pull Request.
- Follow the existing code style (C++23, modern practices)
- Keep components as data-only (no logic)
- Use the ECS pattern for new features
- Add documentation for public APIs
- Test on macOS before submitting
- Rendering: Implement PBR shading, shadows, post-processing
- Physics: Integrate a physics library (Bullet, Jolt)
- Animation: Skeletal animation system
- Tools: Additional editor panels and tools
- Platform: Vulkan/DirectX backends
- Documentation: Tutorials, examples, API docs
This project is licensed under the MIT License - see the LICENSE file for details.
- Assimp - Open Asset Import Library
- STB - Single-file public domain libraries
- Apple Metal - High-performance graphics API
- Unity - ECS workflow and editor design
- Unreal Engine - Asset management patterns
- Godot - Scene system architecture
Made with β€οΈ using C++23 and Metal
