RigidBodyControl with PlaneCollisionShape breaks other RigidBodyControl's

Hi All,

Below is a modified version of the HelloCollision tutorial. In it I have two boxes(“crates”) that are represented by RigidBodyControls. More boxes can be created by left clicking on an object. I am attempting to create an invisible boundary wall on the side of the town that the camera is facing when the application is run. I am doing this with a PlaneCollisionShape.

If the code is run with the lines for adding the PlaneCollisionShape in the setUpWorld() method commented out, the boxes fall from the sky and collide with the floor as expected. If the lines are un-commented, the boxes fall through the floor. Also, when it does get added, there is a NullPointerException thrown when the application is exited. Below is the code that this happens with:

[java]package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.PlaneCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Plane;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import java.util.Random;

public class PlaneTestApplication extends SimpleApplication
implements ActionListener {

private Spatial sceneModel;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private RigidBodyControl zNegativeControl;
private Vector3f sunLightDirection = new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal();
private Node crates = new Node();
private Vector3f CRATE_GRAVITY = new Vector3f(0, -25f, 0);
private float spawnCrateSize = 1;

BitmapText hudCrateText;

public static void main(String[] args) {
AppSettings settings = new AppSettings(true);
settings.setRenderer(AppSettings.LWJGL_OPENGL2);
settings.setResolution(1600, 900);
settings.setVSync(true);

PlaneTestApplication app = new PlaneTestApplication();
app.setDisplayStatView(false);
app.setShowSettings(false);
app.setSettings(settings);
app.start();

}

public void simpleInitApp() {
flyCam.setMoveSpeed(75);
cam.setLocation(new Vector3f(0, 30, 60));
cam.lookAt(Vector3f.ZERO, cam.getUp());

bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
bulletAppState.setDebugEnabled(true);
bulletAppState.getPhysicsSpace().setGravity(Vector3f.ZERO);

setUpKeys();
setUpCrossHairs();
setUpWorld();
setUpLight();

}

private void setUpLight() {
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);

DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(sunLightDirection);
rootNode.addLight(dl);

}

private void setUpKeys() {
inputManager.addMapping(“LeftClick”, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(this, “LeftClick”);
}

private void setUpWorld() {
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));

assetManager.registerLocator("Assets/Scenes/town.zip", ZipLocator.class);
sceneModel = assetManager.loadModel("main.scene");
sceneModel.setLocalScale(2f);

CollisionShape sceneShape = CollisionShapeFactory.createMeshShape((Node) sceneModel);
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);

setUpCrate(new Vector3f(0, 30, -10), 1.75f);
setUpCrate(new Vector3f(0, 60, -10), 1.25f);

rootNode.attachChild(crates);

Plane zNegativePlane = new Plane();
zNegativePlane.setNormal(Vector3f.UNIT_Z);
zNegativePlane.setConstant(-217);
PlaneCollisionShape zNegativeCol = new PlaneCollisionShape(zNegativePlane);
zNegativeControl = new RigidBodyControl(zNegativeCol);

sceneModel.addControl(zNegativeControl);
bulletAppState.getPhysicsSpace().add(zNegativeControl);

bulletAppState.getPhysicsSpace().add(landscape);

rootNode.attachChild(sceneModel);

}

private void setUpCrate(Vector3f location, float halfSize) {
Box crate = new Box(halfSize, halfSize, halfSize);
Geometry crateGeo = new Geometry(“Crate”, crate);
Material matCrate = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);
matCrate.setBoolean(“UseMaterialColors”,true);
matCrate.setColor(“Diffuse”, ColorRGBA.Brown.mult(3));
crateGeo.setMaterial(matCrate);
rootNode.attachChild(crateGeo);

BoxCollisionShape crateShape = new BoxCollisionShape(new Vector3f(halfSize, halfSize, halfSize));
RigidBodyControl crateControl = new RigidBodyControl(crateShape, 1);
crateGeo.addControl(crateControl);
bulletAppState.getPhysicsSpace().add(crateControl);
crateControl.setPhysicsLocation(location);
crateControl.setGravity(CRATE_GRAVITY);

crates.attachChild(crateGeo);

}

protected void setUpCrossHairs() {
guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+");
ch.setLocalTranslation(
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}

public void onAction(String binding, boolean value, float tpf) {
if (binding.equals(“LeftClick”) && value) {
CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
rootNode.collideWith(ray, results);

  if (results.size() > 0) {
    CollisionResult closest = results.getClosestCollision();
    setUpCrate(closest.getContactPoint().add(
      closest.getContactNormal().normalize().multLocal(spawnCrateSize * 1.5f)),
      spawnCrateSize);
  }
}

}

@Override
public void simpleUpdate(float tpf) { }
}[/java]

I am using the 3.0 stable release of the SDK. Any insight on this problem would be appreciated.

I can’t see an error in your code - at least not from just looking at it.
You have 2 options:

  1. You think there is a bug in the engine and want it fixed:
    Provide a minimal test case. That means no crosshairs, no hud text, no assets which need to be loaded…
    This test case can be tested easily by anyone and the issue confirmed.

  2. You just want your game running.
    Use BoxCollisionShape. It’s working. I use it myself.

Found the problem while creating the test case. The plane’s RigidBodyControl instance needs to have 0 mass, just like the level. I had thought that I tried that from following the Dynamic vs. Kinematic vs. Static chart in the local physics integration help, but I guess not.