Skip to main content

Overview

The Rigidbody component is the foundation of physics simulation in Atlas. It binds a Bezel rigidbody to a GameObject and provides a high-level API for physics interactions.

Creating a Rigidbody

auto rb = std::make_shared<Rigidbody>();
rb->setMotionType(MotionType::Dynamic);
rb->setMass(5.0f);
rb->addBoxCollider({0.5f, 0.5f, 0.5f});
rb->setFriction(0.8f);

Motion Types

Rigidbodies support three motion types defined in bezel/bezel.h:64:
enum class MotionType { 
    Static,    // Immovable, zero velocity
    Dynamic,   // Fully simulated with forces and collisions
    Kinematic  // Movable but not affected by forces
};

Static Bodies

Static bodies never move and are used for terrain, walls, and fixed obstacles:
auto ground = std::make_shared<Rigidbody>();
ground->setMotionType(MotionType::Static);
ground->addBoxCollider({10.0f, 0.1f, 10.0f});

Dynamic Bodies

Dynamic bodies are fully simulated and respond to forces, gravity, and collisions:
auto ball = std::make_shared<Rigidbody>();
ball->setMotionType(MotionType::Dynamic);
ball->setMass(1.0f);
ball->addSphereCollider(0.5f);
ball->applyImpulse({0.0f, 10.0f, 0.0f});

Kinematic Bodies

Kinematic bodies can be moved programmatically but don’t respond to forces:
auto platform = std::make_shared<Rigidbody>();
platform->setMotionType(MotionType::Kinematic);
platform->addBoxCollider({2.0f, 0.1f, 2.0f});
// Move directly via transform

Physics Properties

Mass

Mass affects how forces and impulses affect the rigidbody:
// Set mass in kilograms
rigidbody->setMass(10.0f);

// Lower mass = easier to move
rigidbody->setMass(0.5f);  // Light object
rigidbody->setMass(100.0f); // Heavy object
Mass is stored in the underlying bezel::Rigidbody struct at bezel.h:475

Friction

Friction controls how much resistance objects have when sliding:
// Set friction coefficient (0.0 = frictionless, 1.0 = high friction)
rigidbody->setFriction(0.5f);

// Examples:
rigidbody->setFriction(0.0f);  // Ice
rigidbody->setFriction(0.5f);  // Default
rigidbody->setFriction(0.9f);  // Rubber

Restitution (Bounciness)

Restitution controls how much energy is retained during collisions:
// Set restitution (0.0 = no bounce, 1.0 = perfect bounce)
rigidbody->setRestitution(0.7f);

// Examples:
rigidbody->setRestitution(0.0f);  // No bounce
rigidbody->setRestitution(0.5f);  // Some bounce
rigidbody->setRestitution(0.9f);  // Very bouncy

Damping

Damping reduces velocity over time to simulate air resistance:
// Set linear and angular damping
rigidbody->setDamping(0.05f, 0.1f);

// Lower values = less damping (objects move longer)
// Higher values = more damping (objects slow down faster)
The default damping values from bezel.h:489-490:
  • Linear damping: 0.05f
  • Angular damping: 0.1f

Applying Forces and Impulses

Continuous Forces

Forces are applied continuously during physics updates:
// Apply force at center of mass
rigidbody->applyForce({0.0f, 100.0f, 0.0f});

// Apply force at a specific world-space point
rigidbody->applyForceAtPoint(
    {10.0f, 0.0f, 0.0f},  // Force vector
    {0.0f, 1.0f, 0.0f}    // Application point
);

Impulses

Impulses are instantaneous changes in velocity:
// Apply impulse (from test/main.cpp:120)
if (object && object->rigidbody) {
    object->rigidbody->applyImpulse({0.0f, 0.0f, 20.0f});
}
Use forces for continuous effects (like jet engines) and impulses for instant events (like explosions or jumping).

Velocity Control

Setting Velocity

// Set linear velocity directly
rigidbody->setLinearVelocity({5.0f, 0.0f, 0.0f});

// Set angular velocity
rigidbody->setAngularVelocity({0.0f, 1.0f, 0.0f});

Adding Velocity

// Add to existing linear velocity
rigidbody->addLinearVelocity({0.0f, 5.0f, 0.0f});

// Add to existing angular velocity
rigidbody->addAngularVelocity({0.0f, 0.5f, 0.0f});

Reading Velocity

// Get current velocities
Velocity3d linearVel = rigidbody->getLinearVelocity();
Velocity3d angularVel = rigidbody->getAngularVelocity();
Velocity3d totalVel = rigidbody->getVelocity();

Velocity Limits

Prevent instability with velocity limits:
// Set maximum velocities
rigidbody->setMaxLinearVelocity(50.0f);
rigidbody->setMaxAngularVelocity(10.0f);

Tagging System

Tags enable filtering and game logic:
// Add tags
rigidbody->addTag("Player");
rigidbody->addTag("Enemy");

// Check for tags
if (rigidbody->hasTag("Player")) {
    // Player-specific logic
}

// Remove tags
rigidbody->removeTag("Enemy");

