3D Constraint Solver (Sequential Impulses)

3D Constraint Solver (Sequential Impulses) - Description


This project is to add constraint physics to my game engine. Constraints are a method to keep a physical rule valid. For example, a joint constraint would keep two objects attached by a hinge together. A non-penetration constraint would keep objects sitting on each other from falling into each other.


A constraint is a function that should be held valid every frame. Constraints in this implementation are always pair-wise.

Joint Position Constraint

To constrain two or more objects to be tied together, such as an arm to an elbow, or links in a chain, a position constraint is used. The constraint is valid if this formula is satisfied:

C = P1 - P2 = 0
where P1 and P2 are the connection points (3D vectors) on the respective objects. This is intuitively correct because two objects are considered connected if the distance between their connection points in the X, Y, and Z directions are all 0. Constraint implementations compute the state of the constraint each frame, apply forces to objects every frame to ensure that these functions are held true.

To hold the constraint valid, a solution is to hold the derivative of the constraint valid. In this case, since the constraint references the position of points on the objects, enforcing the concept that the velocity of the points is always 0 in all directions that violate the constraint will keep the constraint itself valid at all times. In other words, the velocity of the two connected points relative to each other should always be 0.

dC/dt = (v2 + p2_leverArm X object2_angularVelocity) - (v1 + p1_leverArm X object1_angularVelocity)
Where v1 and v2 are the velocities of each object's center of mass, p1 and p2 leverArm is the vector between each object's center of mass and its constraint point, and angularVelocity is the angular velocity of each object's center of mass. This derivative is used to determine the amount of corrective impulse to apply to the two objects.

This is a video showing a sequence of metal rods connected together using position constraints with random forces applied to it

Angle constraint

Angle constraints constraint two bodies to be rotated a set amount relative to each other.

C = Q1 - Q2 = Angle
where Q1 and Q2 are the orientation of the two bodies.

Angle constraints are interesting because they can be used to create motors by varying the target angle of the constraint over time.

This is a video showing a sequence of metal rods connected together using both angle and position constraints. It is combined with inverse kinematics to move the rods as a robot arm -- the angles from the inverse kinematics solution are passed to the constraint solver, and set to be the target angle constraints between each rod, moving them as motors

Non-penetration constraint

Coming soon.

Sequential impulses

Sequential impulses is a method to enforce all constraints in a frame in a consistent manner. Because constraints are only pairwise, and solving for impulse to correct a single constraint could invalidate the correction of another, something must be done to maintain global consistency. Sequential impulses handles this by solving all constraints many times, applying the corrective impulses each iteration, until the error for each constraint converges to as close to 0 as possible.