Physics API
The API for physics is still work in progress and might change in the future.
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])