Use 3D physics to make objects fall, roll, and collide in a 3D world. Codea uses the Bullet physics engine to simulate their motion.
Add physics bodies to a scene for automatic simulation, or create a physics3d.world and advance it yourself.
Create a world, add bodies, and advance it with world:step():
function setup()
world = physics3d.world()
world.gravity = vec3(0, -9.8, 0)
-- Create a ground plane
ground = world:body(physics3d.STATIC)
ground:add(physics3d.plane(vec3(0, 1, 0), 0))
-- Create a dynamic sphere
ball = world:body(physics3d.DYNAMIC)
ball:add(physics3d.sphere(0.5))
ball.position = vec3(0, 5, 0)
end
function update(dt)
world:update(dt)
end
function draw()
-- Draw the ball position
pushMatrix()
translate(ball.position.x, ball.position.y, ball.position.z)
sphere(0.5)
popMatrix()
endBody types:
physics3d.STATIC — does not move, acts as immovable sceneryphysics3d.DYNAMIC — moved by forces and collisionsphysics3d.KINEMATIC — moved manually via code, pushes dynamic bodies without being affected by gravityWhen working with a scene, attach physics components directly to entities:
function setup()
scn = scene()
local cam = scn:entity("camera")
cam:add(camera.perspective(60))
cam:add(camera.rigs.orbit)
cam.z = -10
-- Static ground
local ground = scn:entity("ground")
ground:add(mesh.plane())
ground:add(physics3d.body(physics3d.STATIC))
ground:add(physics3d.box(vec3(10, 0.1, 10)))
ground.material = material.lit()
-- Dynamic box
local box = scn:entity("box")
box:add(mesh.box())
box:add(physics3d.body(physics3d.DYNAMIC))
box:add(physics3d.box(vec3(1, 1, 1)))
box.y = 5
box.material = material.lit()
scene.main = scn
endThe scene automatically steps the physics simulation each frame.
Choose the collision shape that best matches your object’s visual appearance. Simpler shapes perform better:
physics3d.sphere(radius) — spherephysics3d.box(halfExtents) — axis-aligned box, parameter is half-widths as a vec3physics3d.capsule(radius, height) — capsule (good for characters)physics3d.cylinder(radius, height) — cylinderphysics3d.cone(radius, height) — conephysics3d.plane(normal, constant) — infinite plane, STATIC onlyphysics3d.hull(points) — convex hull around a set of pointsbody:add(physics3d.sphere(1))
body:add(physics3d.box(vec3(0.5, 1, 0.5)))
body:add(physics3d.capsule(0.4, 1.8))React to collisions through entity callbacks or body callbacks:
local box = scn:entity()
box:add(physics3d.body(physics3d.DYNAMIC))
box:add(physics3d.box(vec3(1,1,1)))
box.collisionBegan3d = function(contact)
print("Hit something!", contact.impulse)
endThe contact object contains impulse (force magnitude) and normal (collision normal vector).
Apply forces and impulses to dynamic bodies to set them in motion:
local body = ent:get(physics3d.body)
-- Continuous force (applied each frame, use in update)
body:applyForce(vec3(0, 100, 0))
-- Instant impulse (applied once)
body:applyImpulse(vec3(0, 10, 0))
-- Torque (rotational force)
body:applyTorque(vec3(0, 5, 0))
-- Set velocity directly
body.linearVelocity = vec3(1, 0, 0)
body.angularVelocity = vec3(0, 1, 0)
physics3d.world
physics3d.world()
Create a new physics world
physics3d.world |
physics3d.world:body(type, x, y, z)
Create a new rigidbody in this world
| type | enum. The type of body, STATIC, DYNAMIC or KINEMATIC |
| x | number. The initial x position of the new body |
| y | number. The initial y position of the new body |
| z | number. The initial z position of the new body |
physics3d.body |
The newly created body |
physics3d.world:step(deltaTime)
Steps the simulation by deltaTime
| deltaTime | number, optional. Simulation timestep, in seconds. |
physics3d.world:draw()
Draws a debug representation of the physics world using primitive shapes
physics3d.world:raycast(origin, direction, distance, mask)
Performs a raycast on the physics world from origin in the direction of direction for the distance of distance
The raycast itself is filtered by the optional mask parameter, a bitfield which is compared to collider categories
| origin | vec3. The origin of the ray |
| direction | vec3. The direction of the ray |
| distance | number. The maximum distance for the ray to travel |
| mask | integer, optional. Collision category bit mask restricting which bodies can be hit. |
physics3d.rayHit |
The raycast hit info or nil is no collider was hit |
physics3d.world:sphereCast(origin, direction, distance, radius, mask)
Performs a sphere cast on the physics world from origin in the direction of direction for the distance of distance
The sphere cast itself is filtered by the optional mask parameter, a bitfield which is compared to collider categories
| origin | vec3. The origin of the ray |
| direction | vec3. The direction of the ray |
| distance | number. The maximum distance for the ray to travel |
| radius | number. The radius of the sphere used to perform the cast |
| mask | integer, optional. Collision category bit mask restricting which bodies can be hit. |
physics3d.rayHit |
The raycast hit info or nil is no collider was hit |
physics3d.world.gravity
The current gravity vector for this world
physics3d.body
A three dimensional rigidbody that simulated within a physics3d.world. Used to simulate both dynamic and static objects, responding to physical forces, collisions and physics queries (i.e. raycast, queryBox, etc…)
physics3d.body:destroy()
Destroys this body, removing it from the world in the next simluation step
physics3d.body:sphere(radius, offsetX, offsetY, offsetZ)
Creates and attaches a sphere collider to this body
| radius | number. The radius of the circle |
| offsetX | number, optional. The local x offset of the circle |
| offsetY | number, optional. The local y offset of the circle |
| offsetZ | number, optional. The local y offset of the circle |
physics3d.sphere |
The new circle collider |
physics3d.body:box(halfWidth, halfHeight, halfDepth, offsetX, offsetY, offsetZ)
Creates and attaches a box collider to this body
| halfWidth | number. half width of the box |
| halfHeight | number. half height of the box |
| halfDepth | number. half depth of the box |
| offsetX | number, optional. The local x offset of the circle |
| offsetY | number, optional. The local y offset of the circle |
| offsetZ | number, optional. The local y offset of the circle |
physics3d.box |
The new box collider |
physics3d.body:capsule(radius, height, offsetX, offsetY, offsetZ)
Creates and attaches a capsule collider to this body
| radius | number. The radius of the capsule |
| height | number. The height of the capsule |
| offsetX | number, optional. The local x offset of the circle |
| offsetY | number, optional. The local y offset of the circle |
| offsetZ | number, optional. The local y offset of the circle |
physics3d.polygon |
The new capsule collider |
physics3d.body:mesh(mesh, convex)
Creates and attaches a mesh collider to this body
| mesh | mesh. Mesh defining the collision geometry. |
| convex | boolean, optional. Whether to use a convex hull instead of the triangle mesh. |
physics3d.mesh |
The new capsule collider |
physics3d.body:hinge(anchor, axis)
Creates and attaches a hinge joint to this body. When no other body is provided the hinge joint attaches to the world itself
For two-body joints when one anchor and axis is provided, it will be interpreted as a world space location, which will attach to the relative locations of both bodies
When two anchors and axes are provided (anchorA / axisA and anchorB / axisB) are provided, they will be interpreted in local space and attach to those locations directly
| anchor | vec3. The world-space anchor for one or two-body hinges |
| axis | vec3. The world-space axis for one or two-body hinges |
physics3d.hinge |
The new hinge joint |
physics3d.body:applyForce(force, worldPoint)
Applies a force to this body over time (non-instantanious). Ideal for physical effects such as wind, bouyancy and springs
The optional parameter worldPoint can be used to apply forces to a specific location in world-space
| force | vec3. The force to apply |
| worldPoint | vec3, optional. The world-space location to apply the force at |
physics3d.body:applyTorque(torque)
| torque | vec3. The torque vector to apply |
physics3d.body:applyLinearImpulse(impulse)
| impulse | vec3. The linear impulse to apply |
physics3d.body:applyAngularImpulse(impulse)
| impulse | vec3. The angular impulse to apply |
physics3d.body:worldPoint(localPoint)
Transforms localPoint from local space to world space in respect to this body
| localPoint | vec3. The local space point to transform |
vec3 |
physics3d.body:worldVector(localVector)
Transforms localVector from world space to local space in respect to this body
| localVector | vec3. The world space vector to transform |
vec3 |
physics3d.body:localPoint(worldPoint)
Transforms worldPoint from world space to local space in respect to this body
| worldPoint | vec3. The world space point to transform |
vec3 |
physics3d.body:localVector(worldVector)
Transforms worldVector from world space to local space in respect to this body
| worldVector | vec3. The world space vector to transform |
vec3 |
physics3d.body:velocityAtLocalPoint(localPoint)
Samples the velocity of the body at localPoint in local space
Useful for determining velocity on a body at a specific location for calculating effects, sounds and damage during collisions
| localPoint | vec3. The local point to sample velocity from |
vec3 |
physics3d.body:velocityAtWorldPoint(worldPoint)
Samples the velocity of the body at worldPoint in world space
Useful for determining velocity on a body at a specific location for calculating effects, sounds and damage during collisions
| worldPoint | vec3. The world point to sample velocity from |
vec3 |
physics3d.body.destroyed
Flag indicating that this body has already been destroyed
physics3d.body.position
The position of this body in the simulated world
physics3d.body.mass
The mass of this body in kilograms
physics3d.body.inertia
The interial tensor in kg m^2
physics3d.body.linearDamping
The amount of linear damping to apply, slowing velocity proportionally over time
physics3d.body.angularDamping
The amount of linear damping to apply, slowing rotation propotionally over time
physics3d.body.sleepingAllowed
Flag for allowing sleeping for this body
physics3d.body.awake
Flag for the current awake state of this body, set to true to wake immediately
physics3d.body.enabled
Flag for whether simulation is enabled
physics3d.body.constraints
Flags to lock movement and rotation along each axis, using the following flags:
physics3d.freezePositionXphysics3d.freezePositionYphysics3d.freezePositionZphysics3d.freezeRotationXphysics3d.freezeRotationYphysics3d.freezeRotationZphysics3d.freezeRotationphysics3d.freezePositionphysics3d.freezeAllThese flags can also be combined, i.e. myBody.constraints = physics3d.freezePositionX | physics3d.freezeRotation
physics3d.body.bullet
Continuous physics switch for this body, used to prevent tunneling for fast moving objects
physics3d.collider
TODO
physics3d.sphere
TODO
physics3d.box
TODO
physics3d.capsule
TODO
physics3d.mesh
TODO
physics3d.cylinder
TODO
physics3d.cone
TODO
physics3d.joint
TODO
physics3d.hinge
TODO
physics3d.slider
TODO
physics3d.ballSocket
TODO
physics3d.coneTwist
TODO
physics3d.generic
TODO
physics3d.weld
TODO
physics3d.rayHit
physics3d.rayHit.point
The world position of the raycast hit location
physics3d.rayHit.normal
The world normal of the raycast hit location
physics3d.rayHit.fraction
The fraction of the total ray distance travelled before a hit was detected
physics3d.rayHit.triangleIndex
The index of the triangle hit (if we hit a mesh collider)
physics3d.rayHit.uv
The uv coorindate of the triangle hit (if we hit a mesh collider)
physics3d.rayHit.barycentric
The barycentric coorindate of the triangle hit (if we hit a mesh collider)
physics3d.rayHit.collider
The collider that was hit by the ray
physics3d.rayHit.body
The body of the collider that was hit by the ray