threlte logo
@threlte/rapier

<AutoColliders>

The <AutoColliders> component generates colliders based on its children. Currently these shapes are available:

  1. cuboid – uses each child mesh bounding box and generates a cuboid collider
  2. ball – uses each child mesh bounding box and generates a ball collider
  3. capsule – uses each child mesh bounding box and generates a capsule collider
  4. trimesh – uses each child mesh geometry and generates a polygonal collider which resembles the geometry
  5. convexHull – uses each child mesh geometry and generates a collider which resembles a convex hull around the geometry

The resulting colliders can be transformed (i.e. positioned, rotated and scaled) as well as given regular collider properties such as mass or centerOfMass.

<script lang="ts">
  import { Pane, Checkbox, Button } from 'svelte-tweakpane-ui'
  import { Canvas } from '@threlte/core'
  import { HTML } from '@threlte/extras'
  import { Debug, World } from '@threlte/rapier'
  import Scene from './Scene.svelte'

  let version = $state(0)
  let debug = $state(true)
</script>

<Pane
  title="Auto Colliders"
  position="fixed"
>
  <Checkbox
    bind:value={debug}
    label="Debug"
  />
  <Button
    title="reset"
    on:click={() => {
      version += 1
    }}
  />
</Pane>

<div>
  <Canvas>
    <World>
      {#if debug}
        <Debug />
      {/if}

      {#key version}
        <Scene />
      {/key}

      {#snippet fallback()}
        <HTML transform>
          <p class="text-xs">
            It seems your browser<br />
            doesn't support WASM.<br />
            I'm sorry.
          </p>
        </HTML>
      {/snippet}
    </World>
  </Canvas>
</div>

<style>
  div {
    height: 100%;
  }
</style>
<script lang="ts">
  import { T } from '@threlte/core'
  import { AutoColliders } from '@threlte/rapier'
</script>

<T.Group position={[0, -0.6, 0]}>
  <AutoColliders shape="cuboid">
    <T.Mesh receiveShadow>
      <T.BoxGeometry args={[10, 1, 10]} />
      <T.MeshStandardMaterial />
    </T.Mesh>
  </AutoColliders>
</T.Group>
<script lang="ts">
  import { T } from '@threlte/core'
  import { OrbitControls, Environment, useGltf } from '@threlte/extras'
  import { AutoColliders, RigidBody } from '@threlte/rapier'
  import { derived } from 'svelte/store'
  import { type MeshStandardMaterial, type Mesh, MathUtils } from 'three'
  import Ground from './Ground.svelte'

  const gltf = useGltf<{
    nodes: {
      'node_damagedHelmet_-6514': Mesh
    }
    materials: {
      Material_MR: MeshStandardMaterial
    }
  }>('/models/helmet/DamagedHelmet.gltf')

  const helmet = derived(gltf, (gltf) => {
    if (!gltf || !gltf.nodes['node_damagedHelmet_-6514']) return
    return gltf.nodes['node_damagedHelmet_-6514']
  })
</script>

<Environment url="/textures/equirectangular/hdr/shanghai_riverside_1k.hdr" />

<T.PerspectiveCamera
  makeDefault
  position.x={12}
  position.y={13}
  fov={40}
>
  <OrbitControls />
</T.PerspectiveCamera>

<T.DirectionalLight
  castShadow
  position={[8, 20, -3]}
/>

{#if $helmet}
  <T.Group
    position={[-2.5, 2, 2.5]}
    rotation={[90 * MathUtils.DEG2RAD, 0, 0]}
  >
    <RigidBody>
      <AutoColliders shape="convexHull">
        <T.Mesh
          castShadow
          geometry={$helmet.geometry}
          material={$helmet.material}
        />
      </AutoColliders>
    </RigidBody>
  </T.Group>

  <T.Group
    position={[2.5, 2, 2.5]}
    rotation={[90 * MathUtils.DEG2RAD, 0, 0]}
  >
    <RigidBody>
      <AutoColliders shape="ball">
        <T.Mesh
          castShadow
          geometry={$helmet.geometry}
          material={$helmet.material}
        />
      </AutoColliders>
    </RigidBody>
  </T.Group>

  <T.Group
    position={[2.5, 2, -2.5]}
    rotation={[90 * MathUtils.DEG2RAD, 0, 0]}
  >
    <RigidBody>
      <AutoColliders shape="cuboid">
        <T.Mesh
          castShadow
          geometry={$helmet.geometry}
          material={$helmet.material}
        />
      </AutoColliders>
    </RigidBody>
  </T.Group>

  <T.Group
    position={[0, 2, 0]}
    rotation={[90 * MathUtils.DEG2RAD, 0, 0]}
  >
    <RigidBody>
      <AutoColliders shape="trimesh">
        <T.Mesh
          castShadow
          geometry={$helmet.geometry}
          material={$helmet.material}
        />
      </AutoColliders>
    </RigidBody>
  </T.Group>

  <T.Group
    position={[-2.5, 2, -2.5]}
    rotation={[90 * MathUtils.DEG2RAD, 0, 0]}
  >
    <RigidBody>
      <AutoColliders shape="capsule">
        <T.Mesh
          castShadow
          geometry={$helmet.geometry}
          material={$helmet.material}
        />
      </AutoColliders>
    </RigidBody>
  </T.Group>
{/if}

<T.GridHelper args={[50]} />

<Ground />

Model: Battle Damaged Sci-fi Helmet by theblueturtle_

Component Signature

If a <AutoColliders> component is not a child of a <RigidBody> component, the transform properties are reactive.

If you don't provide any of the properties density, mass or the full mass properties, Rapier will figure that out for you.

Provide density on its own, mass on its own, or mass together with centerOfMass, principalAngularInertia and angularInertiaLocalFrame.

Props

name
type
required
default

angularInertiaLocalFrame
[number, number, number]
no

centerOfMass
[number, number, number]
no

contactForceEventThreshold
number
no

density
number
no

friction
number
no

frictionCombineRule
CoefficientCombineRule
no

mass
number
no

principalAngularInertia
[number, number, number]
no

restitution
number
no

restitutionCombineRule
CoefficientCombineRule
no

sensor
boolean
no

shape
'cuboid' | 'ball' | 'capsule' | 'trimesh' | 'convexHull'
no
'convexHull'

Events

name
payload

create
ref: Collider[]

collisionenter
{ targetCollider: Collider, targetRigidBody: RigidBody | null, manifold: TempContactManifold, flipped: boolean }

collisionexit
{ targetCollider: Collider, targetRigidBody: RigidBody | null }

sensorenter
{ targetCollider: Collider, targetRigidBody: RigidBody | null }

sensorexit
{ targetCollider: Collider targetRigidBody: RigidBody | null }

contact
{ targetCollider: Collider, targetRigidBody: RigidBody | null, manifold: TempContactManifold, flipped: boolean, maxForceDirection: Vector, maxForceMagnitude: number, totalForce: Vector, totalForceMagnitude: number, }

Bindings

name
type

colliders
Collider[]

Exports

name
type
description

refresh
() => void
Invoke this function to update the colliders shapes and transforms.