Physics

The physics engine provides a means to create custom animations that are composable, extensible, and natural-feeling. When an animation inspired by some physical phenomenon is desired, and when tweening would be intractable, actually simulating the physics will give better results.

At its core, the physics engine is an update loop that incrementally steps the world forward to reflect the progression of time. Entities that may be placed in the world include different types of physical bodies, including point particles and three-dimensional boxes, and different types of forces and constraints, like gravity, drag, and collision.

The physics engine is its own module entirely. To bind a Famous view to a body in the physics engine, pass the body in as data to the view, and use the body's position and orientation to set the position and rotation of the view's node.

To get started with physics, require the math and physics APIs.

var math = require('famous/math');
var physics = require('famous/physics');

The Engine

Typical use of the physics engine will begin with something like:

var world = new physics.PhysicsEngine(options);

Afterwards, all physical bodies, forces, and constraints will be incorporated into the current engine via world.add(targets).

One may optionally specify a .origin and/or .orientation in the options hash, or later set these via PhysicsEngine#setOrigin and PhysicsEngine#setOrientation. Then for a body b, one may get the position and orientation of b relative to an untranslated origin and unrotation orientation via PhysicsEngine#getTransform(b). If neither the origin or orientation are altered, the position and orientation of the body may be used directly.

The engine is progressed by successively calling PhysicsEngine#update(time) with an increasing timestamp.

The engine will fire 'prestep' and 'poststep' events before and immediately after each tick of the engine. Callbacks for the events can be registered, deregistered, and manually triggered via PhysicsEngine#on , PhysicsEngine#off, and PhysicsEngine#trigger.

Bodies

All physical bodies maintain various quantities like position and orientation, angular and translational velocities and momenta, as well as physical properties including mass, inertia tensors and coefficients of restitution and friction. These properties are set according to the options hash passed to the constructor, which is the only parameter the constructors allow.

Primitives

Particle

var Particle = physics.Particle;
var myParticle = new Particle({mass: 10});

The simplest body, and superclass of all other bodies. All forces and constraints take in instances of Particle or subclasses as their targets. Instances of Particle are considered point-masses, and will not rotate or carry angular momentum, or collide with other Particle's.

Methods provided by Particle.prototype include getters and setters for Particle properties, as well as methods to apply forces and impulses.

The particle will fire 'collision:start' and 'collision:end' at the beginning and end of contact with another body. Callbacks for the events can be registered, deregistered, and manually triggered via Particle#on , Particle#off, and Particle#trigger.

Sphere

var Sphere = physics.Sphere;
var mySphere = new Sphere({mass: 10, radius: 25});

Extends Particle, and represents a sphere shape. Unlike Particle, has non-zero size defined by the user supplied .radius, and has a non-zero inertia tensor.

Sphere.prototype provides getters and setters for radius which will update size and the inertia tensor as side effects.

Here is a very basic physics demo linking a Sphere with a Node. Note how the Sphere is responsible for determining the Node's postion. Click the logo to move the Sphere.

Box

var Box = physics.Box;
var myBox = new Box({mass: 10, size: [100,200,300]});

Extends Particle, and represents a rectangular box shape. Its span is defined by user supplied .size.

Box is implemented using ConvexBodyFactory.

Creating Custom Shapes

ConvexBodyFactory

var Vec3 = math.Vec3;
var ConvexBodyFactory = physics.ConvexBodyFactory;
var CustomPyramid = ConvexBodyFactory([
    new Vec3(100,0,100),
    new Vec3(100,0,-100),
    new Vec3(-100,0,100),
    new Vec3(-100,0,-100),
    new Vec3(0,150,0)
]);
var myPyramid = new CustomPyramid({size: [50, 50, 50], mass: 10});

A class factory. Takes in a ConvexHull object, or computes one from an array of Vec3's, and returns a class extending Particle with inertia tensor and shape reflecting the input geometry. Used to create custom convex physical shapes.

The size and inertia of the object instantiated using the new constructor will reflect the originally defined shape stretched to match the user supplied .size.

Boundaries

Wall

var Wall = physics.Wall;
var rightWall = new Wall({direction: Wall.LEFT}); // bodies coming from the left will collide with the wall
rightWall.setPosition(1000,0,0);

Extends Particle, and represents an infinite, oriented plane. Will not move or rotate, though can be positioned via .setPosition. The plane may be oriented via the .direction enum, which takes an integer between 0 and 5. The relevant values are attached to the Wall constructor, e.g. Wall.UP, or Wall.LEFT.

Exists primarily to provide a wall collider target for the Collision constraint.

Forces

Every frame of the physics engine, forces will apply an acceleration to each of their targets. Some forces take both a source and targets parameter, other just take targets. All forces take an options hash as their last parameter. Forces typically take a .strength option which specifies their strength.

Force

The superclass of all forces. Provides .setOptions which resets the force to reflect a new options hash. The Force superclass would typically not be used or extended directly, instead instantiate one of its subclasses.

Gravity1D

