Here’s a simple test case for this:
package test;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
import com.jme3.bullet.control.GhostControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
/**
*
* @author joliver82
*/
public class MinieContactTestSimpleTest extends SimpleApplication implements PhysicsCollisionListener, ActionListener
{
private enum CollisionShapeMode
{
MESH, GIMPACT, DYNAMIC
};
private BulletAppState bullet;
private int collisions=0;
private GhostControl collisionTester;
// Test stuff
CollisionShapeMode collShapeMode=CollisionShapeMode.GIMPACT; // Change this to test other collision shapes
public static void main(String[] args) {
MinieContactTestSimpleTest app = new MinieContactTestSimpleTest();
app.start();
}
@Override
public void simpleInitApp()
{
flyCam.setDragToRotate(true);
flyCam.setMoveSpeed(10);
cam.setLocation(new Vector3f(0,10,10));
cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
// Physics
bullet=new BulletAppState();
bullet.setDebugEnabled(true);
bullet.setDebugCamera(cam);
getStateManager().attach(bullet);
//bullet.getPhysicsSpace().addCollisionListener(this);
// Materials
Material grayMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
grayMat.setColor("Color", ColorRGBA.LightGray);
Material redMat=grayMat.clone();
redMat.setColor("Color", ColorRGBA.Red);
Material greenMat=grayMat.clone();
greenMat.setColor("Color", ColorRGBA.Green);
Material blueMat=grayMat.clone();
blueMat.setColor("Color", ColorRGBA.Blue);
// Scene
Geometry floor=new Geometry("Floor");
floor.setMesh(new Box(Vector3f.ZERO, 50, 0.1f, 50));
floor.setMaterial(grayMat);
rootNode.attachChild(floor);
Spatial tmpSpat;
tmpSpat=createCollidableObject(new Box(Vector3f.ZERO, 1, 1, 1), redMat, new Vector3f(-1.9f,1,0), collShapeMode);
bullet.getPhysicsSpace().addCollisionObject(tmpSpat.getControl(GhostControl.class));
rootNode.attachChild(tmpSpat);
tmpSpat=createCollidableObject(new Box(Vector3f.ZERO, 1, 1, 1), greenMat, new Vector3f(0,1,0), collShapeMode);
bullet.getPhysicsSpace().addCollisionObject(tmpSpat.getControl(GhostControl.class));
collisionTester=tmpSpat.getControl(GhostControl.class);
rootNode.attachChild(tmpSpat);
tmpSpat=createCollidableObject(new Box(Vector3f.ZERO, 1, 1, 1), blueMat, new Vector3f(1.9f,1,0), collShapeMode);
bullet.getPhysicsSpace().addCollisionObject(tmpSpat.getControl(GhostControl.class));
rootNode.attachChild(tmpSpat);
// setup keys
getInputManager().addMapping("Overlap", new KeyTrigger(KeyInput.KEY_O));
getInputManager().addListener(this,"Overlap");
}
private Spatial createCollidableObject(Mesh mesh, Material mat, Vector3f position, CollisionShapeMode mode)
{
Geometry geom=new Geometry("");
geom.setMesh(mesh);
geom.setMaterial(mat);
geom.setLocalTranslation(position);
CollisionShape collShape;
switch(mode)
{
case MESH:
collShape=CollisionShapeFactory.createMeshShape(geom);
break;
case GIMPACT:
collShape=new GImpactCollisionShape(mesh);
break;
case DYNAMIC:
default:
collShape=CollisionShapeFactory.createDynamicMeshShape(geom);
break;
}
GhostControl gc=new GhostControl(collShape);
geom.addControl(gc);
return geom;
}
@Override
public void collision(PhysicsCollisionEvent event)
{
++collisions;
System.out.println("collision callback was run " + collisions + " times");
}
@Override
public void onAction(String name, boolean isPressed, float tpf)
{
if("Overlap".equals(name) && isPressed)
{
// Run contact test over a predefined object
collisions=0;
if(collisionTester!=null)
{
int contactTests=bullet.getPhysicsSpace().contactTest(collisionTester, this);
System.out.println("Got " + contactTests + " from contactTest");
}
}
}
}
To test with different collision shapes, change the field collShapeMode to either MESH, GIMPACT or DYNAMIC
Notice the line //bullet.getPhysicsSpace().addCollisionListener(this);
which is commented on purpose as I don’t want it to be reacting to all events but just after I’ve called contactTest
These are my results:
- For dynamic (hull collision shape) → contactTest returns 2 and the collision callback is called twice (correct)
- For mesh → contactTest returns 0 and the collision callback is not called (issue)
- For gimpact → same behaviour as mesh
If I add the collision listener to the physics space (bullet.getPhysicsSpace().addCollisionListener(this);
) the collision callback is called continuously (because there are collisions) but returned value of contactTest keep the same (0 for both mesh and gimpact)
Thanks 