Skip to content

Commit

Permalink
per-material friction and restitution
Browse files Browse the repository at this point in the history
  • Loading branch information
schteppe committed Jan 5, 2015
1 parent ccb78bf commit 09c91fd
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 4 deletions.
71 changes: 71 additions & 0 deletions demos/simpleFriction.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<title>cannon.js - friction 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>

/**
* How to set friction per material.
*/

var demo = new CANNON.Demo(), size = 1.0;

demo.addScene("Friction", function(){
var shape = new CANNON.Box(new CANNON.Vec3(size,size,size));

// Create world
var world = demo.getWorld();
world.broadphase = new CANNON.NaiveBroadphase();
world.iterations = 10;

// Materials
var groundMaterial = new CANNON.Material();
groundMaterial.friction = 0.3;

// ground plane
var groundShape = new CANNON.Plane();
var groundBody = new CANNON.Body({ mass: 0, material: groundMaterial });
groundBody.addShape(groundShape);
world.add(groundBody);
demo.addVisual(groundBody);

// Create a slippery material (friction coefficient = 0.0)
var slipperyMaterial = new CANNON.Material();
slipperyMaterial.friction = 0;

// Create slippery box
var boxBody = new CANNON.Body({ mass: 1, material: slipperyMaterial });
boxBody.addShape(shape);
boxBody.position.set(0,0,5);
world.add(boxBody);
demo.addVisual(boxBody);

// Create box made of groundMaterial
var boxBody2 = new CANNON.Body({ mass: 10, material: groundMaterial });
boxBody2.addShape(shape);
boxBody2.position.set(size*4,0,5);
world.add(boxBody2);
demo.addVisual(boxBody2);

// Change gravity so the boxes will slide along x axis
world.gravity.set(-3,0,-60);
});

demo.start();

</script>
</body>
</html>
14 changes: 13 additions & 1 deletion src/material/Material.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,24 @@ function Material(name){
* @type {String}
*/
this.name = name;

/**
* material id.
* @property id
*/
this.id = Material.idCounter++;

/**
* Friction for this material.
* @property {number} friction
*/
this.friction = -1;

/**
* Restitution for this material.
* @property {number} restitution
*/
this.restitution = -1;
}

Material.idCounter = 0;
18 changes: 15 additions & 3 deletions src/world/World.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,6 @@ World.prototype.internalStep = function(dt){
} else {
cm = this.defaultContactMaterial;
}
var mu = cm.friction;

// g = ( xj + rj - xi - ri ) .dot ( ni )
var gvec = World_step_gvec;
Expand All @@ -602,7 +601,20 @@ World.prototype.internalStep = function(dt){

c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;

c.restitution = cm.restitution;
var mu = cm.friction;
c.restitution = cm.restitution;

// If friction or restitution were specified in the material, use them
if(bi.material && bj.material){
if(bi.material.friction >= 0 && bj.material.friction >= 0){
mu = bi.material.friction * bj.material.friction;
}

if(bi.material.restitution >= 0 && bj.material.restitution >= 0){
c.restitution = bi.material.restitution * bj.material.restitution;
}
}

c.penetration = g;
c.setSpookParams(cm.contactEquationStiffness,
cm.contactEquationRelaxation,
Expand All @@ -614,7 +626,7 @@ World.prototype.internalStep = function(dt){
if(mu > 0){

// Create 2 tangent equations
var mug = mu*gnorm;
var mug = mu * gnorm;
var reducedMass = (bi.invMass + bj.invMass);
if(reducedMass > 0){
reducedMass = 1/reducedMass;
Expand Down

0 comments on commit 09c91fd

Please sign in to comment.