cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
140 lines (120 loc) • 5 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8" />
<title>cannon.js - shapes 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()
/**
* Showcase all available shapes.
*/
function createTetra() {
const vertices = [
new CANNON.Vec3(0, 0, 0),
new CANNON.Vec3(2, 0, 0),
new CANNON.Vec3(0, 2, 0),
new CANNON.Vec3(0, 0, 2),
]
const offset = -0.35
for (let i = 0; i < vertices.length; i++) {
const v = vertices[i]
v.x += offset
v.y += offset
v.z += offset
}
return new CANNON.ConvexPolyhedron({
vertices,
faces: [
[0, 3, 2], // -x
[0, 1, 3], // -y
[0, 2, 1], // -z
[1, 2, 3], // +xyz
],
})
}
demo.addScene('All shapes', () => {
const world = setupWorld(demo)
const mass = 1
const size = 1
// Sphere shape
const sphereShape = new CANNON.Sphere(size)
const sphereBody = new CANNON.Body({ mass })
sphereBody.addShape(sphereShape)
sphereBody.position.set(-size * 2, size + 1, size * 2)
world.addBody(sphereBody)
demo.addVisual(sphereBody)
// Cylinder shape
const cylinderShape = new CANNON.Cylinder(size, size, size * 2, 10)
const cylinderBody = new CANNON.Body({ mass })
cylinderBody.addShape(cylinderShape)
cylinderBody.position.set(size * 2, size + 1, size * 2)
world.addBody(cylinderBody)
demo.addVisual(cylinderBody)
// Cylinder shape 2
const cylinderShape2 = new CANNON.Cylinder(size, size, size * 2, 10)
const cylinderBody2 = new CANNON.Body({ mass })
cylinderBody2.addShape(cylinderShape2)
cylinderBody2.position.set(size * 2, size * 4 + 1, size * 2)
cylinderBody2.quaternion.setFromEuler(Math.PI / 2, Math.PI / 2, 0)
world.addBody(cylinderBody2)
demo.addVisual(cylinderBody2)
// Box shape
const boxShape = new CANNON.Box(new CANNON.Vec3(size, size, size))
const boxBody = new CANNON.Body({ mass })
boxBody.addShape(boxShape)
boxBody.position.set(size * 2, size + 1, -size * 2)
world.addBody(boxBody)
demo.addVisual(boxBody)
// Particle - not a shape but still here to show how to use it.
const particle = new CANNON.Body({ mass })
particle.addShape(new CANNON.Particle())
particle.position.set(size * 2, size + 1, size * 4)
world.addBody(particle)
demo.addVisual(particle)
// Compound
const compoundBody = new CANNON.Body({ mass })
const shape = new CANNON.Box(new CANNON.Vec3(size * 0.5, size * 0.5, size * 0.5))
compoundBody.addShape(shape, new CANNON.Vec3(0, size, 0))
compoundBody.addShape(shape, new CANNON.Vec3(0, 0, 0))
compoundBody.addShape(shape, new CANNON.Vec3(0, -size, 0))
compoundBody.addShape(shape, new CANNON.Vec3(size, -size, 0))
compoundBody.position.set(size * 4, size + 1, size * 4)
world.addBody(compoundBody)
demo.addVisual(compoundBody)
// ConvexPolyhedron tetra shape
const polyhedronShape = createTetra()
const polyhedronBody = new CANNON.Body({ mass })
polyhedronBody.addShape(polyhedronShape)
polyhedronBody.position.set(-size * 2, size + 1, -size * 2)
world.addBody(polyhedronBody)
demo.addVisual(polyhedronBody)
})
demo.start()
function setupWorld(demo) {
const world = demo.getWorld()
world.gravity.set(0, -30, 0)
// Max solver iterations: Use more for better force propagation, but keep in mind that it's not very computationally cheap!
world.solver.iterations = 17
// Tweak contact properties.
// Contact stiffness - use to make softer/harder contacts
world.defaultContactMaterial.contactEquationStiffness = 1e6
// Stabilization time in number of timesteps
world.defaultContactMaterial.contactEquationRelaxation = 3
// 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>