Skip to main content

Overview

Atlas provides a comprehensive vehicle physics system through the Bezel layer, powered by Jolt Physics. The vehicle system includes wheeled vehicle controllers with suspension, differential, transmission, and engine simulation.
The vehicle system is defined in bezel/bezel.h:334-462 and provides high-level wheeled vehicle constraints.

Vehicle Component

The Vehicle component wraps Jolt’s VehicleConstraint system.

Definition (atlas/physics.h:316-337)

class Vehicle final : public Component {
  private:
    bezel::Vehicle vehicle;
    bool created = false;
    bezel::PhysicsWorld *boundWorld = nullptr;
    
  public:
    bezel::VehicleSettings settings;
    
    float forward = 0.0f;   // [-1, 1] throttle/brake
    float right = 0.0f;     // [-1, 1] steering
    float brake = 0.0f;     // [0, 1] brake pedal
    float handBrake = 0.0f; // [0, 1] handbrake
    
    void atAttach() override;
    void beforePhysics() override;
    void requestRecreate();
};

Basic Setup

From bezel.h:418-436, here’s the basic vehicle setup pattern:
auto world = std::make_shared<bezel::PhysicsWorld>();
world->init();

// Create chassis rigidbody
auto chassis = std::make_shared<bezel::Rigidbody>();
chassis->mass = 1200.0f;
chassis->setCollider(std::make_shared<bezel::BoxCollider>(
    Position3d{1.0f, 0.5f, 2.0f}
));
chassis->create(world);

// Create vehicle
bezel::Vehicle vehicle;
vehicle.chassis = chassis.get();
vehicle.settings.wheels.resize(4);  // 4-wheel vehicle
vehicle.create(world);

// Each frame: set driver input
vehicle.setDriverInput(1.0f, 0.0f, 0.0f, 0.0f);
world->update(dt);

Vehicle Settings

VehicleSettings (bezel.h:403-413)

struct VehicleSettings {
    Normal3d up = {0.0f, 1.0f, 0.0f};       // Vehicle up direction
    Normal3d forward = {0.0f, 0.0f, 1.0f};  // Vehicle forward
    
    float maxPitchRollAngleDeg = 180.0f;    // Stability limit
    
    std::vector<VehicleWheelSettings> wheels;
    VehicleControllerSettings controller;
    
    float maxSlopeAngleDeg = 80.0f;         // Max climbable slope
};

Wheel Configuration

VehicleWheelSettings (bezel.h:338-363)

struct VehicleWheelSettings {
    Position3d position = {0.0f, 0.0f, 0.0f};
    
    // Suspension force point (optional)
    bool enableSuspensionForcePoint = false;
    Position3d suspensionForcePoint = {0.0f, 0.0f, 0.0f};
    
    // Axes
    Normal3d suspensionDirection = {0.0f, -1.0f, 0.0f};
    Normal3d steeringAxis = {0.0f, 1.0f, 0.0f};
    Normal3d wheelUp = {0.0f, 1.0f, 0.0f};
    Normal3d wheelForward = {0.0f, 0.0f, 1.0f};
    
    // Suspension
    float suspensionMinLength = 0.3f;
    float suspensionMaxLength = 0.5f;
    float suspensionPreloadLength = 0.0f;
    float suspensionFrequencyHz = 1.5f;
    float suspensionDampingRatio = 0.5f;
    
    // Wheel properties
    float radius = 0.3f;
    float width = 0.1f;
    
    float inertia = 0.9f;
    float angularDamping = 0.2f;
    float maxSteerAngleDeg = 70.0f;
    float maxBrakeTorque = 1500.0f;
    float maxHandBrakeTorque = 4000.0f;
};

Example: 4-Wheel Car Setup

bezel::VehicleSettings settings;

// Configure 4 wheels
settings.wheels.resize(4);

// Front-left wheel
settings.wheels[0].position = {-0.8f, -0.3f, 1.2f};
settings.wheels[0].radius = 0.35f;
settings.wheels[0].width = 0.2f;
settings.wheels[0].maxSteerAngleDeg = 35.0f;  // Steerable

// Front-right wheel
settings.wheels[1].position = {0.8f, -0.3f, 1.2f};
settings.wheels[1].radius = 0.35f;
settings.wheels[1].width = 0.2f;
settings.wheels[1].maxSteerAngleDeg = 35.0f;  // Steerable

