Skip to main content

Physics API

warning

The API for physics is still work in progress and might change in the future.

tip

As physics engine bullet3 is used. We simply provide a JS/JSI wrapper around it. So it can help to familiarize with their documentation first:

Hooks:

The hooks should be used whenever possible.

Example:

First we need to create a physics world:

import { useWorld } from 'react-native-filament';

function App() {
const world = useWorld([0, -9.8, 0]);
}

Often times you want to create a physical body for an entity (asset) in the scene. Here are a few helpers you likely will need to accomplish this:

Get the bounding box of an entity:

const boundingBox = asset.boundingBox // returns an aabb bounding box
const halfExtents = boundingBox.halfExtents
const center = boundingBox.center

Get the transform an entity:

const {transformManager} = useFilamentContext()
const transform = transformManager.getTransform(entity)

// Get the calculated world scale:
const [scaleX, scaleY, scaleZ] = transform.scale

Create a physical shape (resembling the asset)

// useBoxShape expects a vector of halfExtents, so we can just pass the once from our asset
const boxShape = useBoxShape(halfExtents)

// Eventually we need to adjust the local scaling of the shape:
boxShape.localScaling = transform.scale

Create a rigid body

const rigidBody = useRigidBody({
id: "box",
mass: 1,
shape: boxShape,
transform: transform,
// Pass the world for the body to be automatically added to the world:
world: world
})

Update the physical world

We need to simulate physics every frame:

const renderCallback = useCallback(({ timeSinceLastFrame }) => {
"worklet"

// This updates the world at 60Hz/60 FPS. If our actual frame rate
// is different stepSimulation will interpolate the physics.
world.stepSimulation(timeSinceLastFrame, 1, 1 / 60)
}, [world])

Update the transform of our physic entities

Now that the physical world has been updated we need to update the transform of our entities. The transformManager has a convenience method for that:

const renderCallback = useCallback(({ timeSinceLastFrame }) => {
"worklet"

world.stepSimulation(timeSinceLastFrame, 1, 1 / 60)

// Update our entity:
transformManager.updateTransformByRigidBody(entity, rigidBody)
}, [world])