cannon
Version:
A lightweight 3D physics engine written in JavaScript.
212 lines (177 loc) • 7.87 kB
HTML
<html>
<head>
<title>cannon.js - RigidVehicle</title>
<meta charset="utf-8">
<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 src="../build/cannon.js"></script>
<script src="../build/cannon.demo.js"></script>
<script src="../libs/dat.gui.js"></script>
<script src="../libs/Three.js"></script>
<script src="../libs/TrackballControls.js"></script>
<script src="../libs/Detector.js"></script>
<script src="../libs/Stats.js"></script>
<script src="../libs/smoothie.js"></script>
<script>
var demo = new CANNON.Demo();
var mass = 1;
var vehicle;
demo.addScene("car",function(){
var world = demo.getWorld();
world.gravity.set(0, 0, -30);
world.broadphase = new CANNON.SAPBroadphase(world);
world.defaultContactMaterial.friction = 0.2;
var groundMaterial = new CANNON.Material("groundMaterial");
var wheelMaterial = new CANNON.Material("wheelMaterial");
var wheelGroundContactMaterial = window.wheelGroundContactMaterial = new CANNON.ContactMaterial(wheelMaterial, groundMaterial, {
friction: 0.3,
restitution: 0,
contactEquationStiffness: 1000
});
// We must add the contact materials to the world
world.addContactMaterial(wheelGroundContactMaterial);
var chassisShape;
var centerOfMassAdjust = new CANNON.Vec3(0, 0, -1);
chassisShape = new CANNON.Box(new CANNON.Vec3(5, 2, 0.5));
var chassisBody = new CANNON.Body({ mass: 1 });
chassisBody.addShape(chassisShape, centerOfMassAdjust);
chassisBody.position.set(0, 0, 0);
// Create the vehicle
vehicle = new CANNON.RigidVehicle({
chassisBody: chassisBody
});
var axisWidth = 7;
var wheelShape = new CANNON.Sphere(1.5);
var down = new CANNON.Vec3(0, 0, -1);
var wheelBody = new CANNON.Body({ mass: mass, material: wheelMaterial });
wheelBody.addShape(wheelShape);
vehicle.addWheel({
body: wheelBody,
position: new CANNON.Vec3(5, axisWidth/2, 0).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 1, 0),
direction: down
});
var wheelBody = new CANNON.Body({ mass: mass, material: wheelMaterial });
wheelBody.addShape(wheelShape);
vehicle.addWheel({
body: wheelBody,
position: new CANNON.Vec3(5, -axisWidth/2, 0).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, -1, 0),
direction: down
});
var wheelBody = new CANNON.Body({ mass: mass, material: wheelMaterial });
wheelBody.addShape(wheelShape);
vehicle.addWheel({
body: wheelBody,
position: new CANNON.Vec3(-5, axisWidth/2, 0).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 1, 0),
direction: down
});
var wheelBody = new CANNON.Body({ mass: mass, material: wheelMaterial });
wheelBody.addShape(wheelShape);
vehicle.addWheel({
body: wheelBody,
position: new CANNON.Vec3(-5, -axisWidth/2, 0).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, -1, 0),
direction: down
});
// Some damping to not spin wheels too fast
for(var i=0; i<vehicle.wheelBodies.length; i++){
vehicle.wheelBodies[i].angularDamping = 0.4;
}
// Constrain wheels
var constraints = [];
// Add visuals
demo.addVisual(vehicle.chassisBody);
for(var i=0; i<vehicle.wheelBodies.length; i++){
demo.addVisual(vehicle.wheelBodies[i]);
}
vehicle.addToWorld(world);
if(false){
// Ground
var groundShape = new CANNON.Plane();
var ground = new CANNON.Body({ mass: 0, material: groundMaterial });
ground.addShape(groundShape);
ground.position.z = -3;
world.add(ground);
demo.addVisual(ground);
} else {
var mock = false;
var matrix = [];
var sizeX = 64,
sizeY = sizeX;
for (var i = 0; i < sizeX; i++) {
matrix.push([]);
for (var j = 0; j < sizeY; j++) {
var height = Math.sin(i / sizeX * Math.PI * 8) * Math.sin(j / sizeY * Math.PI * 8) * 8 + 8;
if(i===0 || i === sizeX-1 || j===0 || j === sizeY-1)
height = 10;
matrix[i].push(height);
}
}
var hfShape = new CANNON.Heightfield(matrix, {
elementSize: 300 / sizeX
});
var hfBody;
var quat = new CANNON.Quaternion();
var pos = new CANNON.Vec3(-sizeX * hfShape.elementSize / 2, -20, -20);
// Use normal
hfBody = new CANNON.Body({ mass: 0, material: groundMaterial });
hfBody.addShape(hfShape, new CANNON.Vec3(0,0,-1), new CANNON.Quaternion());
hfBody.position.copy(pos);
hfBody.quaternion.copy(quat);
if(!mock){
world.add(hfBody);
demo.addVisual(hfBody);
}
if(mock){
for(var i=0; i<sizeX - 1; i++){
for (var j = 0; j < sizeY - 1; j++) {
for (var k = 0; k < 2; k++) {
hfShape.getConvexTrianglePillar(i, j, !!k);
var convexBody = new CANNON.Body({ mass: 0, material: groundMaterial });
convexBody.addShape(hfShape.pillarConvex);
hfBody.pointToWorldFrame(hfShape.pillarOffset, convexBody.position);
world.add(convexBody);
demo.addVisual(convexBody);
}
}
}
}
}
});
demo.start();
document.onkeydown = handler;
document.onkeyup = handler;
var maxSteerVal = Math.PI / 8;
var maxSpeed = 10;
var maxForce = 100;
function handler(event){
var up = (event.type == 'keyup');
if(!up && event.type !== 'keydown')
return;
switch(event.keyCode){
case 38: // forward
vehicle.setWheelForce(up ? 0 : maxForce, 2);
vehicle.setWheelForce(up ? 0 : -maxForce, 3);
break;
case 40: // backward
vehicle.setWheelForce(up ? 0 : -maxForce/2, 2);
vehicle.setWheelForce(up ? 0 : maxForce/2, 3);
break;
case 39: // right
vehicle.setSteeringValue(up ? 0 : -maxSteerVal, 0);
vehicle.setSteeringValue(up ? 0 : -maxSteerVal, 1);
break;
case 37: // left
vehicle.setSteeringValue(up ? 0 : maxSteerVal, 0);
vehicle.setSteeringValue(up ? 0 : maxSteerVal, 1);
break;
}
}
</script>
</body>
</html>