// Rear-left wheel
settings.wheels[2].position = {-0.8f, -0.3f, -1.2f};
settings.wheels[2].radius = 0.35f;
settings.wheels[2].width = 0.2f;
settings.wheels[2].maxSteerAngleDeg = 0.0f;   // Fixed

// Rear-right wheel
settings.wheels[3].position = {0.8f, -0.3f, -1.2f};
settings.wheels[3].radius = 0.35f;
settings.wheels[3].width = 0.2f;
settings.wheels[3].maxSteerAngleDeg = 0.0f;   // Fixed

Suspension Tuning

Suspension affects handling and ride comfort:
// Soft suspension (comfort)
wheel.suspensionFrequencyHz = 1.0f;
wheel.suspensionDampingRatio = 0.3f;
wheel.suspensionMinLength = 0.2f;
wheel.suspensionMaxLength = 0.6f;

// Stiff suspension (racing)
wheel.suspensionFrequencyHz = 2.5f;
wheel.suspensionDampingRatio = 0.7f;
wheel.suspensionMinLength = 0.3f;
wheel.suspensionMaxLength = 0.4f;

// Off-road suspension (travel)
wheel.suspensionFrequencyHz = 1.2f;
wheel.suspensionDampingRatio = 0.4f;
wheel.suspensionMinLength = 0.1f;
wheel.suspensionMaxLength = 0.8f;

Engine Configuration

VehicleEngine (bezel.h:374-380)

struct VehicleEngine {
    float maxTorque = 500.0f;    // Peak engine torque (Nm)
    float minRPM = 1000.0f;      // Idle RPM
    float maxRPM = 6000.0f;      // Redline RPM
    float inertia = 0.5f;        // Engine inertia
    float angularDamping = 0.2f; // Engine friction
};

Example Engines

// Economy car engine
VehicleEngine economy;
economy.maxTorque = 200.0f;
economy.minRPM = 800.0f;
economy.maxRPM = 5500.0f;

// Sports car engine
VehicleEngine sports;
sports.maxTorque = 500.0f;
sports.minRPM = 1000.0f;
sports.maxRPM = 8000.0f;

// Truck engine
VehicleEngine truck;
truck.maxTorque = 800.0f;  // High torque
truck.minRPM = 600.0f;
truck.maxRPM = 4000.0f;    // Low RPM

Transmission

VehicleTransmission (bezel.h:384-394)

enum class VehicleTransmissionMode { Auto, Manual };

struct VehicleTransmission {
    VehicleTransmissionMode mode = VehicleTransmissionMode::Auto;
    std::vector<float> gearRatios = {2.66f, 1.78f, 1.3f, 1.0f, 0.74f};
    std::vector<float> reverseGearRatios = {-2.90f};
    float switchTime = 0.5f;          // Gear change time
    float clutchReleaseTime = 0.3f;   // Clutch engagement time
    float switchLatency = 0.5f;       // Shift delay
    float shiftUpRPM = 4000.0f;       // Auto upshift RPM
    float shiftDownRPM = 2000.0f;     // Auto downshift RPM
    float clutchStrength = 10.0f;     // Clutch force
};

Example Transmissions

// 5-speed manual
VehicleTransmission manual;
manual.mode = VehicleTransmissionMode::Manual;
manual.gearRatios = {3.5f, 2.2f, 1.5f, 1.0f, 0.8f};

// 6-speed automatic
VehicleTransmission automatic;
automatic.mode = VehicleTransmissionMode::Auto;
automatic.gearRatios = {4.0f, 2.5f, 1.8f, 1.3f, 1.0f, 0.75f};
automatic.shiftUpRPM = 5000.0f;
automatic.shiftDownRPM = 2500.0f;

// Racing transmission (close ratios)
VehicleTransmission racing;
racing.mode = VehicleTransmissionMode::Manual;
racing.gearRatios = {2.8f, 2.2f, 1.8f, 1.5f, 1.2f, 1.0f};
racing.switchTime = 0.1f;  // Quick shifts

Differential

VehicleDifferential (bezel.h:365-372)

