Energy

I used a code from here , removed bricks and added a ceiling. Then I adjusted parameters to make all collisions elastic.When the sphere collides with a joints of walls or when 2 spheres collides with each other, there is a speed loss. If in the room there are a lot of spheres, gradually they are slowed down and stop. On what energy of spheres is spent?

[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.font.BitmapText;
import com.jme3.material.Material;
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;
import com.jme3.math.ColorRGBA;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.KeyInput;

public class HelloJME3 extends SimpleApplication {

public static void main(String args[]) {
HelloJME3 app = new HelloJME3();
app.start();  
}

private BulletAppState bulletAppState;

/** Prepare Materials */
Material wall_mat;
Material stone_mat;
Material floor_mat;

/** Prepare geometries and physical nodes for bricks and cannon balls. */
private RigidBodyControl ball_phy;
private static final Sphere sphere;
private RigidBodyControl floor_phy;
private static final Box floor;
private RigidBodyControl wall_phy;
private static final Box wall;

static {
/** Initialize the cannon ball geometry /
sphere = new Sphere(32, 32, 0.2f, true, false);
sphere.setTextureMode(TextureMode.Projected);
/
* Initialize the floor geometry */
floor = new Box(5f, 0.8f, 5f);
floor.scaleTextureCoordinates(new Vector2f(3, 6));
wall = new Box(5f, 5f, 0.8f);
wall.scaleTextureCoordinates(new Vector2f(3, 6));
}

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

/** Configure cam to look at scene */
cam.setLocation(new Vector3f(0, 4f, 6f));
cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y);
/** Add InputManager action: Left click triggers shooting. */
inputManager.addMapping("shoot", 
        new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(actionListener, "shoot");
inputManager.addListener(actionListener, "pause");
/** Initialize the scene, materials, and physics space */
initMaterials();
initFloor(0f);
initFloor(10f);
initWall();
initCrossHairs();

}

/**

  • Every time the shoot action is triggered, a new cannon ball is produced.
  • The ball is set up to fly from the camera position in the camera direction.
    */
    private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
    if (name.equals(“shoot”) && !keyPressed) {
    makeCannonBall();
    }
    }
    };

/** Initialize the materials used in this scene. */
public void initMaterials() {
wall_mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
TextureKey key = new TextureKey(“Textures/Terrain/BrickWall/BrickWall.jpg”);
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
wall_mat.setTexture(“ColorMap”, tex);

stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
stone_mat.setTexture("ColorMap", tex2);

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);

}

/** Make a solid floor and add it to the scene. /
public void initFloor(float heigth) {
Geometry floor_geo = new Geometry(“Floor”, floor);
floor_geo.setMaterial(floor_mat);
floor_geo.setLocalTranslation(0, heigth, 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_phy.setRestitution(1f);
floor_phy.setFriction(1f);
floor_phy.setKinematic(true);
}

/** Make a solid floor and add it to the scene. */

public void initWall() {
Vector3f loc = new Vector3f(0f, 5f, -5f);
makeWall(loc, false);
loc = new Vector3f(0f, 5f, 5f);
makeWall(loc, false);
loc = new Vector3f(5f, 5f, 0f);
makeWall(loc, true);
loc = new Vector3f(-5f, 5f, 0f);
makeWall(loc, true);
}

public void makeWall(Vector3f loc, boolean rotate) {
Geometry wall_geo = new Geometry(“Wall”, wall);
wall_geo.setMaterial(floor_mat);
wall_geo.setLocalTranslation(loc);
if (rotate) {
wall_geo.rotate(0, 3.1415f / 2, 0);
}
this.rootNode.attachChild(wall_geo);
/* Make the floor physical with mass 0.0f! */
wall_phy = new RigidBodyControl(0.0f);
wall_geo.addControl(wall_phy);
bulletAppState.getPhysicsSpace().add(wall_phy);
wall_phy.setKinematic(true);
wall_phy.setFriction(1f);
wall_phy.setRestitution(1f);
}