var target = new physics.Particle({mass: 1});
var Gravity1D = physics.Gravity1D;
var gravity = new Gravity1D([target], {direction: Gravity1D.DOWN, strength: 300});

A one dimensional constant gravitational force. Either takes a .direction enum and .constant or an .acceleration Vec3 option.

Gravity3D

var source = new physics.Particle({mass: 100});
var target = new physics.Particle({mass: 1});
var Gravity3D = physics.Gravity3D;
var gravity = new Gravity3D(source, [target], {strength: 300});

An inverse-square gravitational force.

Spring

var source = new physics.Particle({mass: 100});
var target = new physics.Particle({mass: 1});
var Spring = physics.Spring;
var spring = new Spring(source, [target], {period: 1, dampingRatio: 0.5, length: 50});

A spring force. Pulls the targets to within .length of the anchor. If you want to anchor the spring to a specific point of the world, pass in null as the source and specify an .anchor Vec3.

RotationalSpring

var source = new physics.Particle({mass: 100});
var target = new physics.Particle({mass: 1});
var RotationalSpring = physics.RotationalSpring;
var rotationalSpring = new RotationalSpring(source, [target], {period: 1, dampingRatio: 0.5});

A spring-like torque. Applies torque to enforce an orientation. If you want to pull the targets to a specific orientation, pass in null as the source and specify an .anchor Quaternion.

Drag

var target = new physics.Particle({mass: 1});
var Drag = physics.Drag;
var drag = new Drag([target], {strength: 0.4});

A force opposing the translational movement of each of its targets.

RotationalDrag

var target = new physics.Particle({mass: 1});
var RotationalDrag = physics.RotationalDrag;
var rotationalDrag = new RotationalDrag([target], {strength: 0.4});

A force opposing the rotation of each of its targets.

Constraints

Rather than being 'fire and forget' like a force in the engine, each constraint is something that must be solved. Each constraint applies impulses to its targets to correct constraint violations, 'solving' it. The constraints have no knowledge of each other, only knowing what needs to be done to correct themselves. Every constraint is solved multiple times, so as to reduce error that might accumulate over the course of the frame.

Constraint

The constraint superclass. Constraints usually either take a targets parameter, or two body parameters, as well as an option hash. The Constraint superclass would typically not be used or extended directly, instead instantiate one of its subclasses.

Angle

var a = new physics.Box();
var b = new physics.Box();
var Angle = physics.Angle;
var angle = new Angle(a, b);

Applies angular impulses to a and b to preserve the angles between the orientations as they are on instantiation. Does not take an options hash.

Distance

var a = new physics.Particle();
var b = new physics.Particle();
var Distance = physics.Distance;
var distance = new Distance(a, b, {period: 1, dampingRatio: 0.5});

Applies impulses to preserve the distance between the positions of a and b as they are on instantiation. Optionally takes a .length option if an alternate distance is desired.

Direction

var a = new physics.Particle();
var b = new physics.Particle();
var Direction = physics.Direction;
var direction = new Direction(a, b, {period: 1, dampingRatio: 0.5});

Applies impulses to preserve the direction of b from a, i.e. acts to keep a and b on the line traced from a to b.

BallAndSocket

var a = new physics.Box();
var b = new physics.Box();
var BallAndSocket = physics.BallAndSocket;
var hinge = new BallAndSocket(a, b, {anchor: new math.Vec3(100,100,0)});

Applies impulses and angular impulses to preserve the local position of anchor relative to a and relative to b. Imagine a and b skewered with two rods, one with a ball on one end, and one with a socket, where the two rods are connected at anchor.

Hinge

var a = new physics.Box();
var b = new physics.Box();
var Hinge = physics.Hinge;
var hinge = new Hinge(a, b, {anchor: new math.Vec3(100,100,0), axis: new Vec3(0,0,1)});

Similar to the BallAndSocket constraint, but additionally applies angular impulses to constrain a and b to only rotate about axis.

Curve

var target = new physics.Particle();
var Curve = physics.Curve;
function f(x,y,z) {
    return x*x + y*y + z*z - 100*100;
}
function g(x,y,z) {
    return z;
}
var curve = new Curve([target], {period: 1, dampingRatio: 0.5, equation1: f, equation2: g});

Takes the surfaces defined by f(x,y,z) = 0 and g(x,y,z) = 0 and acts to keep the targets on their intersection.

Collision

var a = new physics.Box({size: [50,50,50]});
var b = new physics.Box({size: [50,50,50]});
var rightWall = new physics.Wall({direction: physics.Wall.LEFT});
rightWall.setPosition(1000,0,0);
var Collision = physics.Collision;
var collision = new Collision([a, b, rightWall]); // a and b will bounce off of each other and off of rightWall

Updating the Collision constraint has multiple phases. First, possible intersections are tallied via the broad-phase, which determines what bodies are likely to be intersecting based on their positions in space. Next, whether the bodies are actually colliding is determined, and if so, the exact points of contact are found. Finally, the points of contact are entered into a cache that holds the current points of contact between those two bodies. The resolution step for Collision then solves each contact separately.