struct VehicleDifferential {
    int leftWheel = -1;                  // Left wheel index
    int rightWheel = -1;                 // Right wheel index
    float differentialRatio = 3.42f;     // Final drive ratio
    float leftRightSplit = 0.5f;         // Torque split (0.5 = 50/50)
    float limitedSlipRatio = 1.4f;       // Limited slip strength
    float engineTorqueRatio = 1.0f;      // Engine power distribution
};

Drive Configurations

// Rear-wheel drive (RWD)
VehicleDifferential rearDiff;
rearDiff.leftWheel = 2;   // Rear-left
rearDiff.rightWheel = 3;  // Rear-right
rearDiff.differentialRatio = 3.42f;
rearDiff.engineTorqueRatio = 1.0f;  // 100% power

// Front-wheel drive (FWD)
VehicleDifferential frontDiff;
frontDiff.leftWheel = 0;  // Front-left
frontDiff.rightWheel = 1; // Front-right
frontDiff.differentialRatio = 3.73f;
frontDiff.engineTorqueRatio = 1.0f;

// All-wheel drive (AWD)
std::vector<VehicleDifferential> diffs(2);
// Front axle
diffs[0].leftWheel = 0;
diffs[0].rightWheel = 1;
diffs[0].engineTorqueRatio = 0.4f;  // 40% power
// Rear axle
diffs[1].leftWheel = 2;
diffs[1].rightWheel = 3;
diffs[1].engineTorqueRatio = 0.6f;  // 60% power

Controller Settings

VehicleControllerSettings (bezel.h:396-401)

struct VehicleControllerSettings {
    VehicleEngine engine;
    VehicleTransmission transmission;
    std::vector<VehicleDifferential> differentials;
    float differentialLimitedSlipRatio = 1.4f;
};

Driver Input

Control the vehicle with driver inputs:
void setDriverInput(float forward, float right, float brake, float handBrake);

Input Ranges

  • forward: [-1, 1] - Throttle (positive) or reverse (negative)
  • right: [-1, 1] - Steering left (negative) or right (positive)
  • brake: [0, 1] - Brake pedal pressure
  • handBrake: [0, 1] - Handbrake pressure

Example: Keyboard Control

class VehicleController : public Component {
    Vehicle* vehicle = nullptr;
    
    void update(float dt) override {
        float forward = 0.0f;
        float right = 0.0f;
        float brake = 0.0f;
        float handBrake = 0.0f;
        
        // Throttle/reverse
        if (Window::mainWindow->isKeyPressed(Key::W)) {
            forward = 1.0f;
        } else if (Window::mainWindow->isKeyPressed(Key::S)) {
            forward = -1.0f;
        }
        
        // Steering
        if (Window::mainWindow->isKeyPressed(Key::A)) {
            right = -1.0f;
        } else if (Window::mainWindow->isKeyPressed(Key::D)) {
            right = 1.0f;
        }
        
        // Brake
        if (Window::mainWindow->isKeyPressed(Key::Space)) {
            brake = 1.0f;
        }
        
        // Handbrake
        if (Window::mainWindow->isKeyPressed(Key::LeftShift)) {
            handBrake = 1.0f;
        }
        
        vehicle->forward = forward;
        vehicle->right = right;
        vehicle->brake = brake;
        vehicle->handBrake = handBrake;
    }
};

Complete Vehicle Example

Here’s a complete example creating a drivable car:
// 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({50.0f, 0.1f, 50.0f});
ground->setFriction(0.8f);

// Create chassis
auto chassis = std::make_shared<Rigidbody>();
chassis->setMotionType(MotionType::Dynamic);
chassis->setMass(1200.0f);  // 1200kg car
chassis->addBoxCollider({0.9f, 0.4f, 2.0f});
chassis->setFriction(0.5f);

// Create vehicle component
auto vehicle = std::make_shared<Vehicle>();

// Configure wheels
vehicle->settings.wheels.resize(4);
for (int i = 0; i < 4; i++) {
    auto& wheel = vehicle->settings.wheels[i];
    wheel.radius = 0.35f;
    wheel.width = 0.25f;
    wheel.suspensionFrequencyHz = 1.5f;
    wheel.suspensionDampingRatio = 0.5f;
    wheel.suspensionMinLength = 0.2f;
    wheel.suspensionMaxLength = 0.5f;
}

