Skip to content
Robby-cellPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Physics Engine Plugin

A high-performance, header-only 2D and 3D physics engine designed for modern C++17. While optimized for Entity Component System (ECS) architectures via SFINAE trait validation, its generic design allows for seamless integration into OOP-based game engines.

Features

  • Strictly Decoupled: 2D and 3D pipelines are physically separated to optimize compile times and memory layout.
  • ECS-Agnostic: Compatible with EnTT, Flecs, or custom registries via compile-time interface validation.
  • Modern Math: Quaternion-based 3D rotations to avoid Gimbal Lock and 3D Impulse resolution with Baumgarte Stabilization.
  • Data-Oriented: Components are POD (Plain Old Data) structs, ensuring cache-friendly iteration.

1. Integration with ECS (e.g., EnTT)

The engine uses SFINAE to verify that your Registry class provides a .view<T>() and .get<T>() member functions.

Setup

#include <entt/entt.hpp>
#include <physics/systems/PhysicsSystem2D.hpp>
#include <physics/components/RigidBody2D.hpp>

entt::registry registry;
physics::systems::PhysicsSystem2D<entt::registry, entt::entity> physics_system;

// Create an entity
auto entity = registry.create();
registry.emplace<physics::components::Transform2D>(entity, physics::math::Vector2{0.0F, 10.0F});
registry.emplace<physics::components::RigidBody2D>(entity).set_mass(1.0F);

Update Loop

// Within your game loop
float dt = 0.016F;
physics_system.update(registry, dt);

2. Integration with OOP (No ECS)

If you are using a standard GameObject architecture, you can still use the engine by creating a "Thin Wrapper" that mimics the Registry interface. This allows the physics engine to remain highly performant while managing your objects.

Step 1: Create a Wrapper

struct MyGameObject {
    RigidBody3D rigidbody;
    Transform3D transform;
    AABBCollider3D collider;
};

struct ObjectRegistry {
    std::vector<MyGameObject*> objects;

    // Mimic the 'view' interface required by the Physics Engine
    template<typename... Args>
    std::span<MyGameObject*> view() { return objects; }

    // Mimic the 'get' interface
    template<typename T>
    T& get(MyGameObject* obj) {
        if constexpr (std::is_same_v<T, RigidBody3D>) return obj->rigidbody;
        if constexpr (std::is_same_v<T, Transform3D>) return obj->transform;
        if constexpr (std::is_same_v<T, AABBCollider3D>) return obj->collider;
    }
};

Step 2: Update

ObjectRegistry registry;
physics::systems::PhysicsSystem3D<ObjectRegistry, MyGameObject*> physics_system;

physics_system.update(registry, dt);

Building and Testing

Prerequisites

  • CMake 3.21+
  • Ninja or MSVC
  • C++17 Compatible Compiler

Using CMake Presets

# Configure the project (Debug)
cmake --preset debug

# Build
cmake --build --preset debug

# Run Tests
ctest --preset debug

Documentation

Run doxygen Doxyfile to generate the full API reference in the docs/ folder.


3. Usage Guidance for Developers

Why the ECS approach is better for Physics:

In a "serious" project, performance is king. When you use the ECS integration (like with EnTT), all RigidBody and Transform components are stored in contiguous memory. When the PhysicsSystem iterates over them, the CPU can pre-fetch data efficiently, resulting in massive speedups when handling thousands of colliding objects.

Why the OOP approach is provided:

Many legacy engines or smaller tools use a std::vector<std::unique_ptr<GameObject>>. By providing the "Wrapper" pattern in the README, you allow those users to adopt your high-quality physics math without forcing them to rewrite their entire engine architecture to an ECS.

Strict Style Reminder:

  • Templates: All systems are templated on Registry and Entity to maintain agnosticism.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages