Skip to content
Ali Shakiba edited this page Feb 2, 2021 · 26 revisions

This document is ported from Box2D documentation with modification for Planck.js with permission from Erin Catto.

Overview

Planck.js is JavaScript rewrite of Box2D C++ library, a 2D rigid body simulation library for games. Programmers can use it in their games to make objects move in realistic ways and make the game world more interactive. From the game engine's point of view, a physics engine is just a system for procedural animation.

In this document Box2D and Planck.js names are used interchangeably.

Prerequisites

In this manual it is assumed you are familiar with basic physics concepts, such as mass, force, torque, and impulses. If not, please first consult Google search and Wikipedia.

Box2D was created as part of a physics tutorial at the Game Developer Conference. You can get these tutorials from the download section of box2d.org.

Since Planck.js is written in JavaScript, you are expected to be experienced in JavaScript programming. Planck.js should not be your first JavaScript programming project!

Scope

This manual covers the majority of the Planck.js API. However, not every aspect is covered. Please look at the examples included with Planck.js to learn more.

Core Concepts

Planck.js works with several fundamental concepts and objects. We briefly define these objects here and more details are given later in this document.

shape

A shape is 2D geometrical object, such as a circle or polygon.

rigid body

A chunk of matter that is so strong that the distance between any two bits of matter on the chunk is constant. They are hard like a diamond. In the following discussion we use body interchangeably with rigid body.

fixture

A fixture binds a shape to a body and adds material properties such as density, friction, and restitution. A fixture puts a shape into the collision system (broad-phase) so that it can collide with other shapes.

constraint

A constraint is a physical connection that removes degrees of freedom from bodies. A 2D body has 3 degrees of freedom (two translation coordinates and one rotation coordinate). If we take a body and pin it to the wall (like a pendulum) we have constrained the body to the wall. At this point the body can only rotate about the pin, so the constraint has removed 2 degrees of freedom.

contact constraint

A special constraint designed to prevent penetration of rigid bodies and to simulate friction and restitution. You do not create contact constraints; they are created automatically by Planck.js.

joint

This is a constraint used to hold two or more bodies together. Planck.js supports several joint types: revolute, prismatic, distance, and more. Some joints may have limits and motors.

joint limit

A joint limit restricts the range of motion of a joint. For example, the human elbow only allows a certain range of angles.

joint motor

A joint motor drives the motion of the connected bodies according to the joint's degrees of freedom. For example, you can use a motor to drive the rotation of an elbow.

world

A physics world is a collection of bodies, fixtures, and constraints that interact together. Planck.js supports the creation of multiple worlds, but this is usually not necessary.

solver

The physics world has a solver that is used to advance time and to resolve contact and joint constraints. The Planck.js solver is a high performance iterative solver that operates in order N time, where N is the number of constraints.

continuous collision

The solver advances bodies in time using discrete time steps. Without intervention this can lead to tunneling. Tunneling Effect

Planck.js contains specialized algorithms to deal with tunneling. First, the collision algorithms can interpolate the motion of two bodies to find the first time of impact (TOI). Second, there is a sub-stepping solver that moves bodies to their first time of impact and then resolves the collision.

Units

Planck.js works with floating point numbers and tolerances have to be used to make Planck.js perform well. These tolerances have been tuned to work well with meters-kilogram-second (MKS) units. In particular, Planck.js has been tuned to work well with moving shapes between 0.1 and 10 meters. So this means objects between soup cans and buses in size should work well. Static shapes may be up to 50 meters long without trouble.

Being a 2D physics engine, it is tempting to use pixels as your units. Unfortunately this will lead to a poor simulation and possibly weird behavior. An object of length 200 pixels would be seen by Planck.js as the size of a 45 story building.

Caution: Planck.js is tuned for MKS units. Keep the size of moving objects roughly between 0.1 and 10 meters. You'll need to use some scaling system when you render your environment and actors. The Planck.js testbed does this by using stage.js viewbox transform. DO NOT USE PIXELS.

It is best to think of Planck.js bodies as moving billboards upon which you attach your artwork. The billboard may move in a unit system of meters, but you can convert that to pixel coordinates with a simple scaling factor. You can then use those pixel coordinates to place your sprites, etc. You can also account for flipped coordinate axes.

Planck.js uses radians for angles. The body rotation is stored in radians and may grow unbounded. Consider normalizing the angle of your bodies if the magnitude of the angle becomes too large (use body.setAngle).

Caution: Planck.js uses radians, not degrees.

Settings

Settings file defines several constants, these are all documented in the same file. Normally you do not need to adjust these constants.

Planck.js uses floating point math for collision and simulation. Due to round-off error some numerical tolerances are defined. Some tolerances are absolute and some are relative. Absolute tolerances use MKS units.

Math

Planck.js includes a simple small vector and matrix module in lib/common directory. This has been designed to suit the internal needs of Planck.js and the API. All the members are exposed, so you may use them freely in your application.

The math classes is kept simple to make Planck.js easy to port and maintain.

Dynamics

The dynamics classes are the most complex part of Planck.js and is the part you likely interact with the most. The dynamics classes sit on top of Math and Collision classes, so you should be somewhat familiar with those by now.

The Dynamics classes include:

  • fixture class
  • rigid body class
  • contact class
  • joint classes
  • world class

There are many dependencies between these classes so it is difficult to describe one class without referring to another. In the following, you may see some references to classes that have not been described yet. Therefore, you may want to quickly skim this chapter before reading it closely.

Limitations

Planck.js uses several approximations to simulate rigid body physics efficiently. This brings some limitations.

Here are the current limitations:

  1. Stacking heavy bodies on top of much lighter bodies is not stable. Stability degrades as the mass ratio passes 10:1.
  2. Chains of bodies connected by joints may stretch if a lighter body is supporting a heavier body. For example, a wrecking ball connect to a chain of light weight bodies may not be stable. Stability degrades as the mass ratio passes 10:1.
  3. There is typically around 0.5cm of slop in shape versus shape collision.
  4. Continuous collision does not handle joints. So you may see joint stretching on fast moving objects.
  5. Planck.js uses the symplectic Euler integration scheme. It does not reproduce parabolic motion of projectiles and has only first-order accuracy. However it is fast and has good stability.
  6. Planck.js uses an iterative solver to provide real-time performance. You will not get precisely rigid collisions or pixel perfect accuracy. Increasing the iterations will improve accuracy.

References

  • Erin Catto's Publications
  • Collision Detection in Interactive 3D Environments, Gino van den Bergen, 2004
  • Real-Time Collision Detection, Christer Ericson, 2005
Clone this wiki locally