I have functions that get called when two shapes collide, each step as long shapes collide and when shapes don’t collide anymore. First I tried my own solution based on PhysicsCollisionListener, but was very unhappy with it and tried to ported it to ContactListener, since it seem it does exactly what I want.
But I noted, onContactStarted get called multiple times, basing on the used shapes and controls:
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.ContactListener;
import com.jme3.bullet.collision.PersistentManifolds;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.GhostControl;
import com.jme3.input.ChaseCamera;
import com.jme3.light.DirectionalLight;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
public final class Main extends SimpleApplication {
@Override
public void simpleInitApp() {
final Node ninjaNode = new Node();
final Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
ninja.scale(0.05f, 0.05f, 0.05f);
ninja.rotate(0.0f, -3.0f, 0.0f);
ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);
ninjaNode.attachChild(ninja);
final Node ninjaShapeNode = new Node("NinjaShape");
ninjaNode.attachChild(ninjaShapeNode);
getRootNode().attachChild(ninjaNode);
final BulletAppState bullet = new BulletAppState();
bullet.setDebugEnabled(true);
getStateManager().attach(bullet);
bullet.getPhysicsSpace().addContactListener(new Listener());
final GhostControl ninjaGhost = new GhostControl(new SphereCollisionShape(25));
ninjaShapeNode.addControl(ninjaGhost);
bullet.getPhysicsSpace().add(ninjaGhost);
final CharacterControl ninjaControl = new CharacterControl(new BoxCollisionShape(10, 10, 10), 0);
ninjaControl.setGravity(0);
//final RigidBodyControl ninjaControl = new RigidBodyControl(CollisionShapeFactory.createMeshShape(ninja), 0);
//final RigidBodyControl ninjaControl = new RigidBodyControl(new BoxCollisionShape(10, 10, 10), 0);
ninja.addControl(ninjaControl);
bullet.getPhysicsSpace().add(ninjaControl);
ninja.addControl(new ChaseCamera(getCamera(), ninja, getInputManager()));
getRootNode().addLight(new DirectionalLight(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal()));
}
private static class Listener implements ContactListener {
@Override
public void onContactStarted(final long manifoldId) {
final long bodyAId = PersistentManifolds.getBodyAId(manifoldId);
final PhysicsCollisionObject pcoA = PhysicsCollisionObject.findInstance(bodyAId);
final long bodyBId = PersistentManifolds.getBodyBId(manifoldId);
final PhysicsCollisionObject pcoB = PhysicsCollisionObject.findInstance(bodyBId);
final Spatial spatialA = getSpatialFromPCO(pcoA);
final Spatial spatialB = getSpatialFromPCO(pcoB);
if(spatialA == null || spatialB == null) {
return;
}
final String nameA = spatialA.getName();
final String nameB = spatialB.getName();
System.out.println("Started:" + nameA + " - " + nameB);
}
@Override
public void onContactProcessed(final PhysicsCollisionObject pcoA, final PhysicsCollisionObject pcoB, final long manifoldId) {
}
@Override
public void onContactEnded(final long manifoldId) {
final long bodyAId = PersistentManifolds.getBodyAId(manifoldId);
final PhysicsCollisionObject pcoA = PhysicsCollisionObject.findInstance(bodyAId);
final long bodyBId = PersistentManifolds.getBodyBId(manifoldId);
final PhysicsCollisionObject pcoB = PhysicsCollisionObject.findInstance(bodyBId);
final Spatial spatialA = getSpatialFromPCO(pcoA);
final Spatial spatialB = getSpatialFromPCO(pcoB);
if(spatialA == null || spatialB == null) {
return;
}
final String nameA = spatialA.getName();
final String nameB = spatialB.getName();
System.out.println("Ended:" + nameA + " - " + nameB);
}
public Spatial getSpatialFromPCO(final PhysicsCollisionObject obj) {
final Object userObject = obj.getUserObject();
if (userObject instanceof Spatial) {
return (Spatial) (userObject);
}
return(null);
}
}
public static void main(final String[] args) {
new Main().start();
}
}
With
final CharacterControl ninjaControl = new CharacterControl(new BoxCollisionShape(10, 10, 10), 0);
ninjaControl.setGravity(0);
it prints
Started:NinjaShape - Ninja-ogremesh
Started:NinjaShape - Ninja-ogremesh
With
final RigidBodyControl ninjaControl = new RigidBodyControl(CollisionShapeFactory.createMeshShape(ninja), 0);
also.
With
final RigidBodyControl ninjaControl = new RigidBodyControl(new BoxCollisionShape(10, 10, 10), 0);
it prints just one line.
Did I done something wrong?