// Front wheels (steerable)
vehicle->settings.wheels[0].position = {-0.85f, -0.3f, 1.3f};
vehicle->settings.wheels[0].maxSteerAngleDeg = 35.0f;
vehicle->settings.wheels[1].position = {0.85f, -0.3f, 1.3f};
vehicle->settings.wheels[1].maxSteerAngleDeg = 35.0f;

// Rear wheels (driven)
vehicle->settings.wheels[2].position = {-0.85f, -0.3f, -1.3f};
vehicle->settings.wheels[3].position = {0.85f, -0.3f, -1.3f};

// Configure engine
vehicle->settings.controller.engine.maxTorque = 500.0f;
vehicle->settings.controller.engine.minRPM = 1000.0f;
vehicle->settings.controller.engine.maxRPM = 6000.0f;

// Configure transmission
vehicle->settings.controller.transmission.mode = VehicleTransmissionMode::Auto;
vehicle->settings.controller.transmission.gearRatios = {3.5f, 2.2f, 1.5f, 1.0f, 0.8f};
vehicle->settings.controller.transmission.shiftUpRPM = 5000.0f;

// Configure differential (RWD)
VehicleDifferential rearDiff;
rearDiff.leftWheel = 2;
rearDiff.rightWheel = 3;
rearDiff.differentialRatio = 3.42f;
rearDiff.engineTorqueRatio = 1.0f;
vehicle->settings.controller.differentials = {rearDiff};

// Update loop
while (running) {
    // Get input and update vehicle
    vehicle->forward = getThrottle();    // [-1, 1]
    vehicle->right = getSteering();      // [-1, 1]
    vehicle->brake = getBrake();         // [0, 1]
    vehicle->handBrake = getHandBrake(); // [0, 1]
    
    world->update(deltaTime);
}

Vehicle Presets

Sports Car

VehicleSettings getSportsCarSettings() {
    VehicleSettings settings;
    settings.wheels.resize(4);
    
    // Low, stiff suspension
    for (auto& wheel : settings.wheels) {
        wheel.radius = 0.32f;
        wheel.width = 0.28f;
        wheel.suspensionFrequencyHz = 2.5f;
        wheel.suspensionDampingRatio = 0.7f;
        wheel.suspensionMinLength = 0.15f;
        wheel.suspensionMaxLength = 0.25f;
    }
    
    // Powerful engine
    settings.controller.engine.maxTorque = 600.0f;
    settings.controller.engine.maxRPM = 8000.0f;
    
    // Quick shifting
    settings.controller.transmission.switchTime = 0.1f;
    settings.controller.transmission.gearRatios = {2.8f, 2.0f, 1.5f, 1.2f, 1.0f, 0.8f};
    
    return settings;
}

Off-Road Truck

VehicleSettings getOffRoadSettings() {
    VehicleSettings settings;
    settings.wheels.resize(4);
    
    // High, soft suspension with lots of travel
    for (auto& wheel : settings.wheels) {
        wheel.radius = 0.45f;  // Large tires
        wheel.width = 0.35f;
        wheel.suspensionFrequencyHz = 1.0f;
        wheel.suspensionDampingRatio = 0.4f;
        wheel.suspensionMinLength = 0.1f;
        wheel.suspensionMaxLength = 0.8f;  // Lots of travel
    }
    
    // High-torque engine
    settings.controller.engine.maxTorque = 800.0f;
    settings.controller.engine.minRPM = 600.0f;
    settings.controller.engine.maxRPM = 4500.0f;
    
    // Low gearing for torque
    settings.controller.transmission.gearRatios = {4.5f, 3.0f, 2.0f, 1.5f, 1.0f};
    
    settings.maxSlopeAngleDeg = 60.0f;  // Can climb steep slopes
    
    return settings;
}

API Reference

Vehicle Component (atlas/physics.h:316-337)

PropertyTypeDescription
settingsVehicleSettingsComplete vehicle configuration
forwardfloatThrottle/reverse input [-1, 1]
rightfloatSteering input [-1, 1]
brakefloatBrake input [0, 1]
handBrakefloatHandbrake input [0, 1]
MethodDescription
requestRecreate()Rebuild vehicle constraint

Bezel Vehicle (bezel.h:438-462)

MethodDescription
create(PhysicsWorld)Create vehicle in world
destroy(PhysicsWorld)Remove vehicle from world
isCreated()Check if vehicle is created
setDriverInput(float, float, float, float)Set control inputs

See Also

Build docs developers (and LLMs) love