Rapier logo

Instance rigid body

Simulate many repeated objects efficiently by creating one Rapier rigid body per instance of a TresInstancedMesh.

InstancedRigidBody is the high-performance alternative to many individual RigidBody components. It wraps a TresInstancedMesh and creates/updates one physics body per instance, so you can simulate hundreds of objects while still sharing geometry and material.

Use it when you need large crowds of similar objects (particles, debris, stacked balls, etc.) with proper collisions and much lower render overhead.

Usage

<script setup lang="ts">
import { TresCanvas } from "@tresjs/core";
import { OrbitControls } from "@tresjs/cientos";
import { Physics, InstancedRigidBody } from "@tresjs/rapier";
import { SphereGeometry, MeshStandardMaterial, DynamicDrawUsage, Matrix4 } from "three";

const instanceRef = shallowRef()
const torusKnots = new SphereGeometry(0.25, 32, 32)
const torusKnotsMaterial = new MeshStandardMaterial()

watch(instanceRef, (mesh) => {
  mesh?.instanceMatrix.setUsage(DynamicDrawUsage)

  if (mesh) {
    for (let i = 0; i < mesh.count; i++) {
      const x = (Math.random() - 0.5) * 5
      const y = ((Math.random()) * 2) + 5
      const z = (Math.random() - 0.5) * 5

      mesh.setMatrixAt(
        i,
        new Matrix4().makeTranslation(x, y, z),
      )
    }
    mesh.instanceMatrix.needsUpdate = true
  }
})
</script>

<template>
  <TresCanvas clear-color="#82DBC5">
    <TresPerspectiveCamera :position="[15, 15, 15]" :look-at="[0, 0, 0]" />
    <OrbitControls />

    <Suspense>
      <Physics :debug="debug">
        <InstancedRigidBody collider="ball" :args="[0.25]" :restitution="0.5">
          <TresInstancedMesh ref="instanceRef" :args="[torusKnots, torusKnotsMaterial, 500]" />
        </InstancedRigidBody>

        <RigidBody type="fixed">
          <TresMesh>
            <TresPlaneGeometry :args="[20, 20, 20]" :rotate-x="-Math.PI / 2" />
            <TresMeshBasicMaterial color="#f4f4f4" />
          </TresMesh>
        </RigidBody>
      </Physics>
    </Suspense>
    <TresDirectionalLight :position="[1, 2, 3]" />
    <TresAmbientLight :intensity="0.5" />
  </TresCanvas>
</template>