Chipmunk v2.5 : Scheme Documentation tool
1 Introduction
Chipmunk is a 2D rigid body physics library distributed under the MIT license. It can be compiled in order to use it with Racket. The Foreign Function Interface to the C Chipmunk API has been released by Jay McCarthy on Planet.
This page of documentation is a mix between several pieces, old and new, thanks to Charlélie Bouvier. It should not be considered as 100% reliable ! The Chipmuk version used here is rather old and not much documented. Be happy, do better...

There are 4 basic things you need to know about in order to work with Chipmunk:
Rigid Bodies: A rigid body holds the physical properties of an object. (mass, position, rotation, velocity, etc.) It does not have a shape by itself. If you’ve done physics with particles before, rigid bodies differ in that they are able to rotate.
Collision Shapes: By attaching shapes to bodies, you can define the a body’s shape. You can attach as many shapes to a single body as you need to in order to define a complex shape. Shapes contain the surface properties of an object such as how much friction or elasticity it has.
Constraints/Joints: Constraints and joints describe how bodies are attached to each other.
Spaces: Spaces are the basic simulation unit in Chipmunk. You add bodies, shapes and joints to a space, and then update the space as a whole.
2 How to Install Chipmunk library for Racket on Linux
Make sure you have make and cmake installed on your system.
> su root or > sudo su |
> apt-get update |
> apt-get upgrade |
> apt-get install make cmake subversion |
To compile Chipmunk Physics, you’ll need some more libraries :
> su root or > sudo su |
> apt-get update |
> apt-get upgrade |
> apt-get install freeglut3 freeglut3-dev glutg3 glutg3-dev libgl1-mesa-dev |
libglu1-mesa-dev libglut3 libglut3-dev libice-dev libpthread-stubs0 |
libpthread-stubs0-dev libsm-dev libx11-dev libxau-dev libxaw7-dev |
libxcb-xlib0-dev libxcb1-dev libxdmcp-dev libxext-dev libxmu-dev |
libxmu-headers libxpm-dev libxi-dev libxt-dev mesa-common-dev |
x11proto-core-dev x11proto-input-dev x11proto-kb-dev x11proto-xext-dev |
xlibmesa-gl-dev xtrans-dev |
Within a Unix shell, create a Chimpunk directory, and cd to that directory. Then download the Chipmunk (old v2) sources :
> su root or > sudo su |
> mkdir ~/Chipmunk |
> cd ~/Chipmunk |
> svn co -r 194 http://chipmunk-physics.googlecode.com/svn/trunk/ . |
> cmake . |
> make |
When you compile chipmunk with make, the shell will produce an error with the chipmunk demos, please ignore.
Link the dynamic library :
> cd [RacketPath]/lib/racket/ |
> ln -s chipmunk/src/libchipmunk.so.4 ./libchipmunk.so |
> ln -s chipmunk/src/libchipmunk.dylib . |
> chmod a+x libchipmunk.so |
> chmod a+x libchipmunk.dylib |
3 How to Install Chipmunk library for Racket on MacOS-X
You must have make and cmake installed on your system. On Mac, make sure you have MacPorts installed for the command port. Install MacPorts if not. Then :
$ sudo port install cmake |
I suppose that you have installed the developer package and X11 from the MacOS-X install disk, many libs should be already available. Within a Unix Terminal, cd to your [RacketPath]/lib directory, then create a chimpunk directory, and cd to that directory. Then download the Chipmunk (old v2) sources :
$ svn co -r 194 http://chipmunk-physics.googlecode.com/svn/trunk/ . |
$ cmake . |
$ make |
$ cd .. |
Now we are back in the [RacketPath]/lib directory. Build a symbolic link :
$ ln -s chipmunk/src/libchipmunk.4.dylib ./libchipmunk.dylib |
4 Getting Started with Chipmunk
4.1 Initialization
To use chipmunk use this require :
(require (planet jaymccarthy/chipmunk))
At the top of your program, you must initialize Chipmunk. Otherwise you will crash as soon as the first collision happens :
(cpInitChipmunk)
And then you must reset the ShapeIdCounter :
(cpResetShapeIdCounter)
Chipmunk keeps a counter so that every new shape is given a unique hash value to be used in the spatial hash. Because this affects the order in which the collisions are found and handled, you should reset the shape counter every time you populate a space with new shapes. If you don’t, there might be (very) slight differences in the simulation.
4.2 The different Chipmunk’s main functions.
First of all, Chipmunk uses double precision floating point numbers throughout it’s calculations by default.
Then you have to use floating point numbers like this :
(define SPACE (cpSpaceNew))
(set-cpSpace-gravity! SPACE (cpv 0.0 700.0))
You also have to use Scheme inexact numbers for your space’s size when you use it in some functions. Example :
(define SIZE 400.0)
The main types of objects are denoted by :
cpVect - Create and manipulate 2D vectors.
cpBB - Create and manipulate 2D axis-aligned bounding boxes.
vpBody - Create and work with rigid bodies.
cpShape - Attach collision shapes to rigid bodies.
cpSpace - Create a space to put your objects into and simulate them.
cpConstraint - Create joints and other constraints.
5 Chipmunk Vectors : cpVect
5.1 cpVect constructors
| (cpv x y) → cpVect? |
| x : cpFloat? |
| y : cpFloat? |
Returns a new Chipmunk Vector. Example:
(define v1 (cpv 5.0 3.0))
| (cpvzero) → cpVect? |
Same as (cpv 0.0 0.0).
5.2 cpVect fields access
Chipmunk uses structs, so to access to the fields you will use struct-field like this :
| (cpVect-x p) → cpFloat? |
| p : pos? |
Returns the x field from the p field of a body. Example:
(define x (cpVect-x (cpBody-p BALL)))
| (cpVect-y p) → cpFloat? |
| p : pos? |
Returns the y field from the p field of a body. Example:
(define y (cpVect-y (cpBody-p BALL)))
5.3 cpVect operations
| (cpvadd v ...) → cpVect? |
| v : cpVect? |
Returns the addition of the cpVects. Example:
(define vAB (cpvadd v1 v2))
| (cpvsub v1 v2) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
Returns the substraction of the two cpVect. Example:
(define vAB (cpvsub v1 v2))
| (cpvneg v) → cpVect? |
| v : cpVect? |
Negates a Chipmunk Vector. Example:
(define nv (cpvneg v))
| (cpvmult v s) → cpVect? |
| v : cpVect? |
| s : cpFloat? |
Scalar multiplication. Example:
(define v6 (cpvmult v 6.0))
| (cpvdot v1 v2) → cpFloat? |
| v1 : cpVect? |
| v2 : cpVect? |
Vector dot product. Example:
(define vdAB (cpvdot v1 v2))
| (cpvcross v1 v2) → cpFloat? |
| v1 : cpVect? |
| v2 : cpVect? |
2D vector cross product analog. The cross product of 2D vectors results in a 3D vector with only a z component. This function returns the magnitude of the z value. Example:
(define vcrossAB (cpvcross v1 v2))
| (cpvperp v) → cpVect? |
| v : cpVect? |
Returns a perpendicular vector (90 degree rotation). Example:
(define vperp (cpvperp v))
| (cpvrperp v) → cpVect? |
| v : cpVect? |
Returns a perpendicular vector (-90 degree rotation). Example:
(define vrperp (cpvrperp v))
| (cpvproject v1 v2) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
Returns the vector projection of v1 onto v2. Example:
(define vprojectAB (cpvproject v1 v2))
| (cpvrotate v1 v2) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
Uses complex multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector. Example:
(define vrotateAB (cpvrotate v1 v2))
| (cpvunrotate v1 v2) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
Inverse of (cpvrotate). Example:
(define vrotateAB (cpvunrotate v1 v2))
| (cpvlength v) → cpFloat? |
| v : cpVect? |
Returns the length of v. Example:
(define vL (cpvlength v))
| (cpvlengthsq v) → cpFloat? |
| v : cpVect? |
Returns the squared length of v. Faster than (cpvlength) when you only need to compare lengths. Example:
(define vL2 (cpvlengthsq v))
| (cpvslerp v1 v2 t) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
| t : cpFloat? |
Linearly interpolate between v1 and v2. Example:
(define vlerpABt (cpvunrotate v1 v2 t))
| (cpvlerpconst v1 v2 d) → cpVect? |
| v1 : cpVect? |
| v2 : cpVect? |
| d : cpFloat? |
Linearly interpolate between v1 towards v2 by distance d. Example:
(define vlerpcABd (cpvunrotate v1 v2 d))
| (cpvclamp v len) → cpVect? |
| v : cpVect? |
| len : cpFloat? |
Clamp v to length len. Example:
(define vclen (cpvclamp v len))
| (cpvnormalize v) → cpVect? |
| v : cpVect? |
Returns a normalized copy of v or cpvzero if v was already cpvzero. Protects against divide by zero errors. Example:
(define vnorm (cpvnormalize v))
| (cpvdist v1 v2) → cpFloat? |
| v1 : cpVect? |
| v2 : cpVect? |
Returns the distance between v1 and v2. Example:
(define dv1v2 (cpvdist v1 v2))
| (cpvdistsq v1 v2) → cpFloat? |
| v1 : cpVect? |
| v2 : cpVect? |
Returns the squared distance between v1 and v2. Faster than (cpvdist) when you only need to compare distances. Example:
(define d2v1v2 (cpvdistsq v1 v2))
| (cpvnear v1 v2) → boolean? |
| v1 : cpVect? |
| v2 : cpVect? |
Returns true if the distance between v1 and v2 is less than dist. Example:
(define nearv1v2? (cpvnear v1 v2))
| (cpvforangle a) → cpVect? |
| a : cpFloat? |
Returns the unit length vector for the given angle (in radians). Example:
(define cpv20rad (cpvforangle 20))
| (cpvtoangle v) → cpFloat? |
| v : cpVect? |
Returns the angular direction v is pointing in (in radians). Example:
(define cpv1angle (cpvtoangle v1))
| (cpvstr v) → string? |
| v : cpVect? |
Returns a string representation of v. Intended mostly for debugging purposes and not production use. NOTE: The string points to a static local and is reset every time the function is called. If you want to print more than one vector you will have to split up your printing onto separate lines. Example:
(define vtoString (cpvstr v))
6 Chipmunk bounding boxes : cpBB
6.1 cpBB : structure
l Left.
b Bottom.
r Right.
t Top.
Simple bounding box struct. Stored as left, bottom, right, and top fields.
6.2 cpBB : Constructors
| (cpBBNew l b r t) → cpBB? |
| l : cpFloat? |
| b : cpFloat? |
| r : cpFloat? |
| t : cpFloat? |
Convenience constructor for cpBB structs. Like cpv this function returns a copy and not a malloced pointer. Example:
(define bb1 (cpBBNew l b r t))
6.3 cpBB : fields access
Chipmunk uses structs, then to access to the fields you may use struct-field like this :
(define l (cpBB-l bb))
6.4 cpBB : Operations
| (cpBBintersects bb1 bb2) → boolean? |
| bb1 : cpBB? |
| bb2 : cpBB? |
Returns true if the bounding boxes intersect. Example:
(define interab? (cpBBintersects a b))
| (cpBBintersects bb1 bb2) → boolean? |
| bb1 : cpBB? |
| bb2 : cpBB? |
Returns true if the bounding boxes intersect. Example:
(define interab? (cpBBintersects a b))
| (cpBBcontainsBB bb other) → boolean? |
| bb : cpBB? |
| other : cpBB? |
Returns true if bb completely contains other. Example:
(define containsbb? (cpBBintersects bb other))
| (cpBBcontainsBB bb other) → boolean? |
| bb : cpBB? |
| other : cpBB? |
Returns true if bb completely contains other. Example:
(define containsbb? (cpBBintersects bb other))
| (cpBBcontainsVect bb v) → boolean? |
| bb : cpBB? |
| v : cpVect? |
Returns true if bb contains v. Example:
(define containsv? (cpBBintersects bb b))
| (cpBBmerge bb1 bb2) → number? |
| bb1 : cpBB? |
| bb2 : cpBB? |
Return the minimal bounding box that contains both bb1 and bb2. Example:
(define mergeab (cpBBmerge a b))
| (cpBBexpand bb v) → number? |
| bb : cpBB? |
| v : cpVect? |
Return the minimal bounding box that contains both bb and v. Example:
(define expandvbb (cpBBexpand bb v))
| (cpBBClampVect bb v) → cpVect? |
| bb : cpBB? |
| v : cpVect? |
Returns a copy of v clamped to the bounding box. Example:
(define clampbbv (cpBBClampVect bb v))
| (cpBBClampVect bb v) → cpVect? |
| bb : cpBB? |
| v : cpVect? |
Returns a copy of v clamped to the bounding box. Example:
(define clampbbv (cpBBClampVect bb v))
| (cpBBWrapVect bb v) → cpVect? |
| bb : cpBB? |
| v : cpVect? |
Returns a copy of v wrapped to the bounding box. Example:
(define wrappedvbb (cpBBWrapVect bb v))
7 Chipmunk rigid bodies : cpBody
7.1 cpBody : structure
m Mass : cpFloat
m_inv 1/Mass : cpFloat
i Moment of inertia : cpFloat
i_inv 1/i : cpFloat
p position : cpVect
v velocity : cpVect
f force : cpVect
a angle in radians : cpFloat
w angular velocity : cpFloat
t torque : cpFloat
rot rotation of the body as a unit length vector : cpVect
Getters are ok, avoid to use setters. Example:
(define alpha (cpBody-a BALL))
7.2 cpBody : Constructors
| (cpBodyNew m i) → cpBody |
| m : cpFloat? |
| i : cpFloat? |
m and i are the mass and moment of inertia for the body.
Example:
(define BALL (cpBodyNew 20.0 (cpMomentForCircle 20.0 0.0 15.0 cpvzero)))
| (cpBodyInit body m i) → cpBody |
| body : cpBody? |
| m : cpFloat? |
| i : cpFloat? |
m and i are the mass and moment of inertia for the body. Example:
(cpBodyInit BALL 20.0 (cpMomentForCircle 20.0 0.0 15.0 cpvzero))
| (cpBodyDestroy body) → void |
| body : cpBody? |
Destroy the cpBody body. Example:
(cpBodyDestroy BALL)
| (cpBodyFree body) → void |
| body : cpBody? |
Standard set of Chipmunk memory management function to free memory. Example:
(cpBodyFree BALL)
7.3 cpBody : Moments of Inertia
| (cpMomentForCircle m r1 r2 offset) → cpFloat? |
| m : cpFloat? |
| r1 : cpFloat? |
| r2 : cpFloat? |
| offset : cpVect? |
Calculate the moment of inertia for a hollow circle, r1 and r2 are the inner and outer diameters in no particular order. (A solid circle has an inner diameter of 0)
| (cpMomentForSegment m a b) → cpFloat? |
| m : cpFloat? |
| a : cpVect? |
| b : cpVect? |
Calculate the moment of inertia for a line segment. The endpoints a and b are relative to the body.
| (cpMomentForPoly m numVerts verts offset) → cpFloat? |
| m : cpFloat? |
| numVerts : integer? |
| verts : vect-of-cpVect? |
| offset : cpVect? |
Calculate the moment of inertia for a solid polygon shape assuming it’s center of gravity is at it’s centroid. The offset is added to each vertex.
7.4 cpBody : Integration Functions
| (cpBodySlew body pos dt) → void |
| body : cpBody? |
| pos : cpVect? |
| dt : cpFloat? |
Modify the velocity of the body so that it will move to the specified absolute coordinates in the next timestep. Intended for objects that are moved manually with a custom velocity integration function. Example:
(cpBodySlew Ball (cpv (cpVect-x (cpBody-p Ball)) (cpVect-y (cpBody-p Ball))) 20)
| ||||||||||||||||||||||||||||
| body : cpBody? | ||||||||||||||||||||||||||||
| gravity : cpVect? | ||||||||||||||||||||||||||||
| damping : cpFloat? | ||||||||||||||||||||||||||||
| dt : cpFloat? |
Default rigid body velocity integration function. Updates the velocity of the body using Euler integration. Example:
(cpBodyUpdateVelocity BALL (cpv 5.0 3.0) 10.0 20.0)
| (cpBodyUpdatePosition body dt) → void |
| body : cpBody? |
| dt : cpFloat? |
Default rigid body position integration function. Updates the position of the body using Euler integration. Unlike the velocity function, it’s unlikely you’ll want to override this function. If you do, make sure you understand it’s source code as it’s an important part of the collision/joint correction process. Example:
(cpBodyUpdatePosition BALL 20.0)
7.5 Coordinate Conversion Functions
| (cpBodyLocal2World body v) → cpVect? |
| body : cpBody? |
| v : cpVect? |
Convert from body local coordinates to world space coordinates. Example:
(cpBodyLocal2World BALL (cpv 5.0 3.0))
| (cpBodyWorld2Local body v) → cpVect? |
| body : cpBody? |
| v : cpVect? |
Convert from body local coordinates to world space coordinates. Example:
(cpBodyWorld2Local BALL (cpv 5.0 3.0))
7.6 Applying Forces and Torques
| (cpBodyApplyImpulse body j r) → void |
| body : cpBody? |
| j : cpVect? |
| r : cpVect? |
Apply the impulse j to body at a relative offset (important!) r from the center of gravity. Both r and j are in world coordinates. Example:
(cpBodyApplyImpulse BALL (cpv 5.0 3.0) (cpv 5.0 3.0))
| (cpBodyResetForces body) → void |
| body : cpBody? |
Zero both the forces and torques accumulated on body. Example:
(cpBodyResetForces BALL)
| (cpBodyApplyForce body f r) → void |
| body : cpBody? |
| f : cpVect? |
| r : cpVect? |
Apply (accumulate) the force f on body at a relative offset (important!) r from the center of gravity. Both r and f are in world coordinates. Example:
(cpBodyApplyImpulse BALL (cpv 5.0 3.0) (cpv 5.0 3.0))
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| a : cpBody? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b : cpBody | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchr1 : cpVect? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchr2 : cpVect? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rlen : cpFloat? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| k : cpFloat? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dmp : cpFloat? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dt : cpFloat? |
Apply a spring force between bodies a and b at anchors anchr1 and anchr2 respectively k is the spring constant Young’s modulus, rlen is the rest length of the spring, dmp is the damping constant (force/velocity), and dt is the time step to apply the force over. Note: not solving the damping forces in the impulse solver causes problems with large damping values. There is a new constraint type cpDampedSpring that should be used instead. Example:
(cpBodyApplyImpulse BALL1 BALL2 (cpv 5.0 3.0) (cpv 5.0 3.0) 2.0 2.0 20.0)
7.7 cpBody : Notes
Use forces to modify the rigid bodies if possible. This is likely to be the most stable.
Modifying a body’s velocity shouldn’t necessarily be avoided, but applying large changes can cause strange results in the simulation. Experiment freely, but be warned.
Don’t modify a body’s position every step unless you really know what you are doing. Otherwise you’re likely to get the position/velocity badly out of sync.
8 Chipmunk Collision Shapes : cpShape
8.1 cpShape : structure
bb : cpBB. The bounding box of the shape. Only guaranteed to be valid after cpShapeCacheBB() or cpSpaceStep() is called. Moving a body that a shape is connected to does not update it’s bounding box.
sensor : boolean. A boolean value if this shape is a sensor or not. Sensors only call collision callbacks, and never generate real collisions.
collision_type. A user definable field, see the collision pair function section below for more information.
group: Shapes in the same non-zero group do not generate collisions. Useful when creating an object out of many shapes that you don’t want to self collide. Defaults to 0.
layers: Shapes only collide if they are in the same bit-planes. i.e. (a->layers & b->layers) != 0 By default, a shape occupies all 32 bit-planes.
data. A user definable field.
body : cpBody. The rigid body the shape is attached to.
e : float. Elasticity of the shape. A value of 0.0 gives no bounce, while a value of 1.0 will give a "perfect" bounce. However due to inaccuracies in the simulation using 1.0 or greater is not recommended. See the notes at the end of the section.
u : float. Friction coefficient. Chipmunk uses the Coulomb friction model, a value of 0.0 is frictionless. Tables of friction coefficients. See the notes at the end of the section.
surface_v : cpVect. The surface velocity of the object. Useful for creating conveyor belts or players that move around. This value is only used when calculating friction, not resolving the collision.
8.2 cpShape : Operations
| (cpShapeCacheBB shape) → cpBB |
| shape : cpShape? |
Updates and returns the bounding box of shape. Example:
(cpShapeCacheBB shape)
| (cpShapeResetShapeIdCounter) → void |
Example:
(cpShapeResetShapeIdCounter)
8.3 cpShape : Types
8.3.1 cpShape : Circle Shapes
| (cpCircleShapeNew body radius offset) → cpShape? |
| body : cpBody? |
| radius : cpFloat? |
| offset : cpFloat? |
Creates a new circle attached to the body.
body is the body to attach the circle to, offset is the offset from the body’s center of gravity in body local coordinates. Example:
(cpCircleShapeNew body 15.0 cpvzero)
| (cpCircleShapeInit circle body offset radius) → cpShape? |
| circle : cpCircleShape? |
| body : cpBody? |
| offset : cpVect? |
| radius : cpFloat? |
Initilization of a cpCircleShape circle.
body is the body to attach the circle to, offset is the offset from the body’s center of gravity in body local coordinates. Example:
(cpCircleShapeInit circle body (cpv 5.0 3.0) cpvzero)
8.3.2 cpShape : Segment Shapes
| (cpSegmentShapeNew body a b radius) → cpShape? |
| body : cpBody? |
| a : cpVect? |
| b : cpVect? |
| radius : cpFloat? |
Creates a new Segment attached to the body.
body is the body to attach the segment to, a and b are the endpoints, and radius is the thickness of the segment. Example:
(cpSegmentShapeNew body (cpv 5.0 0.0) (cpv 0.0 5.0) 1.0)
| (cpSegmentShapeInit seg body a b radius) → cpShape? |
| seg : cpSegmentShape? |
| body : cpBody? |
| a : cpVect? |
| b : cpVect? |
| radius : cpFloat? |
Initilization of a cpSegmentShape seg. body is the body to attach the segment to, a and b are the endpoints, and radius is the thickness of the segment.
Example:
(cpSegmentShapeInit segment body (cpv 5.0 0.0) (cpv 0.0 5.0) 1.0)
8.3.3 cpShape : Polygon Shapes
| (cpPolyShapeNew body verts offset) → cpShape? |
| body : cpBody? |
| verts : vect-of-cpVect? |
| offset : cpVect? |
Creates a new Polygone attached to the body. body is the body to attach the polygone to, verts is a vect of cpVect’s defining a convex hull with a counter-clockwise (!) winding, offset is the offset from the body’s center of gravity in body local coordinates. An assertion will be thrown the vertexes are not convex or do not have a counter-clockwise winding.
Example:
(cpPolyShapeNew body (vector (cpv 0.0 0.0) (cpv 5.0 0.0) (cpv 5.0 3.0) (cpv 0.0 5.0) (cpv 3.0 5.0)) (cpv 1.0 1.0))
| (cpPolyShapeInit poly body verts offset) → cpShape? |
| poly : cpShapePoly? |
| body : cpBody? |
| verts : vect-of-cpVect? |
| offset : cpVect? |
Creates a new polygon attached to the body. verts is a vect of cpVect’s defining a convex hull with a counter-clockwise winding, offset is the offset from the body’s center of gravity in body local coordinates. An assertion will be thrown the vertexes are not convex or do not have a counter-clockwise winding.
Example:
(cpPolyShapeInit poly body (vector (cpv 0.0 0.0) (cpv 5.0 0.0) (cpv 5.0 3.0) (cpv 0.0 5.0) (cpv 3.0 5.0)) (cpv 1.0 1.0))
| (cpPolyShapeGetNumVerts poly) → non-negative-integer? |
| poly : cpPolyShape? |
Getter for Polygone shape numVerts. Example:
(cpPolyShapeGetNumVerts poly)
| (cpPolyShapeGetVert poly) → vector? |
| poly : cpPolyShape? |
Getter for Polygone shape Vert. Example:
(cpPolyShapeGetNumVerts poly)
8.4 cpShape : Notes
You can attach multiple collision shapes to a rigid body. This should allow you to create almost any shape you could possibly need.
Shapes attached to the same rigid body will never generate collisions. You don’t have to worry about overlap when attaching multiple shapes to a rigid body.
The amount of elasticity applied during a collision is determined by multiplying the elasticity of both shapes together. The same is done for determining the friction. If you want to override this default behavior, you can do so inside of a preSolve collision callback. See the section on CollisionCallbacks for more information.
Make sure you add both the body and it’s collision shapes to a space. The exception is when you want to have a static body or a body that you integrate yourself. In that case, only add the shape.
9 Chipmunk Joints : cpJoint
There are currently 4 kinds of joints:
Pin Joints connect two rigid bodies with a solid pin or rod. It keeps the anchor points at a set distance from one another.
Slide Joints are like pin joints, but have a minimum and maximum distance. A chain could be modeled using this joint. It keeps the anchor points from getting to far apart, but will allow them to get closer together.
Pivot Joints simply allow two objects to pivot about a single point.
Groove Joints allows attaching an object to another by a groove.
9.1 cpJoint : Constructor
| (cpPinJointNew a b anchr1 anchr2) → cpJoint? |
| a : cpBody? |
| b : cpBody? |
| anchr1 : cpvect? |
| anchr2 : cpvect? |
Returns a new pin joint connecting bodies a and b with anchors at points anchr1 and anchr2.
| (cpSlideJointNew a b anchr1 anchr2 min max) → cpJoint? |
| a : cpBody? |
| b : cpBody? |
| anchr1 : cpvect? |
| anchr2 : cpvect? |
| min : cpFloat? |
| max : cpFloat |
Returns a new slide joint connecting bodies a and b with anchors at points anchr1 and anchr2, min and max are the allowed distances of the anchor points.
| (cpPivotJointNew a b pivot) → cpJoint? |
| a : cpBody? |
| b : cpBody? |
| pivot : cpvect? |
Returns a new pivot joint connecting bodies a and b. pivot is the point in world coordinates of the pivot. Because the pivot location is given in world coordinates, you must have the bodies moved into the correct positions already.
| |||||||||||||||||||||||||||||||||||
| a : cpBody? | |||||||||||||||||||||||||||||||||||
| b : cpBody? | |||||||||||||||||||||||||||||||||||
| groove_a : cpvect? | |||||||||||||||||||||||||||||||||||
| groove_b : cpvect? | |||||||||||||||||||||||||||||||||||
| anchr2 : cpVect? |
The groove goes from groove_a to groove_b on body a, and the pivot is attached to anchr2 on body b. All coordinates are body local.
9.2 cpJoint : Notes
You can add multiple joints between two bodies, but make sure that they don’t fight. It can cause the bodies to explode.
Make sure you add both of the connected bodies and the joint to a space.
10 Chipmunk spaces: cpSpace
10.1 cpSpace : structure
iterations : int. The number of iterations to use when solving constraints (collisions and joints). Defaults to 10.
gravity : cpVect. The amount of gravity applied to the system.
damping : float. The amount of viscous damping applied to the system. A value of 0.9 means that each body will lose 10% of it’s velocity per second. Defaults to 1. Like gravity can be overridden on a per body basis.
For example, to set the gravity of the space SPACE, just set it’s gravity field :
(set-cpSpace-gravity! SPACE 400.0)
10.2 What are iterations and why should I care ?
Chipmunk uses an iterative solver to figure out the forces between objects in the space. What this means is that it builds a big list of all of the collisions, joints, and other constraints between the bodies and makes several passes over the list considering each one individually. The number of passes it makes is the iteration count, and each iteration makes the solution more accurate. If you use too many iterations, the physics should look nice and solid, but may use up too much CPU time. If you use too few iterations, the simulation may seem mushy or bouncy when the objects should be solid. Setting the number of iterations lets you balance between CPU usage and the accuracy of the physics. Chipmunk’s default of 10 iterations is sufficient for most simple games.
10.3 cpSpace : constructor
| (cpSpaceNew) → cpSpace? |
Returns a new space. The number of iterations used for solving constraints defaults to 10. Example :
(define SPACE (cpSpaceNew))
10.4 cpSpace : operations
| (cpSpaceAddShape space shape) → void |
| space : cpSpace? |
| shape : cpShape? |
| (cpSpaceAddStaticShape space shape) → void |
| space : cpSpace? |
| shape : cpShape? |
| (cpSpaceAddBody space body) → void |
| space : cpSpace? |
| body : cpBody? |
| (cpSpaceAddJoint space joint) → void |
| space : cpSpace? |
| joint : cpJoint? |
| (cpSpaceRemoveShape space shape) → void |
| space : cpSpace? |
| shape : cpShape? |
| (cpSpaceRemoveStaticShape space shape) → void |
| space : cpSpace? |
| shape : cpShape? |
| (cpSpaceRemoveBody space body) → void |
| space : cpSpace? |
| body : cpBody? |
| (cpSpaceRemoveJoint space joint) → void |
| space : cpSpace? |
| joint : cpJoint? |
These functions add and remove shapes, bodies and joints from space. Only add a shape as a static shape if it does not move.
| (cpSpaceResizeStaticHash space dim count) → void |
| space : cpSpace? |
| dim : float? |
| count : non-negative-integer? |
| (cpSpaceResizeActiveHash space dim count) → void |
| space : cpSpace? |
| dim : float? |
| count : non-negative-integer? |
The spatial hashes used by Chipmunk’s collision detection are fairly size sensitive. dim is the size of the hash cells. Setting dim to the average objects size is likely to give the best performance. count is the suggested minimum number of cells in the hash table. Bigger is better, but only to a point. Setting count to ~10x the number of objects in the hash is probably a good starting point. By default, dim is 100.0, and count is 1000.
| (cpSpaceRehashStatic space) → void |
| space : cpSpace? |
Rehashes the shapes in the static spatial hash. You only need to call this if you move one of the static shapes.
| (cpSpaceStep space dt) → void |
| space : cpSpace? |
| dt : float? |
Update the space for the given time step. Using a fixed time step is highly recommended. Doing so will increase the efficiency of the contact persistence, requiring an order of magnitude fewer iterations to resolve the collisions in the usual case.
10.5 cpSpace : Notes
When removing objects from the space, make sure you remove any other objects that reference it. For instance, when you remove a body, remove the joints and shapes attached to it.
The number of iterations, and the size of the time step determine the quality of the simulation. More iterations, or smaller time steps increase the quality.
Because static shapes are only rehashed when you request it, it’s possible to use a much higher count argument to cpHashResizeStaticHash than to cpHashResizeStaticHash. Doing so will use more memory though.
10.6 Mysteries of cpSpaceStep explained
The cpSpaceStep function is really the workhorse of Chipmunk. So what exactly does it do?
Persistent contacts with a stamp that is out of date by more than cp_contact_persistence are filtered out. Velocities of all rigid bodies in the space are integrated using cpBodyUpdateVelocity. All active shapes have their bounding boxes calculated and cached. Collisions between the active shapes and static shapes are found. (collision pair functions are called) Collisions between the active shapes are found. (collision pair functions are called) Information about all constraints (collisions and joints) is pre-calculated. Impulses are found and applied to solve all constraints (joints and collisions). Positions of all rigid bodies in the space are integrated using cpBodyUpdatePosition. Chipmunk does a lot of processing on the shapes in the system in order to provide robust and fast collision detection, but the same is not true of the rigid bodies. Really all cpSpaceStep does to the bodies in the system is to integrate them and apply impulses to them.
The integration step is really just for convenience. If you integrate the velocity of your rigid bodies before calling cpSpaceStep and integrate their positions afterward, you don’t have to add them to the space at all. In fact, there are good reasons for not doing so. All bodies in the space are integrated using the same gravity and damping, and this prevents you from providing interesting objects such as moving platforms.
If you are going to do the integration for your rigid bodies manually, I would highly recommend that you use cpBodyUpdatePosition to integrate the position of the objects and only integrate the velocity. cpBodyUpdatePosition is a required step for penetration resolution, and weird things could happen if it’s not called. Chipmunk uses Euler integration, so calculating the velocity required to move a body to a specific position is trivial if that is what you wish to do.
11 Collision pair functions, groups, and layers
There are three ways that you can specify which shapes are allowed to collide in Chipmunk: collision pair functions, groups, and layers. What are their intended purposes?
Collision pair functions : More than just a callback, collision pair functions can conditionally allow a collision between two shapes. This is the only choice if you need to perform some logic based on the shapes or contact information before deciding to allow the collision.
Groups : Groups filter out collisions between objects in the same non-zero groups. A good example of when groups would be useful is to create a multi-body, multi-shape object such as a ragdoll. You don’t want the parts of the ragdoll to collide with itself, but you do want it to collide with other ragdolls.
Layers : Layers are another way of grouping shapes. Collision between shapes that don’t occupy one or more of the same layers are filtered out. Layers are implemented using a bitmask on an unsigned long, so there are up to 32 layers available.
To be clear, for a collision to occur, all of the tests have to pass. Additionally, collisions between static shapes are not considered nor are collisions between shapes connected to the same rigid body.
Mysteries of cpSpaceStep() explained.
12 Collision pair functions (TO BE REVISED !)
Collision pair functions allow you to add callbacks for certain collision events. Each cpShape structure has a user definable collision_type field that is used to identify its type. For instance, you could define an enumeration of collision types such as bullets and players, and then register a collision pair function to reduce the players health when a collision is found between the two.
Additionally, the return value of a collision pair function determines whether or not a collision will be processed. If the function returns false, the collision will be ignored. One use for this functionality is to allow a rock object to break a vase object. If the approximated energy of the collision is above a certain level, flag the vase to be removed from the space, apply an impulse to the rock to slow it down, and return false. After the cpSpaceStep returns, remove the vase from the space.
WARNING : It is not safe for collision pair functions to remove or free shapes or bodies from a space. Doing so will likely end in a segfault as an earlier collision may already be referencing the shape or body. You must wait until after the cpSpaceStep function returns.
An array of cpContact structs are passed to collision pair functions. Some user accessible fields include :
p : cpVect. Position of the collision.
n : cpvect. Normal of the collision.
dist : float. Penetration distance of the collision.
| |||||||||||||||||||||||||||||||||||
| space : cpSpace? | |||||||||||||||||||||||||||||||||||
| a : non-negative-integer? | |||||||||||||||||||||||||||||||||||
| b : non-negative-integer? | |||||||||||||||||||||||||||||||||||
| func : cpCollFunc? | |||||||||||||||||||||||||||||||||||
| data : cpDataPointer? |
Register func to be called when a collision is found between a shapes with collision_type fields that match a and b. data is passed to func as a parameter (TO BE REVISED). The ordering of the collision types will match the ordering passed to the callback function.
| (cpSpaceRemoveCollisionPairfunc space a b) → void? |
| space : cpSpace? |
| a : non-negative-integer? |
| b : non-negative-integer? |
Remove the function for the given collision type pair. The order of a and b must match the original order used with cpSpaceAddCollisionPairFunc.
Prototype for a cpCollFunc (TO BE REVISED) :
| (f a b contacts normal-coef) → boolean? |
| a : cpShape |
| b : cpShape |
| contacts : (vectorof cpContact) |
| normal-coef : float? |
13 Point Queries (TO BE REVISED)
Chipmunk spaces currently support one kind of spatial queries : point. Any type can be done efficiently against an entire space, or against individual shapes. All types of queries take a collision group and layer that are used to filter matches out using the same rules used for filtering collisions between shapes. See cpShape for more information.
| ||||||||||||||||||||||||||||||||||||||||||
| space : cpSpace? | ||||||||||||||||||||||||||||||||||||||||||
| point : cpVect? | ||||||||||||||||||||||||||||||||||||||||||
| layers : cpLayers? | ||||||||||||||||||||||||||||||||||||||||||
| group : cpGroup? | ||||||||||||||||||||||||||||||||||||||||||
| func : cpSpacePointQueryFunc? | ||||||||||||||||||||||||||||||||||||||||||
| data : cpDataPointer? |
Query space at point filtering out matches with the given layers and group. func is called for each shape found along with the data argument passed to cpSpacePointQuery. Sensor shapes are included.
| ||||||||||||||||||||||||||||||||||||||||||
| space : cpSpace? | ||||||||||||||||||||||||||||||||||||||||||
| point : cpVect? | ||||||||||||||||||||||||||||||||||||||||||
| layers : cpLayers? | ||||||||||||||||||||||||||||||||||||||||||
| group : cpGroup? | ||||||||||||||||||||||||||||||||||||||||||
| func : cpSpacePointQueryFunc? | ||||||||||||||||||||||||||||||||||||||||||
| data : cpDataPointer? |
Query space at point and return the first shape found matching the given layers and group. Returns NULL if no shape was found. Sensor shapes are ignored.