cannon
Version:
A lightweight 3D physics engine written in JavaScript.
308 lines (275 loc) • 12.8 kB
HTML
<!DOCTYPE html>
<html>
<head>
<title>cannon.js - ragdoll demo</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();
demo.addScene("NoCone",function(){
var world = demo.getWorld();
world.gravity.set(0,0,-5);
var scale = 3;
var position = new CANNON.Vec3(0,0,10);
createRagdoll(scale, position, world, Math.PI, Math.PI, Math.PI);
createGround(world);
createStaticSphere(world);
});
demo.addScene("NormalCone",function(){
var world = demo.getWorld();
world.gravity.set(0,0,-5);
var scale = 3;
var position = new CANNON.Vec3(0,0,10);
createRagdoll(scale, position, world, Math.PI / 4, Math.PI / 3, Math.PI / 8);
createGround(world);
createStaticSphere(world);
});
demo.addScene("ThinCone",function(){
var world = demo.getWorld();
world.gravity.set(0,0,-5);
var scale = 3;
var position = new CANNON.Vec3(0,0,10);
createRagdoll(scale, position, world, 0, 0, 0);
createGround(world);
createStaticSphere(world);
});
demo.start();
function createRagdoll(scale, position, world, angleA, angleB, twistAngle){
var numBodiesAtStart = world.bodies.length;
var shouldersDistance = 0.5 * scale,
upperArmLength = 0.4 * scale,
lowerArmLength = 0.4 * scale,
upperArmSize = 0.2 * scale,
lowerArmSize = 0.2 * scale,
neckLength = 0.1 * scale,
headRadius = 0.25 * scale,
upperBodyLength = 0.6 * scale,
pelvisLength = 0.4 * scale,
upperLegLength = 0.5 * scale,
upperLegSize = 0.2 * scale,
lowerLegSize = 0.2 * scale,
lowerLegLength = 0.5 * scale;
var headShape = new CANNON.Sphere(headRadius),
upperArmShape = new CANNON.Box(new CANNON.Vec3(upperArmLength * 0.5, upperArmSize * 0.5, upperArmSize * 0.5)),
lowerArmShape = new CANNON.Box(new CANNON.Vec3(lowerArmLength * 0.5, lowerArmSize * 0.5, lowerArmSize * 0.5)),
upperBodyShape = new CANNON.Box(new CANNON.Vec3(shouldersDistance * 0.5, upperBodyLength * 0.5, lowerArmSize * 0.5)),
pelvisShape = new CANNON.Box(new CANNON.Vec3(shouldersDistance * 0.5, pelvisLength * 0.5, lowerArmSize * 0.5)),
upperLegShape = new CANNON.Box(new CANNON.Vec3(upperLegSize * 0.5, upperLegLength * 0.5, lowerArmSize * 0.5)),
lowerLegShape = new CANNON.Box(new CANNON.Vec3(lowerLegSize * 0.5, lowerLegLength * 0.5, lowerArmSize * 0.5));
// Lower legs
var lowerLeftLeg = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(-shouldersDistance/2,lowerLegLength / 2, 0)
});
var lowerRightLeg = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(shouldersDistance/2,lowerLegLength / 2, 0)
});
lowerLeftLeg.addShape(lowerLegShape);
lowerRightLeg.addShape(lowerLegShape);
world.addBody(lowerLeftLeg);
world.addBody(lowerRightLeg);
demo.addVisual(lowerRightLeg);
demo.addVisual(lowerLeftLeg);
// Upper legs
var upperLeftLeg = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(-shouldersDistance/2,lowerLeftLeg.position.y+lowerLegLength/2+upperLegLength / 2, 0),
});
var upperRightLeg = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(shouldersDistance/2,lowerRightLeg.position.y+lowerLegLength/2+upperLegLength / 2, 0),
});
upperLeftLeg.addShape(upperLegShape);
upperRightLeg.addShape(upperLegShape);
world.addBody(upperLeftLeg);
world.addBody(upperRightLeg);
demo.addVisual(upperLeftLeg);
demo.addVisual(upperRightLeg);
// Pelvis
var pelvis = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(0, upperLeftLeg.position.y+upperLegLength/2+pelvisLength/2, 0),
});
pelvis.addShape(pelvisShape);
world.addBody(pelvis);
demo.addVisual(pelvis);
// Upper body
var upperBody = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(0,pelvis.position.y+pelvisLength/2+upperBodyLength/2, 0),
});
upperBody.addShape(upperBodyShape);
world.addBody(upperBody);
demo.addVisual(upperBody);
// Head
var head = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(0,upperBody.position.y+upperBodyLength/2+headRadius+neckLength, 0),
});
head.addShape(headShape);
world.addBody(head);
demo.addVisual(head);
// Upper arms
var upperLeftArm = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(-shouldersDistance/2-upperArmLength/2, upperBody.position.y+upperBodyLength/2, 0),
});
var upperRightArm = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(shouldersDistance/2+upperArmLength/2, upperBody.position.y+upperBodyLength/2, 0),
});
upperLeftArm.addShape(upperArmShape);
upperRightArm.addShape(upperArmShape);
world.addBody(upperLeftArm);
world.addBody(upperRightArm);
demo.addVisual(upperLeftArm);
demo.addVisual(upperRightArm);
// lower arms
var lowerLeftArm = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3( upperLeftArm.position.x - lowerArmLength/2 - upperArmLength/2, upperLeftArm.position.y, 0)
});
var lowerRightArm = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3( upperRightArm.position.x + lowerArmLength/2 + upperArmLength/2, upperRightArm.position.y, 0)
});
lowerLeftArm.addShape(lowerArmShape);
lowerRightArm.addShape(lowerArmShape);
world.addBody(lowerLeftArm);
world.addBody(lowerRightArm);
demo.addVisual(lowerLeftArm);
demo.addVisual(lowerRightArm);
// Neck joint
var neckJoint = new CANNON.ConeTwistConstraint(head, upperBody, {
pivotA: new CANNON.Vec3(0,-headRadius-neckLength/2,0),
pivotB: new CANNON.Vec3(0,upperBodyLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
world.addConstraint(neckJoint);
// Knee joints
var leftKneeJoint = new CANNON.ConeTwistConstraint(lowerLeftLeg, upperLeftLeg, {
pivotA: new CANNON.Vec3(0, lowerLegLength/2,0),
pivotB: new CANNON.Vec3(0,-upperLegLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
var rightKneeJoint= new CANNON.ConeTwistConstraint(lowerRightLeg, upperRightLeg, {
pivotA: new CANNON.Vec3(0, lowerLegLength/2,0),
pivotB: new CANNON.Vec3(0,-upperLegLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
world.addConstraint(leftKneeJoint);
world.addConstraint(rightKneeJoint);
// Hip joints
var leftHipJoint = new CANNON.ConeTwistConstraint(upperLeftLeg, pelvis, {
pivotA: new CANNON.Vec3(0, upperLegLength/2,0),
pivotB: new CANNON.Vec3(-shouldersDistance/2,-pelvisLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
var rightHipJoint = new CANNON.ConeTwistConstraint(upperRightLeg, pelvis, {
pivotA: new CANNON.Vec3(0, upperLegLength/2,0),
pivotB: new CANNON.Vec3(shouldersDistance/2,-pelvisLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
world.addConstraint(leftHipJoint);
world.addConstraint(rightHipJoint);
// Spine
var spineJoint = new CANNON.ConeTwistConstraint(pelvis, upperBody, {
pivotA: new CANNON.Vec3(0,pelvisLength/2,0),
pivotB: new CANNON.Vec3(0,-upperBodyLength/2,0),
axisA: CANNON.Vec3.UNIT_Y,
axisB: CANNON.Vec3.UNIT_Y,
angle: angleA,
twistAngle: twistAngle
});
world.addConstraint(spineJoint);
// Shoulders
var leftShoulder = new CANNON.ConeTwistConstraint(upperBody, upperLeftArm, {
pivotA: new CANNON.Vec3(-shouldersDistance/2, upperBodyLength/2,0),
pivotB: new CANNON.Vec3(upperArmLength/2,0,0),
axisA: CANNON.Vec3.UNIT_X,
axisB: CANNON.Vec3.UNIT_X,
angle: angleB
});
var rightShoulder= new CANNON.ConeTwistConstraint(upperBody, upperRightArm, {
pivotA: new CANNON.Vec3(shouldersDistance/2, upperBodyLength/2,0),
pivotB: new CANNON.Vec3(-upperArmLength/2,0,0),
axisA: CANNON.Vec3.UNIT_X,
axisB: CANNON.Vec3.UNIT_X,
angle: angleB,
twistAngle: twistAngle
});
world.addConstraint(leftShoulder);
world.addConstraint(rightShoulder);
// Elbow joint
var leftElbowJoint = new CANNON.ConeTwistConstraint(lowerLeftArm, upperLeftArm, {
pivotA: new CANNON.Vec3(lowerArmLength/2, 0,0),
pivotB: new CANNON.Vec3(-upperArmLength/2,0,0),
axisA: CANNON.Vec3.UNIT_X,
axisB: CANNON.Vec3.UNIT_X,
angle: angleA,
twistAngle: twistAngle
});
var rightElbowJoint= new CANNON.ConeTwistConstraint(lowerRightArm, upperRightArm, {
pivotA: new CANNON.Vec3(-lowerArmLength/2,0,0),
pivotB: new CANNON.Vec3(upperArmLength/2,0,0),
axisA: CANNON.Vec3.UNIT_X,
axisB: CANNON.Vec3.UNIT_X,
angle: angleA,
twistAngle: twistAngle
});
world.addConstraint(leftElbowJoint);
world.addConstraint(rightElbowJoint);
// Move all body parts
for (var i = numBodiesAtStart; i < world.bodies.length; i++) {
var body = world.bodies[i];
body.position.vadd(position, body.position);
}
}
function createGround(world){
// add ground plane
var groundShape = new CANNON.Plane();
var groundBody = new CANNON.Body({ mass: 0 });
groundBody.addShape(groundShape);
groundBody.position.set(0,0,-1);
world.add(groundBody);
demo.addVisual(groundBody);
}
function createStaticSphere(world){
// Add a sphere to land on
var sphereShape = new CANNON.Sphere(4);
var sphereBody = new CANNON.Body({ mass: 0 });
sphereBody.addShape(sphereShape);
sphereBody.position.set(0,0,-1);
world.add(sphereBody);
demo.addVisual(sphereBody);
}
</script>
</body>
</html>