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;