JSFiddle - React, Tailwind, and code Playground
HTML
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.177.0/build/three.webgpu.js",
"orbitControls": "https://unpkg.com/three@0.177.0/examples/jsm/controls/OrbitControls.js",
"rapier": "https://poseidonenergy.github.io/RapierJsPublishRepo/no-object-creation/rapier.mjs"
}
}
</script>
<div id="overlayContainer">
<button id="testButton">Run Benchmark</button>
<div id="infoDiv1"></div>
<div id="infoDiv2" style="display:none;"></div>
</div>
CSS
* {
margin: 0;
border: 0;
padding: 0;
line-height: 1;
}
html {
height: 100%;
overflow: hidden;
}
body {
height: 100%;
overflow: hidden;
font-family: sans-serif;
background-color: #808080;
user-drag: none;
-webkit-user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
#overlayContainer {
font-family:
"Segoe UI",
"Lucida Grande",
-apple-system,
BlinkMacSystemFont,
"Liberation Sans",
sans-serif;
font-size: 14px;
position: absolute;
z-index: 3;
padding: 10px;
box-sizing: content-box;
background-color: rgba(0, 0, 0, 0.5);
color: #ffffff;
}
#infoDiv1 {
margin-top: 10px;
min-width: 40ch;
min-height: 1lh;
}
#infoDiv2 {
margin-top: 10px;
min-width: 40ch;
min-height: 1lh;
}
#testButton {
display: block;
background-clip: padding-box;
border-width: 2px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.5);
padding: 5px;
cursor: pointer;
}
.click-through {
&,
& * {
pointer-events: none;
}
}
table {
display: table;
width: 100%;
table-layout: auto;
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
}
tr.top-border {
border-top-width: 2px;
border-style: solid;
}
tr,
td,
th {
vertical-align: middle;
}
JavaScript
import * as THREE from "three";
import * as RAPIER from "rapier";
import { OrbitControls } from "orbitControls";
const infoDiv1 = document.getElementById("infoDiv1");
const infoDiv2 = document.getElementById("infoDiv2");
const testButton = document.getElementById("testButton");
const physicsTickDelayMs = 16;
const groundDimensions = [10, 1, 10];
const groundPosition = [0, -1, 0];
const groundRestitution = 0.3;
const ceilingHeight = 10;
const ballRadius = 0.5;
const ballRestitution = 0.3;
const ballStartPos = { x: 0, y: 5, z: 0 };
async function onButtonClick(world, rigidBody) {
const rigidBodies = 1000;
const fps = 60;
const originalBenchmark = await new Promise((resolve) => {
let c = 0;
let seconds = 0;
doThing();
function doThing() {
if (++c < fps) {
const t0 = performance.now();
for (let i = 0; i < rigidBodies; i++) {
let pos = rigidBody.translationOriginal();
let rot = rigidBody.rotationOriginal();
}
seconds += (performance.now() - t0) / 1000;
setTimeout(doThing, 0);
} else {
resolve(seconds);
}
}
});
const newBenchmark = await new Promise((resolve) => {
let c = 0;
let seconds = 0;
const positionBuffer = {x:0,y:0,z:0};
const rotationBuffer = {x:0,y:0,z:0,w:0};
doThing();
function doThing() {
if (++c < fps) {
const t0 = performance.now();
for (let i = 0; i < rigidBodies; i++) {
rigidBody.translation(positionBuffer);
rigidBody.rotation(rotationBuffer);
}
seconds += (performance.now() - t0) / 1000;
setTimeout(doThing, 0);
} else {
resolve(seconds);
}
}
});
infoDiv1.innerHTML = `
Results after calling translation()<br/>
and rotation() on each rigid body<br/>
at ${fps} FPS, with ${rigidBodies} rigid bodies:<br/><br/>
<table style="width:0.01%;">
<tr>
<td...