cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
120 lines (103 loc) • 4.04 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8" />
<title>cannon.js - trimesh demo</title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
</head>
<body>
<script type="module">
import * as CANNON from '../dist/cannon-es-control.js'
import { Demo } from './js/Demo.js'
const demo = new Demo()
demo.addScene('Raycasting', () => {
const world = demo.getWorld()
world.gravity.set(0, 0, 0)
// Particle as marker for the raycast hit
const N = 10
const particleShape = new CANNON.Particle()
const particleBodies = []
for (let i = 0; i < N * N; i++) {
const particleBody = new CANNON.Body({
mass: 1,
shape: particleShape,
collisionResponse: false,
})
world.addBody(particleBody)
demo.addVisual(particleBody)
particleBodies.push(particleBody)
}
// Torus
const torusShape = CANNON.Trimesh.createTorus(4, 3.5, 16, 16)
const torusBody = new CANNON.Body({ mass: 1 })
torusBody.addShape(torusShape)
torusBody.position.set(0.01, 0.01, 0.01)
torusBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
torusBody.angularVelocity.set(0, 0, 1)
world.addBody(torusBody)
demo.addVisual(torusBody)
// Do the raycasting
const from = new CANNON.Vec3(-10, 0, 1)
const to = new CANNON.Vec3(10, 0, 1)
const result = new CANNON.RaycastResult()
const raycastOptions = {}
function postStepListener(event) {
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
from.set(-10, i * 0.1, j * 0.1)
to.set(10, i * 0.1, j * 0.1)
result.reset()
world.raycastClosest(from, to, raycastOptions, result)
particleBodies[i * N + j].position.copy(result.hitPointWorld)
}
}
}
world.addEventListener('postStep', postStepListener)
// Remove listener when we change demo
demo.addEventListener('destroy', () => {
world.removeEventListener('postStep', postStepListener)
})
})
demo.addScene('Trimesh', () => {
const world = setupWorld(demo)
// Sphere
const sphereShape = new CANNON.Sphere(1)
const sphereBody = new CANNON.Body({
mass: 1,
shape: sphereShape,
position: new CANNON.Vec3(-3, 11, 3),
})
world.addBody(sphereBody)
demo.addVisual(sphereBody)
// Torus
const torusShape = CANNON.Trimesh.createTorus(4, 3.5, 16, 16)
const torusBody = new CANNON.Body({ mass: 1 })
torusBody.addShape(torusShape)
torusBody.position.set(0, 4, 0)
torusBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
torusBody.velocity.set(0, 1, 1)
world.addBody(torusBody)
demo.addVisual(torusBody)
})
demo.start()
function setupWorld(demo) {
const world = demo.getWorld()
world.gravity.set(0, -10, 0)
// Tweak contact properties.
// Contact stiffness - use to make softer/harder contacts
world.defaultContactMaterial.contactEquationStiffness = 1e7
// Stabilization time in number of timesteps
world.defaultContactMaterial.contactEquationRelaxation = 4
// Static ground plane
const groundShape = new CANNON.Plane()
const groundBody = new CANNON.Body({ mass: 0 })
groundBody.addShape(groundShape)
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
world.addBody(groundBody)
demo.addVisual(groundBody)
return world
}
</script>
</body>
</html>