chandlerprall / Physijs

Physics plugin for Three.js
MIT License
2.75k stars 455 forks source link

force of friction doesn't work #274

Closed df257 closed 8 years ago

df257 commented 8 years ago

var geo=new THREE.SphereGeometry(5,20,20); var mat=new Physijs.createMaterial(new THREE.MeshLambertMaterial({color:'#f60'}),10000,10); var mesh=new Physijs.SphereMesh(geo,mat,10); mesh.position.set(0,30,0); scene.add(mesh);

The ground is also set 10000, but sphere still rolling

ghost commented 8 years ago

@df257 your friction and restitution values should always be between 0 and 1, because past that I don't think it makes a difference. Details found on wiki.

Anyways, for your sphere, it's not actually a problem. The friction is what actually makes the ball roll. Without it the ball would slide onto the ground (assuming both objects have friction set to 0). If you don't want the ball to roll, how about packing it into a box representation:

var geo = new THREE.SphereGeometry(5, 20, 20);
var mat = Physijs.createMaterial(new THREE.MeshLambertMaterial({color: "#f60"}), 1, 0);
var mesh = new Physijs.BoxMesh(geo, mat, 10);
// do extra stuff...

In this case, it should not slide at all when it hits the ground because in the physics area, it thinks it is a box, so the friction response is different. You could of course use mesh.setAngularVelocity and pass it with a zero vector, which will cancel all rolling forces on the object:

var zvec = new THREE.Vector3(0, 0, 0);

// Disable rolling only when in contact
mesh.addEventListener("collision", function(obj_b, a, b){
    mesh.setAngularVelocity(zvec);
});

Hope this helps.

df257 commented 8 years ago

@xprogram, I'm sorry, my question is not clear. It should keep rolling and scroll for a while, then stop. In my case, this sphere not stop and I changed the friction to 1.

In your case, I changed SphereMesh to BoxMesh, sphere is not rolling.

ghost commented 8 years ago

Ah. Now I get it! Well, looking at #32, you can make this possible with:

var linearDamping = 0.5;
var angularDamping = 0;
mesh.setDamping(linearDamping, angularDamping);

This creates an effect of drag, which slows down the sphere over time. It should be what you are looking for.

df257 commented 8 years ago

@xprogram, thank you very much for your help, but this code just make the sphere roll slowly. Slows down over time, the sphere is not stop.

ghost commented 8 years ago

Ok... how about this:

// Slow down sphere manually over time
var slowing_rate = new THREE.Vector3(1, 1, 1);
var mesh_eps = 0.0001;
scene.addEventListener("update", function(){
    if(mesh.getAngularVelocity().length() < mesh_eps){
        mesh.setAngularVelocity(new THREE.Vector3(0, 0, 0));
    } else {
        mesh.setAngularVelocity(mesh.getAngularVelocity().sub(slowing_rate));
    }
});

This code binds an event listener so that every scene update, the sphere rolling speed is lowered by the slowing_rate vector by accessing the speed already defined and subtracting it by the vector. When the rolling speed gets really small (in this case smaller than mesh_eps), we can pretty much disable rolling speed. You should tweak slowing_rate to your own value by replacing every constructor parameter with some number.