Skip to content

Latest commit

 

History

History
386 lines (289 loc) · 10.4 KB

File metadata and controls

386 lines (289 loc) · 10.4 KB

Engine API Guide

VoidEngine exposes a reusable C++20 static library named VoidEngine. The main convenience include is:

#include <void_engine/engine.h>

That header includes the public engine surface from core, platform, renderer, scene, ui, and editor.

Linking

Inside this repository, CMake targets link directly against VoidEngine:

target_link_libraries(MyApp PRIVATE VoidEngine)

The editor, demo, tools, and tests all use the same engine library target.

Application Lifecycle

ve::Application owns the main engine subsystems and drives the game loop.

Owned systems include:

  • window and OpenGL context
  • time and fixed physics tick
  • input and gamepad manager
  • event bus
  • job system
  • audio device
  • ImGui layer
  • splash screen

Typical usage:

#include <void_engine/engine.h>

class MyApp final : public ve::Application {
public:
    MyApp()
        : ve::Application(makeConfig()) {}

protected:
    void onInit() override {
        m_device.init();
        m_scene.initPhysics();
    }

    void onPhysicsUpdate(ve::f64 fixedDt) override {
        m_scene.stepPhysics(static_cast<ve::f32>(fixedDt));
    }

    void onUpdate(ve::f64 dt) override {
        m_scene.stepAnimations(static_cast<ve::f32>(dt));
        m_scene.stepParticles(static_cast<ve::f32>(dt));
        m_scene.stepScripts(static_cast<ve::f32>(dt), &getInput());
    }

    void onRender() override {
        m_device.clear();
        m_scene.render(m_camera, m_device);
    }

private:
    static ve::AppConfig makeConfig() {
        ve::AppConfig config;
        config.window.title = "My VoidEngine App";
        config.window.width = 1600;
        config.window.height = 900;
        return config;
    }

    ve::Scene m_scene;
    ve::RenderDevice m_device;
    ve::FreeCamera m_camera;
};

int main() {
    MyApp app;
    app.run();
}

Core Systems

Header Purpose
core/application.h Main application base class and subsystem ownership.
core/log.h Engine logging and log entries consumed by the editor console.
core/event_bus.h Event dispatch infrastructure.
core/time.h Frame timing and fixed physics tick support.
core/input.h Keyboard, mouse, and input state.
core/input_map.h Named actions mapped to keyboard, mouse, and gamepad bindings.
core/gamepad.h GLFW gamepad access.
core/job_system.h Parallel job execution for engine-scale work.
core/audio_* Audio device, clips, sources, mixer, music streams, and playlists.
core/physics_world.h Jolt-backed physics world, bodies, queries, and stepping.
core/asset_baker.h Mesh/texture baking helpers used by vebake.
core/asset_pack.h .vepack writer/reader helpers used by vepack.
core/game_package.h .vegame.json runtime package metadata.

Scene And ECS

ve::Scene is the central runtime/editor container. It owns:

  • entity pool
  • UUID mapping
  • generic component stores
  • transform hierarchy
  • rendering integration
  • physics integration
  • script runtime state
  • animation and particle stepping
  • serialization snapshots for play mode

Basic entity/component flow:

ve::Scene scene;

ve::Entity entity = scene.createEntity();
scene.addName(entity, "Player");

auto& transform = scene.addTransform(entity);
transform.position = {0.0f, 1.0f, 0.0f};

scene.addRigidbody(entity, {.motionType = ve::PhysicsMotionType::Dynamic});
scene.addCollider(entity, ve::ColliderComponent::makeBox({0.5f, 0.5f, 0.5f}));

Generic component API:

scene.addComponent<MyComponent>(entity, MyComponent{});

if (scene.hasComponent<MyComponent>(entity)) {
    auto& component = scene.getComponent<MyComponent>(entity);
}

scene.removeComponent<MyComponent>(entity);

Multi-component queries:

scene.each<ve::TransformComponent, ve::MeshRendererComponent>(
    [](ve::Entity entity, auto& transform, auto& meshRenderer) {
        // Process renderable entity.
    });

Parallel query:

scene.parallelEach<ve::TransformComponent, ve::AnimatorComponent>(
    jobs,
    [](ve::Entity entity, auto& transform, auto& animator) {
        // Process animation-related data.
    });

Built-In Components

Component Purpose
TransformComponent Local transform and parent-child relationship.
NameComponent Human-readable entity display name.
MeshRendererComponent Mesh and material reference for rendering.
LightComponent Directional, point, and spot lighting data.
RigidbodyComponent Physics body settings.
ColliderComponent Box, sphere, capsule, and collision shape data.
TriggerComponent Trigger/overlap behavior.
ScriptComponent Lua script path and runtime script hooks.
AnimatorComponent Skeletal animation state.
ParticleEmitterComponent Runtime particle emitter configuration.
TerrainComponent Terrain heightfield, splat layers, foliage, and terrain rendering data.
PrefabInstanceComponent Prefab linkage and revert/detach workflow support.

Rendering

Important renderer types:

