Three.js and Rapier

Learn how to set up a Three.js scene with Rapier to add physics.

Creating a basic Three.js scene with Rapier

To get started, we created a very basic scene in which a cube drops down and hits a plane. The following screenshot shows the output of the example physics-setup.js (given in the playground below):

Press + to interact
Simple Rapier physics
Simple Rapier physics

Example: Physics setup

Click the “Run” button to execute the above example. Once the application is running, please click the provided link to view the output in a new window.

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// const CopyWebpackPlugin = require('copy-webpack-plugin')
const fs = require('fs').promises

// we should search through the directories in examples, and use
// the name from the files to generate the HtmlWebpackPlugin settings.
module.exports = async () => {

  return {
    module: {
      rules: [
        {
          test: /\.glsl$/i,
          use: 'raw-loader'
        }
      ]
    },
    mode: 'development',
    entry: {
      'chapter-12': './samples/chapters/chapter-12/physics-setup.js',
    },
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js',
      publicPath: '/',
    },
    plugins: [
      new HtmlWebpackPlugin(),
    ],
    experiments: {
      asyncWebAssembly: true
    },
    devServer: {
       allowedHosts: 'all',
       host: '0.0.0.0',
       port: '3000',
       static: [
        {
          directory: path.join(__dirname, 'assets'),
          publicPath: '/assets'
        },
        {
          directory: path.join(__dirname, 'dist')
        }
      ] 
    },
  mode: 'development',
  }
}
Create physics simulation with Rapier

When we open this example, we’ll see the cube slowly drops down, hits the corner of the gray horizontal plane, and bounces off it. We could have accomplished this without using a physics engine by updating the position and rotation of the cube and programming how it should react. This is, however, rather difficult to do because we need to know exactly when it hits, where it hits, and how the cube should spin away after the hit. With Rapier, we just have to configure the physical world, and Rapier will calculate exactly what happens to the objects in the scene.

Before we can configure our models to use the Rapier engine, we need to install Rapier in our project:

Press + to interact
yarn add @dimforge/rapier3d

Note: We’ve already done this, so you don’t have to install this for the examples in this course.

Creating Rapier world

Once added, we need to import Rapier into our project. This is done slightly differently than the normal imports we’ve seen because Rapier needs to load additional WebAssembly resources. This is needed because the Rapier library is developed in the Rust language and compiled into WebAssembly so it can also be used on the web. To use Rapier, we need to wrap our script like this:

Press + to interact
import * as THREE from 'three'
import { RigidBodyType } from '@dimforge/rapier3d'
// maybe other imports
import('@dimforge/rapier3d').then((RAPIER) => {
// the code
});

This last import statement will load the Rapier library asynchronously and calls the callback when all the data has been loaded and parsed (line 2). ...