diff --git a/engine/src/jbullet/com/jme3/bullet/PhysicsSpace.java b/engine/src/jbullet/com/jme3/bullet/PhysicsSpace.java index 0c9e15669..e4235ce8a 100644 --- a/engine/src/jbullet/com/jme3/bullet/PhysicsSpace.java +++ b/engine/src/jbullet/com/jme3/bullet/PhysicsSpace.java @@ -132,8 +132,8 @@ public class PhysicsSpace { private int maxSubSteps = 4; private javax.vecmath.Vector3f rayVec1 = new javax.vecmath.Vector3f(); private javax.vecmath.Vector3f rayVec2 = new javax.vecmath.Vector3f(); - private com.bulletphysics.linearmath.Transform sweepTrans1=new com.bulletphysics.linearmath.Transform(new javax.vecmath.Matrix3f()); - private com.bulletphysics.linearmath.Transform sweepTrans2=new com.bulletphysics.linearmath.Transform(new javax.vecmath.Matrix3f()); + private com.bulletphysics.linearmath.Transform sweepTrans1 = new com.bulletphysics.linearmath.Transform(new javax.vecmath.Matrix3f()); + private com.bulletphysics.linearmath.Transform sweepTrans2 = new com.bulletphysics.linearmath.Transform(new javax.vecmath.Matrix3f()); private AssetManager debugManager; /** @@ -559,7 +559,20 @@ public class PhysicsSpace { private void addRigidBody(PhysicsRigidBody node) { physicsNodes.put(node.getObjectId(), node); + + //Workaround + //It seems that adding a Kinematic RigidBody to the dynamicWorld prevent it from being non kinematic again afterward. + //so we add it non kinematic, then set it kinematic again. + boolean kinematic = false; + if (node.isKinematic()) { + kinematic = true; + node.setKinematic(false); + } dynamicsWorld.addRigidBody(node.getObjectId()); + if (kinematic) { + node.setKinematic(true); + } + Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding RigidBody {0} to physics space.", node.getObjectId()); if (node instanceof PhysicsVehicle) { Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding vehicle constraint {0} to physics space.", ((PhysicsVehicle) node).getVehicleId()); @@ -695,13 +708,13 @@ public class PhysicsSpace { * You have to use different Transforms for start and end (at least distance > 0.4f). * SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center. */ - public List sweepTest(CollisionShape shape, Transform start, Transform end){ + public List sweepTest(CollisionShape shape, Transform start, Transform end) { List results = new LinkedList(); - if(!(shape.getCShape() instanceof ConvexShape)){ + if (!(shape.getCShape() instanceof ConvexShape)) { Logger.getLogger(PhysicsSpace.class.getName()).log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!"); return results; } - dynamicsWorld.convexSweepTest((ConvexShape)shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); + dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); return results; } @@ -711,17 +724,17 @@ public class PhysicsSpace { * You have to use different Transforms for start and end (at least distance > 0.4f). * SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center. */ - public List sweepTest(CollisionShape shape, Transform start, Transform end, List results){ + public List sweepTest(CollisionShape shape, Transform start, Transform end, List results) { results.clear(); - if(!(shape.getCShape() instanceof ConvexShape)){ + if (!(shape.getCShape() instanceof ConvexShape)) { Logger.getLogger(PhysicsSpace.class.getName()).log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!"); return results; } - dynamicsWorld.convexSweepTest((ConvexShape)shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); + dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); return results; } - private class InternalSweepListener extends CollisionWorld.ConvexResultCallback{ + private class InternalSweepListener extends CollisionWorld.ConvexResultCallback { private List results; @@ -735,7 +748,6 @@ public class PhysicsSpace { results.add(new PhysicsSweepTestResult(obj, Converter.convert(lcr.hitNormalLocal), lcr.hitFraction, bln)); return lcr.hitFraction; } - } /** diff --git a/engine/src/test/jme3test/bullet/TestKinematicAddToPhysicsSpaceIssue.java b/engine/src/test/jme3test/bullet/TestKinematicAddToPhysicsSpaceIssue.java new file mode 100644 index 000000000..8947d8a7e --- /dev/null +++ b/engine/src/test/jme3test/bullet/TestKinematicAddToPhysicsSpaceIssue.java @@ -0,0 +1,80 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package jme3test.bullet; + +import com.jme3.app.SimpleApplication; +import com.jme3.bullet.BulletAppState; +import com.jme3.bullet.PhysicsSpace; +import com.jme3.bullet.collision.shapes.MeshCollisionShape; +import com.jme3.bullet.collision.shapes.PlaneCollisionShape; +import com.jme3.bullet.collision.shapes.SphereCollisionShape; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.math.Plane; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.shape.Sphere; + +/** + * + * @author Nehon + */ +public class TestKinematicAddToPhysicsSpaceIssue extends SimpleApplication { + + public static void main(String[] args) { + TestKinematicAddToPhysicsSpaceIssue app = new TestKinematicAddToPhysicsSpaceIssue(); + app.start(); + } + BulletAppState bulletAppState; + + @Override + public void simpleInitApp() { + + bulletAppState = new BulletAppState(); + stateManager.attach(bulletAppState); + bulletAppState.getPhysicsSpace().enableDebug(assetManager); + // Add a physics sphere to the world + Node physicsSphere = PhysicsTestHelper.createPhysicsTestNode(assetManager, new SphereCollisionShape(1), 1); + physicsSphere.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(3, 6, 0)); + rootNode.attachChild(physicsSphere); + + //Setting the rigidBody to kinematic before adding it to the physic space + physicsSphere.getControl(RigidBodyControl.class).setKinematic(true); + //adding it to the physic space + getPhysicsSpace().add(physicsSphere); + //Making it not kinematic again, it should fall under gravity, it doesn't + physicsSphere.getControl(RigidBodyControl.class).setKinematic(false); + + // Add a physics sphere to the world using the collision shape from sphere one + Node physicsSphere2 = PhysicsTestHelper.createPhysicsTestNode(assetManager, new SphereCollisionShape(1), 1); + physicsSphere2.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(5, 6, 0)); + rootNode.attachChild(physicsSphere2); + + //Adding the rigid body to physic space + getPhysicsSpace().add(physicsSphere2); + //making it kinematic + physicsSphere2.getControl(RigidBodyControl.class).setKinematic(false); + //Making it not kinematic again, it works properly, the rigidbody is affected by grvity. + physicsSphere2.getControl(RigidBodyControl.class).setKinematic(false); + + + + // an obstacle mesh, does not move (mass=0) + Node node2 = PhysicsTestHelper.createPhysicsTestNode(assetManager, new MeshCollisionShape(new Sphere(16, 16, 1.2f)), 0); + node2.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(2.5f, -4, 0f)); + rootNode.attachChild(node2); + getPhysicsSpace().add(node2); + + // the floor mesh, does not move (mass=0) + Node node3 = PhysicsTestHelper.createPhysicsTestNode(assetManager, new PlaneCollisionShape(new Plane(new Vector3f(0, 1, 0), 0)), 0); + node3.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f, -6, 0f)); + rootNode.attachChild(node3); + getPhysicsSpace().add(node3); + + } + + private PhysicsSpace getPhysicsSpace() { + return bulletAppState.getPhysicsSpace(); + } +}