Type Purpose
RenderDevice OpenGL render-state and draw wrapper.
ShaderProgram Shader compilation, linking, uniforms, and hot reload support.
ShaderLibrary Named shader collection.
Mesh GPU mesh buffers with typed vertex layout support.
Texture2D Texture loading, parameters, and GL ownership.
CubemapTexture Skybox and image-based lighting cubemap support.
Framebuffer Off-screen rendering target.
Camera / FreeCamera Projection/view camera utilities.
Font / UIRenderer Font loading and retained UI drawing support.

ve::Scene::render(camera, device) can render entities with Transform + MeshRenderer and applies scene environment settings.

Scene rendering supports:

  • forward rendering
  • deferred rendering path
  • directional/point/spot lighting
  • shadow resources
  • skybox
  • image-based lighting
  • SSAO
  • bloom
  • tone mapping
  • gamma correction
  • FXAA
  • vignette
  • color grading controls
  • instancing/static batching
  • frustum and occlusion culling infrastructure
  • physics debug rendering
  • particle and terrain rendering

Environment access:

auto& environment = scene.getEnvironment();
environment.ambient = {0.12f, 0.10f, 0.13f};
environment.lightDirection = {0.3f, -0.8f, 0.5f};
environment.lightIntensity = 1.2f;

auto& deferred = scene.getDeferredRendererSettings();
deferred.enabled = true;
deferred.bloom = true;
deferred.toneMapping = true;

Physics

Physics is exposed through ve::PhysicsWorld and scene convenience APIs.

Common flow:

scene.initPhysics();

ve::Entity entity = scene.createEntity();
scene.addTransform(entity);
scene.addRigidbody(entity, {.motionType = ve::PhysicsMotionType::Dynamic});
scene.addCollider(entity, ve::ColliderComponent::makeBox({1.0f, 1.0f, 1.0f}));

scene.stepPhysics(fixedDeltaTime);

Picking and raycasts:

ve::SceneRaycastHit hit;
bool found = scene.pickClosest(camera, mousePosition, viewportSize, hit);

Trigger helpers:

std::vector<ve::Entity> overlaps = scene.getTriggerOverlaps(triggerEntity);
bool touching = scene.isTriggerOverlapping(triggerEntity, otherEntity);

Scripting

Lua scripts are attached through ScriptComponent. The scene owns script runtime state and exposes update/physics hooks.

ve::ScriptComponent script;
script.path = "samples/scripts/rotator.lua";
scene.addScript(entity, script);

scene.stepScripts(deltaTime, &input);
scene.stepScriptPhysics(fixedDeltaTime, &input);
scene.reloadScripts();

The editor inspector can assign .lua files through drag-drop from the Asset Browser and includes a Reload Scripts button.

Input Maps

ve::InputMap maps named actions to keyboard, mouse, and gamepad bindings. It is used by game packages through controls JSON files.

Supported binding sources:

  • Keyboard
  • MouseButton
  • GamepadButton
  • GamepadAxis

Runtime use:

ve::InputMap map;
map.loadFromFile("game/config/signal_breach.controls.json");

map.update(input, 0);

if (map.isActionPressed("fire")) {
    // Fire once.
}

float moveRight = map.getActionValue("move_right");

Audio

Audio APIs are split into:

  • AudioDevice
  • AudioClip
  • AudioSource
  • AudioMixer
  • MusicStream
  • MusicPlaylist

The implementation is designed for sound effects, grouped mixing, priorities, virtualization, streamed music, playlists, and crossfade-style flows.

Asset And Resource APIs

API Purpose
AssetBaker Convert mesh/texture data into runtime-friendly baked formats.
AssetPackReader / packDirectory Read/write .vepack archives.
ResourceManager Runtime resource ownership and lookup.
TextureManager Texture cache and loading helper.
AssetMetadata UUID/path metadata for assets.

These APIs are also used by the CLI tools documented in Assets, Packages, and Tooling.

Scene Serialization

ve::SceneSerializer reads and writes scene JSON.

ve::SceneSerializer serializer(scene);
serializer.saveToFile("samples/scenes/my_scene.scene.json");
serializer.loadFromFile("samples/scenes/my_scene.scene.json");

Mesh, material, and texture pointers are non-owning runtime references. Use SceneSerializer::AssetResolver to map runtime pointers to stable string IDs during save and back to pointers during load.

Game Packages

ve::GamePackage represents .vegame.json metadata.

Fields include:

  • version
  • title
  • description
  • scenario id
  • startup scene
  • controls config
  • asset root
  • optional asset pack

Use it to resolve package-relative paths:

ve::GamePackage package;
package.loadFromFile("game/signal_breach.vegame.json");

auto base = std::filesystem::path("game");
auto scenePath = package.resolveStartupScene(base);
auto controlsPath = package.resolveControlsConfig(base);

Reusable Editor APIs

The editor UI classes live in the engine library so they can be reused by the main editor app or future editor tools.

Class Purpose
SceneHierarchyPanel Entity tree panel.
InspectorPanel Component property editor.
ViewportPanel Scene/Game viewport and gizmos.
AssetBrowserPanel Filesystem asset browser.
ConsolePanel Log viewer.
ProfilerPanel Frame profiler UI.
UndoHistory Undo/redo command stack.
PlayModeManager Editor/play/paused state and scene snapshot restoration.

For full usage details see Editor Guide.