ReactPhysics3D Documentation

repository·master·Indexed 23 days ago

https://github.com/danielchappuis/reactphysics3d

A lightweight, standalone C++ physics engine for 3D simulations and games. It features rigid body dynamics, discrete collision detection (Sphere, Box, Capsule, Convex Mesh, Static Concave Mesh, and Height Field), and a Sequential Impulses Solver for collision response. The library is designed for high portability, avoiding external libraries and STL containers. It includes developer tools such as an integrated profiler, debugging renderer, and a testbed application.

Tokens
14K
Snippets
37
Records
61
Agent score
74%

What's inside ReactPhysics3D

  1. Overview of ReactPhysics3D features

    master

    ReactPhysics3D is an open-source C++ physics engine library designed for 3D simulations and games. It is a standalone library that does not use external libraries or STL containers, making it highly portable and easy to integrate into existing C++ projects.

    Key features include:

    • Rigid body dynamics and Discrete collision detection.
    • Collision shapes: Sphere, Box, Capsule, Convex Mesh, Static Concave Mesh, and Height Field.
    • Advanced Collision Detection: Broadphase (Dynamic AABB tree) and Narrowphase (SAT/GJK).
    • Collision Response: Sequential Impulses Solver for response and friction.
    • Joints: Ball and Socket, Hinge, Slider, and Fixed joints.
    • Capabilities: Ray casting, collision filtering with categories, and a sleeping technique for inactive bodies.
    • Developer Tools: Integrated profiler, debugging renderer, logs, and a testbed application with demos.
  2. Configure the ReactPhysics3D Profiler

    master

    To use the real-time profiler, you must build the library with the RP3D_PROFILING_ENABLED CMake variable enabled.

    How it works

    • Collection: The profiler collects performance data while the application is running.
    • Output: When the PhysicsWorld destructor is called, the profiling information is written to a text file.
    • File Naming: By default, one profile file is created per PhysicsWorld. Files are named after the world (e.g., world.txt, world1.txt).
    • Customization: You can change the name of a world by setting it in the WorldSettings object during PhysicsWorld creation.
  3. Understand Collider Behaviors

    master

    Colliders can exhibit different behaviors depending on how they are configured:

    • Simulation Collider: The default behavior. Colliders will physically bump into each other, generating contact points and forces.
    • World Query Collider: Used for manual queries like raycast(), testOverlap(), or testPointInside(). A collider can be both a simulation collider and a world query collider.
    • Trigger: A collider that does not physically collide with anything but can report when it is overlapping with another collider.

    Note: A collider cannot be both a Simulation Collider and a Trigger at the same time.

  4. Understand Rigid Body types: Static, Kinematic, and Dynamic

    master

    ReactPhysics3D supports three types of rigid bodies, which can be set using RigidBody::setType(BodyType type):

    • Static (BodyType::STATIC): Infinite mass and zero velocity. Position can be changed manually, but it does not collide with other static or kinematic bodies. Use this for floors or buildings.
    • Kinematic (BodyType::KINEMATIC): Infinite mass, but velocity can be changed manually. The physics engine computes its position. It does not collide with other static or kinematic bodies. Use this for moving platforms.
    • Dynamic (BodyType::DYNAMIC): Non-zero mass and velocity determined by forces. The physics engine determines its position. It can collide with all other body types. This is the default type.

    Note: When a body is created, it is DYNAMIC by default.

    // Change the type of the body to kinematic
    body->setType(BodyType::KINEMATIC);
  5. Manage memory in ReactPhysics3D

    master

    ReactPhysics3D uses a centralized memory management system via the PhysicsCommon object.

    Object Ownership

    Objects like PhysicsWorld and RigidBody are created via factory methods. You must not use the C++ delete operator on these objects. Instead, use the provided destruction methods to release memory manually, or allow the PhysicsCommon object to handle it upon its own destruction.

    Manual Destruction

    • To destroy a rigid body: world->destroyRigidBody(body);
    • To destroy a physics world: physicsCommon.destroyPhysicsWorld(world);

    Custom Allocators

    By default, the library uses std::malloc() and std::free(). To use a custom allocator, inherit from the MemoryAllocator class and override allocate() and release(). Note that allocate() must return memory that is 16 bytes aligned.

  6. Achieve determinism in ReactPhysics3D simulations

    master

    ReactPhysics3D is deterministic when compiled with the same compiler and running on the same machine. To ensure two simulation runs are identical, follow these practices:

    1. Reset State: Completely destroy and recreate the PhysicsWorld, all Body objects, and all Joint objects to clear cached internal simulation data.
    2. Consistent Ordering: Create bodies and joints in the exact same order every time.
    3. Consistent Execution: Ensure all method calls to the PhysicsWorld, bodies, and joints occur in the same sequence.
  7. Configure Collision Filtering

    master

    Collision filtering allows you to group colliders into categories and specify which categories can collide with each other using bitmasks.

    Rules for Collision: A collider is only able to collide with another if the first collider's category is part of the second collider's collide with mask, AND the second collider's category is part of the first collider's collide with mask. The condition must be satisfied in both directions.

    Workflow:

    1. Define categories using bitwise values (e.g., 0x0001, 0x0002).
    2. Assign a category to a collider using Collider::setCollisionCategoryBits().
    3. Define allowed collisions using Collider::setCollideWithMaskBits() (use bitwise OR | to allow multiple categories).
    enum Category {
        CATEGORY1 = 0x0001,
        CATEGORY2 = 0x0002,
        CATEGORY3 = 0x0004
    };
    
    // Assign categories
    colliderBody1->setCollisionCategoryBits(CATEGORY1);
    colliderBody2->setCollisionCategoryBits(CATEGORY2);
    
    // Specify what to collide with
    colliderBody1->setCollideWithMaskBits(CATEGORY3); // Only collides with Category 3
    colliderBody2->setCollideWithMaskBits(CATEGORY1 | CATEG3); // Collides with 1 and 3
  8. How the PhysicsCommon object works

    master

    The PhysicsCommon class is the central entry point for ReactPhysics3D. It serves three primary roles:

    1. Factory Module: It is used to instantiate physics worlds, collision shapes, and other objects.
    2. Memory Management: It centralizes all memory allocations for the library.
    3. Logging: It contains the logger for library events.

    You must instantiate PhysicsCommon before creating any other physics objects.

    // First you need to create the PhysicsCommon object.
    PhysicsCommon physicsCommon;
    
    // Use it to create a physics world
    PhysicsWorld* world = physicsCommon.createPhysicsWorld();
    
    // Use it to create collision shapes
    SphereShape* sphereShape = physicsCommon.createSphereShape(radius);
  9. How Physics World works: Simulation vs. Collision Testing

    master

    ReactPhysics3D can be used in two primary ways:

    1. Collision Testing (Static): You do not call PhysicsWorld::update(). Instead, you use methods like testOverlap(), testCollision(), or testPointInside() to query the state of bodies. This is useful if you only need to know if objects are touching without simulating motion.
    2. Real-time Simulation (Dynamic): You create RigidBody objects and call PhysicsWorld::update(timeStep) every frame. The engine automatically calculates motion based on forces, collisions, and joint constraints. This is the standard approach for games.
  10. How joints work in ReactPhysics3D

    master

    Joints are used to constrain the motion of rigid bodies relative to each other. A single joint represents a constraint between two rigid bodies. By default, a body has six degrees of freedom (three translation, three rotation); different joint types reduce these degrees of freedom to simulate specific mechanical connections.

    To create a joint, you follow a two-step process:

    1. Create a JointInfo object (e.g., BallAndSocketJointInfo, HingeJointInfo, SliderJointInfo, or FixedJointInfo) containing the necessary parameters like the two rigid bodies, anchor points, and axes.
    2. Call PhysicsWorld::createJoint() with that info object. This method returns a pointer to the created joint object, which you should dynamic_cast to the specific joint type to access its properties and methods.
  11. Create and configure a Physics World

    master

    A PhysicsWorld is the container for all bodies you want to simulate. You create it using a PhysicsCommon object. You can either use default settings or provide a PhysicsWorld::WorldSettings object to customize parameters like gravity, velocity solver iterations, and sleeping behavior at creation time.

    Note: Settings provided during creation are copied. To change settings after creation, use the specific setter methods provided by the PhysicsWorld class API.

    // Create the world settings
    PhysicsWorld::WorldSettings settings;
    settings.defaultVelocitySolverNbIterations = 20;
    settings.isSleepingEnabled = false;
    settings.gravity = Vector3(0, -9.81, 0);
    
    // Create the physics world with your settings
    PhysicsWorld* world = physicsCommon.createPhysicsWorld(settings);