/** This method creates one individual physical cannon ball.

  • By defaul, the ball is accelerated and flies
  • from the camera position in the camera direction.*/
    public void makeCannonBall() {
    /** Create a cannon ball geometry and attach to scene graph. /
    Geometry ball_geo = new Geometry(“cannon ball”, sphere);
    Material mat1 = new Material(assetManager,
    “Common/MatDefs/Misc/Unshaded.j3md”);
    mat1.setColor(“Color”, ColorRGBA.Blue);
    ball_geo.setMaterial(mat1);
    //ball_geo.setMaterial(stone_mat);
    rootNode.attachChild(ball_geo);
    /
    * Position the cannon ball /
    ball_geo.setLocalTranslation(cam.getLocation());
    /
    * Make the ball physcial with a mass > 0.0f /
    ball_phy = new RigidBodyControl(1f);
    /
    * Add physical ball to physics space. /
    ball_geo.addControl(ball_phy);
    ball_phy.setRestitution(1.0f);
    ball_phy.setKinematic(false);
    ball_phy.setFriction(1.0f);
    bulletAppState.getPhysicsSpace().add(ball_phy);
    /
    * Accelerate the physcial ball to shoot it. */
    ball_phy.setLinearVelocity(cam.getDirection().mult(25));
    }

/** A plus sign used as crosshairs to help the player with aiming.*/
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // fake crosshairs :slight_smile:
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}
}
[/java]

Well first of all keep in midn that computer game physics are not like newtonian physics but more impulse based look alright ones.

So:

  1. A part of the energy might go into the friction
  2. Bullet is quite conservative with forces, so in most cases inaccurate calculations are rounded down instead of up (compare bullet vehicle with physx x here, where such safeguards are obiviously not present ^^)
  3. Bullet does not really have something like bounciness, due to the internal workings, but you could try to use a lower resititution on the wall (and maybee a slightly increased margin) then it would behave more like a rubbber ball instead of a stone ball

Where does most inaccuracys come from?
Wel in when it calculates a tick, all meshes are moved and rotated according to ther velocity and angular velocity (and addition applied foreces ect),
then it is searched for intersecting geometrys, once such are found, a correcting force (a solution) is searched that would resolve the logical conflict of two overlapping object and is applied.
This means depending on the tick size the objects intersect by a different amount, (or might even teleport trough other objects) and create different solutions with different forces.

What this means practically -> If you are required to have a mostly deterministic physics engine it might be a good idea, to make sure that bullet runs internal with always the same step size (for this the substeps are, bullet normally use 1/60s ticks and if the tpf passed is to large, it does several ticks internally to have a minimum amount of reliability)
to prevent tunneling a ccd feature can be used, similar to a ray test bullet does a sweep test that is using the actual mesh for testing instead of a ray and thus is able to detect tunneling properly and take objects inbetween into account.

3 Likes

Thanks for your answer!

<cite>@Empire Phoenix said:</cite> 1. A part of the energy might go into the friction
I set setFriction (1f) both to walls, and spheres, however it didn't help.
<cite>@Empire Phoenix said:</cite> Bullet does not really have something like bounciness, due to the internal workings, but you could try to use a lower resititution on the wall (and maybee a slightly increased margin) then it would behave more like a rubbber ball instead of a stone ball
Reduction of restitution of walls led only to even big losses of speed.

I consider that the problem arises because of rotation of spheres round its pivot-center. When the sphere hits in a room corner, it loses about a half of the speed. Is it possible to disable the rotation of spheres and how to do it?

If all you are wanting is perfect lossless bounces of spheres against each other and planes then that’s a trivial problem - just write your own physics and get the exact behaviour you need.

<cite>@Phaser said:</cite> Reduction of restitution of walls led only to even big losses of speed.

If you want it to bounce more, then you need to raise the restitution not lower it.

<cite>@Phaser said:</cite> Is it possible to disable the rotation of spheres and how to do it?

Every pre-tick call
[java]control.setAngularVelocity (Vector3f.ZERO);[/java]

Ah right, sorry yes, higher the restitution ^^

Do you need to completely eliminate the error?
In that case, tweaking Bullet will help but never be perfect, and the error will accumulate.
You can try reinjecting the missing energy, e.g. by speeding up the balls in each frame to correct the missing energy amount.

Thanks to all for answers! Now I manually correct speed at each collision, the problem is solved.