// Use tags with raycasts
rigidbody->raycastTagged({"Enemy", "Obstacle"}, direction, 100.0f);
Tags are stored in bezel::Rigidbody at bezel.h:479:
std::vector<std::string> tags;

Sensors (Triggers)

Sensors detect overlaps without physical collision response:
auto sensor = std::make_shared<Sensor>();
sensor->addSphereCollider(1.0f);
sensor->setSignal("PlayerEnteredZone");
The Sensor class (defined in atlas/physics.h:481-487) is a convenience wrapper:
class Sensor final : public Rigidbody {
  public:
    Sensor() { Rigidbody::isSensor = true; }
    
    void setSignal(const std::string &signal) { 
        sendSignal = signal; 
    }
};

Physics Queries

Rigidbodies support multiple query types. Results are delivered asynchronously via Component::onQueryReceive().

Raycasting

// Cast ray from rigidbody position
rigidbody->raycast({0.0f, -1.0f, 0.0f}, 100.0f);

// Cast ray with all hits
rigidbody->raycastAll({0.0f, -1.0f, 0.0f}, 100.0f);

// Cast ray from arbitrary world position
rigidbody->raycastWorld(
    {0.0f, 10.0f, 0.0f},   // Origin
    {0.0f, -1.0f, 0.0f},   // Direction
    100.0f                  // Max distance
);

// Cast with tag filtering
rigidbody->raycastTagged(
    {"Enemy", "Destructible"},  // Tags to hit
    {0.0f, -1.0f, 0.0f},
    100.0f
);

Overlap Queries

// Check overlap at current position
rigidbody->overlap();

// Check overlap with specific shapes
rigidbody->overlapSphere(2.0f);
rigidbody->overlapBox({1.0f, 1.0f, 1.0f});
rigidbody->overlapCapsule(0.5f, 2.0f);

// Check overlap at world position
rigidbody->overlapSphereWorld({0.0f, 5.0f, 0.0f}, 1.0f);

Movement Prediction (Sweep)

Predict collisions before moving:
Position3d endPosition = {5.0f, 0.0f, 0.0f};

// Predict movement with current collider
rigidbody->predictMovement(endPosition);

// Predict with specific shapes
rigidbody->predictMovementSphere(endPosition, 0.5f);
rigidbody->predictMovementBox(endPosition, {0.5f, 0.5f, 0.5f});

// Get all hits along path
rigidbody->predictMovementAll(endPosition);

Receiving Query Results

class MyComponent : public Component {
    void onQueryReceive(QueryResult& result) override {
        if (result.operation == QueryOperation::Raycast) {
            if (result.raycastResult.hit.didHit) {
                std::cout << "Hit at distance: " 
                          << result.raycastResult.hit.distance << std::endl;
            }
        }
    }
};

Transform Synchronization

Rigidbody positions can be set programmatically:
// Set position (updates physics body)
rigidbody->body->setPosition(
    {10.0f, 5.0f, 0.0f},
    physicsWorld
);

// Set rotation (updates physics body)
rigidbody->body->setRotation(
    {0.0f, 45.0f, 0.0f},
    physicsWorld
);
From bezel.h:496-500, these methods update both the rigidbody state and the backend physics body.

Complete Example

Here’s a complete example creating a bouncing ball:
// Create physics world
auto world = std::make_shared<bezel::PhysicsWorld>();
world->init();
world->setGravity({0.0f, -9.81f, 0.0f});

// Create ground
auto ground = std::make_shared<Rigidbody>();
ground->setMotionType(MotionType::Static);
ground->addBoxCollider({10.0f, 0.1f, 10.0f});
ground->setFriction(0.5f);

// Create ball
auto ball = std::make_shared<Rigidbody>();
ball->setMotionType(MotionType::Dynamic);
ball->setMass(1.0f);
ball->addSphereCollider(0.5f);
ball->setRestitution(0.8f);  // Bouncy!
ball->setFriction(0.3f);
ball->applyImpulse({0.0f, 10.0f, 0.0f});

// Update loop
while (running) {
    world->update(deltaTime);
}

API Reference

Rigidbody Methods (atlas/physics.h:346-476)

MethodDescription
setMotionType(MotionType)Set static, dynamic, or kinematic mode
setMass(float)Set mass in kilograms
setFriction(float)Set friction coefficient (0.0-1.0)
setRestitution(float)Set bounciness (0.0-1.0)
setDamping(float, float)Set linear and angular damping
applyForce(Position3d)Apply continuous force
applyForceAtPoint(Position3d, Position3d)Apply force at point
applyImpulse(Position3d)Apply instant impulse
setLinearVelocity(Position3d)Set linear velocity
addLinearVelocity(Position3d)Add to linear velocity
setAngularVelocity(Position3d)Set angular velocity
addAngularVelocity(Position3d)Add to angular velocity
getLinearVelocity()Get current linear velocity
getAngularVelocity()Get current angular velocity
setMaxLinearVelocity(float)Set max linear velocity
setMaxAngularVelocity(float)Set max angular velocity
addTag(string)Add tag for filtering
hasTag(string)Check if tag exists
removeTag(string)Remove tag

See Also

Build docs developers (and LLMs) love