@bluera/vue-threejs-rapier
Declarative rigid-body physics for vue-threejs, powered by Rapier.
Ported from
@react-three/rapier— the React Three Fiber integration for the Rapier physics engine. The Vue version provides the same component and composable API adapted for Vue's reactivity system.
Availability
@bluera/vue-threejs-rapier is included in the monorepo. Install the core package to use it:
Plugin registration
Register as a fiber plugin to set global defaults:
import { createRapierPlugin } from '@bluera/vue-threejs-rapier'
<Canvas :plugins="[createRapierPlugin({ gravity: [0, -9.81, 0] })]">// Or app-wide
import { registerFiberPlugin } from '@bluera/vue-threejs'
import { rapierFiberPlugin } from '@bluera/vue-threejs-rapier'
registerFiberPlugin(app, rapierFiberPlugin)Usage
Wrap physics objects in a Physics world and add RigidBody components:
<script setup>
import { Canvas } from '@bluera/vue-threejs'
import { Physics, RigidBody, CuboidCollider } from '@bluera/vue-threejs-rapier'
</script>
<template>
<Canvas>
<ambientLight />
<Physics>
<!-- Dynamic falling box -->
<RigidBody>
<mesh>
<boxGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</RigidBody>
<!-- Static ground plane -->
<RigidBody type="fixed">
<CuboidCollider :args="[10, 0.1, 10]" />
<mesh>
<boxGeometry :args="[20, 0.2, 20]" />
<meshStandardMaterial color="green" />
</mesh>
</RigidBody>
</Physics>
</Canvas>
</template>Components
Physics
The physics world container. All rigid bodies and colliders must be descendants of Physics.
| Prop | Type | Default | Description |
|---|---|---|---|
gravity | number[] | [0, -9.81, 0] | World gravity vector |
timestep | number | 1/60 | Fixed timestep |
interpolate | boolean | true | Interpolate between physics steps |
paused | boolean | false | Pause the simulation |
debug | boolean | false | Render debug wireframes |
RigidBody
A physics-enabled rigid body. Children meshes are automatically synced to the body's transform.
| Prop | Type | Default | Description |
|---|---|---|---|
type | string | dynamic | dynamic, fixed, kinematicPosition, kinematicVelocity |
position | number[] | [0,0,0] | Initial position |
rotation | number[] | [0,0,0] | Initial rotation (Euler) |
gravityScale | number | 1 | Per-body gravity multiplier |
restitution | number | 0 | Bounciness (0 = no bounce, 1 = full bounce) |
friction | number | 0.5 | Surface friction |
Debug
Renders wireframe outlines for all colliders in the physics world.
<Physics>
<Debug />
<!-- bodies -->
</Physics>Colliders
Collider components define the physics shape. Place them inside a RigidBody.
| Component | Shape | Args |
|---|---|---|
BallCollider | Sphere | [radius] |
CuboidCollider | Box | [halfX, halfY, halfZ] |
CapsuleCollider | Capsule | [halfHeight, radius] |
CylinderCollider | Cylinder | [halfHeight, radius] |
ConeCollider | Cone | [halfHeight, radius] |
TrimeshCollider | Triangle mesh | [vertices, indices] |
HeightfieldCollider | Heightfield | [rows, cols, heights, scale] |
If no explicit collider is provided, RigidBody auto-generates colliders from child mesh geometries.
<RigidBody>
<BallCollider :args="[0.5]" />
<mesh>
<sphereGeometry :args="[0.5]" />
<meshStandardMaterial />
</mesh>
</RigidBody>Joints
Connect two rigid bodies with a constraint.
| Component | Description |
|---|---|
FixedJoint | Locks bodies together rigidly |
SphericalJoint | Ball-and-socket joint |
RevoluteJoint | Hinge joint (single axis rotation) |
PrismaticJoint | Slider joint (single axis translation) |
RopeJoint | Max-distance constraint |
SpringJoint | Damped spring between bodies |
<RigidBody ref="bodyA">
<!-- ... -->
</RigidBody>
<RigidBody ref="bodyB">
<!-- ... -->
</RigidBody>
<SphericalJoint :body-a="bodyA" :body-b="bodyB" :anchor-a="[0, 1, 0]" :anchor-b="[0, -1, 0]" />Composables
useRapier
Access the Rapier world and API from any descendant of Physics.
import { useRapier } from '@bluera/vue-threejs-rapier'
const { world, rapier } = useRapier()useRigidBody
Access the rigid body API from within a RigidBody.
import { useRigidBody } from '@bluera/vue-threejs-rapier'
const { rigidBody, api } = useRigidBody()
// api.applyImpulse([0, 5, 0])useCollider
Access collider data from within a collider component.
import { useCollider } from '@bluera/vue-threejs-rapier'
const { collider } = useCollider()useBeforePhysicsStep / useAfterPhysicsStep
Run logic before or after each physics step.
import { useBeforePhysicsStep, useAfterPhysicsStep } from '@bluera/vue-threejs-rapier'
useBeforePhysicsStep((world) => {
// apply forces, read positions, etc.
})
useAfterPhysicsStep((world) => {
// read results after simulation
})See also
- Rapier documentation — full physics engine reference
- Original
@react-three/rapier— React integration reference - Plugin system — how fiber plugins work