Rolling balls that never stop

I’m trying the physics in JMonkey with a simple example of a lot of balls bouncing and colliding with each other and the floor.

The problem is that many balls never come to a stop: they keep rolling down the floor. Why? How should I make them stop in a realistic way?

I’ve set the friction and restitution of both the floor and the balls and tried different values.

This is the complete code of the example:

[java]package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;

public class HelloBouncingBalls extends SimpleApplication {

public static void main(String[] args) {
    HelloBouncingBalls app = new HelloBouncingBalls();
    app.start();
}
/**
 * Prepare the Physics Application State (jBullet)
 */
private BulletAppState bulletAppState;

/**
 * Prepare geometries and physical nodes for the floor and the balls.
 */
private RigidBodyControl ball_phy;
private static final Sphere ball;
private RigidBodyControl floor_phy;
private static final Box floor;

static {
    /**
     * Initialize the ball geometry
     */
    ball = new Sphere(16, 16, 0.3f, true, false);
    ball.setTextureMode(TextureMode.Projected);
    /**
     * Initialize the floor geometry
     */
    floor = new Box(100f, 1f, 100f);
    floor.scaleTextureCoordinates(new Vector2f(6, 6));
}

@Override
public void simpleInitApp() {
    /**
     * Set up Physics Game
     */
    bulletAppState = new BulletAppState();
    
    stateManager.attach(bulletAppState);
    bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0f,-9.81f,0f));
    //bulletAppState.getPhysicsSpace().enableDebug(assetManager);

    /**
     * Configure cam to look at scene
     */
    cam.setLocation(new Vector3f(0, 5, -10));
    cam.lookAt(new Vector3f(0, 2, 0), Vector3f.UNIT_Y);
    /**
     * Initialize the scene, materials, and physics space
     */
    initBalls();
    initFloor();
}

/**
 * Make a solid floor and add it to the scene.
 */
public void initFloor() {
    Material floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");
    key3.setGenerateMips(true);
    Texture tex3 = assetManager.loadTexture(key3);
    tex3.setWrap(WrapMode.Repeat);
    floor_mat.setTexture("ColorMap", tex3);
    
    Geometry floor_geo = new Geometry("Floor", floor);
    floor_geo.setMaterial(floor_mat);
    floor_geo.setLocalTranslation(0, -0.1f, 0);
    this.rootNode.attachChild(floor_geo);
    /* Make the floor physical with mass 0.0f! */
    floor_phy = new RigidBodyControl(0.0f);
    
    floor_geo.addControl(floor_phy);
    bulletAppState.getPhysicsSpace().add(floor_phy);
    /* Floor physical properties */
    floor_phy.setRestitution(0.7f);
    floor_phy.setFriction(1f);
}

/**
 * This loop builds a lot of balls.
 */
public void initBalls() {
    for (int j = 0; j < 10; j++) {
        for (int i = -5; i < 5; i++) {
            Vector3f vt = new Vector3f(i * 2, 10, j * 2);
            makeBall(vt);
        }
    }
}

/**
 * This method creates one individual ball.
 */
public void makeBall(Vector3f loc) {
    /**
     * Create a ball geometry and attach to scene graph.
     */
    Material ball_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    ball_mat.setColor("Color", ColorRGBA.randomColor());
    Geometry ball_geo = new Geometry("ball", ball);
    ball_geo.setMaterial(ball_mat);
    rootNode.attachChild(ball_geo);
    /**
     * Make ball physical with a mass > 0.0f.
     */
    ball_phy = new RigidBodyControl(1f);
    /**
     * Add physical ball to physics space.
     */
    ball_geo.addControl(ball_phy);
    bulletAppState.getPhysicsSpace().add(ball_phy);
    /* Set an initial velocity */
    ball_phy.setLinearVelocity(new Vector3f(FastMath.rand.nextFloat()-0.5f,
            FastMath.rand.nextFloat(), FastMath.rand.nextFloat()-0.5f));
    /* Set physical properties */
    ball_phy.setRestitution(0.6f);
    ball_phy.setFriction(1f);
    ball_phy.setSleepingThresholds(1f, 1f);
    /* Set location */
    ball_phy.setPhysicsLocation(loc);
}

}[/java]

I’d use

[java]
ball_phy.setAngularDamping(0.5f);
[/java]

This slowly slows down the spinning of the ball, so that it eventually stops moving.
I don’t know if you should use this, but it does look realistic to me.

Thank you m41q!

I didn’t know about damping settings. Now it works like a charm!