diff --git a/examples-testing/changes.patch b/examples-testing/changes.patch
index ca62c4b54..50d8cc4e5 100644
--- a/examples-testing/changes.patch
+++ b/examples-testing/changes.patch
@@ -1527,6 +1527,27 @@ index 4f782d45..0759cfca 100644
const d = document.createElement('div');
d.innerHTML = '
' + name + '
';
+diff --git a/examples-testing/examples/physics_rapier_instancing.ts b/examples-testing/examples/physics_rapier_instancing.ts
+index 8f1bdda2..67d3517f 100644
+--- a/examples-testing/examples/physics_rapier_instancing.ts
++++ b/examples-testing/examples/physics_rapier_instancing.ts
+@@ -1,12 +1,12 @@
+ import * as THREE from 'three';
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+-import { RapierPhysics } from 'three/addons/physics/RapierPhysics.js';
++import { RapierPhysics, RapierPhysicsObject } from 'three/addons/physics/RapierPhysics.js';
+ import Stats from 'three/addons/libs/stats.module.js';
+
+-let camera, scene, renderer, stats;
+-let physics, position;
++let camera: THREE.PerspectiveCamera, scene: THREE.Scene, renderer: THREE.WebGLRenderer, stats: Stats;
++let physics: RapierPhysicsObject, position: THREE.Vector3;
+
+-let boxes, spheres;
++let boxes: THREE.InstancedMesh, spheres: THREE.InstancedMesh;
+
+ init();
+
diff --git a/examples-testing/examples/svg_lines.ts b/examples-testing/examples/svg_lines.ts
index 99b74c40..65aaf28d 100644
--- a/examples-testing/examples/svg_lines.ts
diff --git a/examples-testing/examples/physics_rapier_instancing.ts b/examples-testing/examples/physics_rapier_instancing.ts
new file mode 100644
index 000000000..8f1bdda24
--- /dev/null
+++ b/examples-testing/examples/physics_rapier_instancing.ts
@@ -0,0 +1,123 @@
+import * as THREE from 'three';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { RapierPhysics } from 'three/addons/physics/RapierPhysics.js';
+import Stats from 'three/addons/libs/stats.module.js';
+
+let camera, scene, renderer, stats;
+let physics, position;
+
+let boxes, spheres;
+
+init();
+
+async function init() {
+ physics = await RapierPhysics();
+ position = new THREE.Vector3();
+
+ //
+
+ camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 100);
+ camera.position.set(-1, 1.5, 2);
+ camera.lookAt(0, 0.5, 0);
+
+ scene = new THREE.Scene();
+ scene.background = new THREE.Color(0x666666);
+
+ const hemiLight = new THREE.HemisphereLight();
+ hemiLight.intensity = 0.3;
+ scene.add(hemiLight);
+
+ const dirLight = new THREE.DirectionalLight();
+ dirLight.position.set(5, 5, 5);
+ dirLight.castShadow = true;
+ dirLight.shadow.camera.zoom = 2;
+ scene.add(dirLight);
+
+ const floor = new THREE.Mesh(new THREE.BoxGeometry(10, 5, 10), new THREE.ShadowMaterial({ color: 0x444444 }));
+ floor.position.y = -2.5;
+ floor.receiveShadow = true;
+ scene.add(floor);
+ physics.addMesh(floor);
+
+ //
+
+ const material = new THREE.MeshLambertMaterial();
+
+ const matrix = new THREE.Matrix4();
+ const color = new THREE.Color();
+
+ // Boxes
+
+ const geometryBox = new THREE.BoxGeometry(0.075, 0.075, 0.075);
+ boxes = new THREE.InstancedMesh(geometryBox, material, 400);
+ boxes.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // will be updated every frame
+ boxes.castShadow = true;
+ boxes.receiveShadow = true;
+ scene.add(boxes);
+
+ for (let i = 0; i < boxes.count; i++) {
+ matrix.setPosition(Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5);
+ boxes.setMatrixAt(i, matrix);
+ boxes.setColorAt(i, color.setHex(0xffffff * Math.random()));
+ }
+
+ physics.addMesh(boxes, 1);
+
+ // Spheres
+
+ const geometrySphere = new THREE.IcosahedronGeometry(0.05, 4);
+ spheres = new THREE.InstancedMesh(geometrySphere, material, 400);
+ spheres.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // will be updated every frame
+ spheres.castShadow = true;
+ spheres.receiveShadow = true;
+ scene.add(spheres);
+
+ for (let i = 0; i < spheres.count; i++) {
+ matrix.setPosition(Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5);
+ spheres.setMatrixAt(i, matrix);
+ spheres.setColorAt(i, color.setHex(0xffffff * Math.random()));
+ }
+
+ physics.addMesh(spheres, 1);
+
+ //
+
+ renderer = new THREE.WebGLRenderer({ antialias: true });
+ renderer.setPixelRatio(window.devicePixelRatio);
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ renderer.shadowMap.enabled = true;
+ document.body.appendChild(renderer.domElement);
+
+ stats = new Stats();
+ document.body.appendChild(stats.dom);
+
+ //
+
+ const controls = new OrbitControls(camera, renderer.domElement);
+ controls.target.y = 0.5;
+ controls.update();
+
+ animate();
+
+ setInterval(() => {
+ let index = Math.floor(Math.random() * boxes.count);
+
+ position.set(0, Math.random() + 1, 0);
+ physics.setMeshPosition(boxes, position, index);
+
+ //
+
+ index = Math.floor(Math.random() * spheres.count);
+
+ position.set(0, Math.random() + 1, 0);
+ physics.setMeshPosition(spheres, position, index);
+ }, 1000 / 60);
+}
+
+function animate() {
+ requestAnimationFrame(animate);
+
+ renderer.render(scene, camera);
+
+ stats.update();
+}
diff --git a/examples-testing/index.js b/examples-testing/index.js
index 2eb5758dc..0a69834ce 100644
--- a/examples-testing/index.js
+++ b/examples-testing/index.js
@@ -376,7 +376,7 @@ const files = {
// 'physics_ammo_rope',
// 'physics_ammo_terrain',
// 'physics_ammo_volume',
- // 'physics_rapier_instancing',
+ 'physics_rapier_instancing',
],
misc: [
'misc_animation_groups',
diff --git a/types/three/OTHER_FILES.txt b/types/three/OTHER_FILES.txt
index ff6f0f924..fd4d35bdf 100644
--- a/types/three/OTHER_FILES.txt
+++ b/types/three/OTHER_FILES.txt
@@ -92,6 +92,7 @@ examples/jsm/objects/Sky.d.ts
examples/jsm/objects/Water.d.ts
examples/jsm/objects/Water2.d.ts
examples/jsm/physics/AmmoPhysics.d.ts
+examples/jsm/physics/RapierPhysics.d.ts
examples/jsm/postprocessing/AfterimagePass.d.ts
examples/jsm/postprocessing/BloomPass.d.ts
examples/jsm/postprocessing/BokehPass.d.ts
diff --git a/types/three/examples/jsm/physics/RapierPhysics.d.ts b/types/three/examples/jsm/physics/RapierPhysics.d.ts
new file mode 100644
index 000000000..f5197aad0
--- /dev/null
+++ b/types/three/examples/jsm/physics/RapierPhysics.d.ts
@@ -0,0 +1,11 @@
+import { Mesh } from '../../../src/Three';
+
+type Vector = { x: number; y: number; z: number };
+
+export interface RapierPhysicsObject {
+ addMesh: (mesh: Mesh, mass?: number, restitution?: number) => void;
+ setMeshPosition: (mesh: Mesh, position: Vector, index?: number) => void;
+ setMeshVelocity: (mesh: Mesh, velocity: Vector, index?: number) => void;
+}
+
+export function RapierPhysics(): Promise;