PlaneCollisionShape: Bugged?

My friends and I are having some trouble with PlaneCollisionShape. We’re using it as the collision shape for the “ground” in our game, as it is perfectly flat, and we want it to stretch on no matter how far you may walk. The problem is, the mere existence of a PlaneCollisionShape appears to cause collision listeners to ALWAYS fire EVERY tick, even when no collisions are occurring.



We have a hacky workaround in place right now, using a perfectly flat HeightfieldCollisionShape, which does not exhibit this behavior. But ultimately, we need to use PlaneCollisionShape so that there is no arbitrary limit to the world’s surface area before you just “fall off.”



Here is our Ground object, with the PlaneCollisionShape currently commented out with our workaround in place:

http://hg.avaraline.net/javara/src/6a911637c678/src/javara/world/physical/Ground.java#cl-33



Here is our PhysicsCollisionGroupListener instance that was firing unconditionally:

http://hg.avaraline.net/javara/src/6a911637c678/src/javara/world/World.java#cl-47



And for good measure, the class of the object whose collisions with the player are being listened for:

http://hg.avaraline.net/javara/src/6a911637c678/src/javara/world/goodies/Goody.java



So, what gives? Did we find a bug? Or are we doing something wrong?


  • ryan

(It is worth noting that we are running jME3 Nightlies. Sorry, forgot to mention it.)

Can you make a testcase for this problem? As soon as I implement collision listeners in native bullet I can check if this is a jbullet issue or if its in the norma bullet too.

Sure. Here you go, fresh out of the oven:



[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.bullet.collision.PhysicsCollisionGroupListener;

import com.jme3.bullet.collision.PhysicsCollisionObject;

import com.jme3.bullet.collision.shapes.BoxCollisionShape;

import com.jme3.bullet.collision.shapes.PlaneCollisionShape;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Plane;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Spatial.CullHint;

import com.jme3.scene.shape.Box;



public class Main extends SimpleApplication {

private BulletAppState bulletAppState;

private Geometry planeGeom, physicalBox, showOnCollisionEvent;



public static void main(String[] args) {

Main app = new Main();

app.start();

}



@Override

public void simpleInitApp() {

Box planeBox = new Box(Vector3f.ZERO, 5, 0.01f, 5);

PlaneCollisionShape plane = new PlaneCollisionShape(new Plane(Vector3f.UNIT_Y, 0));

RigidBodyControl planePhysics = new RigidBodyControl(plane, 0);

Material planeMat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

planeMat.setColor(“Color”, ColorRGBA.Yellow);



planeGeom = new Geometry(“Plane”, planeBox);

planeGeom.setMaterial(planeMat);

planeGeom.addControl(planePhysics);

planePhysics.setPhysicsLocation(new Vector3f(0, -5, 0));



Box b = new Box(Vector3f.ZERO, 1, 1, 1);

BoxCollisionShape physicsShape = new BoxCollisionShape(new Vector3f(1,1,1));

RigidBodyControl physics = new RigidBodyControl(physicsShape, 5);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.setColor(“Color”, ColorRGBA.Cyan);



physicalBox = new Geometry(“Physical Box”, b);

physicalBox.setMaterial(mat);

physicalBox.addControl(physics);

physics.setPhysicsLocation(new Vector3f(-1.5f, 0, 0));



Material mat2 = mat.clone();

mat2.setColor(“Color”, ColorRGBA.Magenta);

showOnCollisionEvent = new Geometry(“Signal Box”, b);

showOnCollisionEvent.setMaterial(mat2);

showOnCollisionEvent.setLocalTranslation(1.5f, 0, 0);

showOnCollisionEvent.setCullHint(CullHint.Always);



rootNode.attachChild(planeGeom);

rootNode.attachChild(physicalBox);

rootNode.attachChild(showOnCollisionEvent);



bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);



bulletAppState.getPhysicsSpace().enableDebug(assetManager);

bulletAppState.getPhysicsSpace().addCollisionGroupListener(testListener, 1);

bulletAppState.getPhysicsSpace().add(planePhysics);

bulletAppState.getPhysicsSpace().add(physics);

}



private PhysicsCollisionGroupListener testListener = new PhysicsCollisionGroupListener() {

public boolean collide(PhysicsCollisionObject obj1, PhysicsCollisionObject obj2) {

showOnCollisionEvent.setCullHint(CullHint.Inherit);

return true;

}

};

}

[/java]



Upon running it you should see a cyan box, falling towards a flat yellow quad. The quad is there to show you where the PlaneCollisionShape is, exactly. What you should not see is a magenta box, hovering in the air at the same level that the cyan box spawns. The expected behavior is for the magenta box to only show up after the cyan box smashes into the yellow quad. However, the magenta box appears immediately… because the existence of a PlaneCollisionShape in the physics space causes collision events to fire every tick. If you change the collision shape for the yellow quad to be something else, like a BoxCollisionShape, it behaves as expected. If you comment out the line that adds planePhysics to the physics space, it also behaves as expected: the magenta box doesn’t appear, and the cyan box falls through the quad

to no effect.


  • ryan

Can anyone confirm that they get the same results? Or are we just doing something wrong?


  • ryan

I get the same result yeah.