jMonkeyEngine / jMonkeyEngine/jmonkeyengine
missing collisions for some rotations of a GImpact shape
Open
Nobody has claimed this yet.
Needs investigation
Physics
- Dominant language
- Java
- Stars
- 4.3k
- Forks
- 1.2k
- Avg merge
- 4d 7h
- Merged PRs (30d)
- 14
Description
This issue affects both jme3-bullet and jme3-jbullet. It was reported at the Forum: https://hub.jmonkeyengine.org/t/possible-bug-in-physics/41977
Here is the test code:
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.control.RigidBodyControl;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.shape.Box;
import static java.lang.Math.PI;
public class Bug2 extends SimpleApplication implements PhysicsCollisionListener {
private int ticks = 0;
private int lastCollisionTick = 0;
private Mesh boxMesh;
private Material mat;
private BulletAppState bulletAppState;
private Node box2;
public static void main(String[] args) {
Bug2 bug = new Bug2();
bug.showSettings = false;
bug.start();
}
@Override
public void simpleInitApp() {
bulletAppState = new BulletAppState();
this.stateManager.attach(bulletAppState);
bulletAppState.getPhysicsSpace().addCollisionListener(this);
viewPort.setBackgroundColor(ColorRGBA.Gray);
viewPort.getCamera().setLocation(new Vector3f(0,0,-10000));
viewPort.getCamera().lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
viewPort.getCamera().setFrustumFar(20000);
/*
Here the original code builds the cube from coordinates.
The issue does not happen with JMonkey's Box at least for these particular values.
*/
boxMesh = new Mesh();
Box q = new Box(2000,2000,2000);
for(VertexBuffer origin : q.getBufferList()) {
boxMesh.setBuffer(origin.getBufferType(), origin.getNumComponents(), origin.getFormat(), origin.getData());
}
boxMesh.updateBound();
mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
mat.setColor("Diffuse", ColorRGBA.Blue);
final DirectionalLight light = new DirectionalLight();
light.setDirection(new Vector3f(0.5f, -0.7f, 1.0f));
rootNode.addLight(light);
createBoxGivenRotation(new Quaternion());
box2 = createBoxGivenRotation(randomQuaternion());
}
private Node createBoxGivenRotation(Quaternion q) {
Geometry spatial = new Geometry("Box", boxMesh);
RigidBodyControl control = new RigidBodyControl(1.0f);
spatial.setMaterial(mat);
spatial.addControl(control);
control.setKinematic(true);
Node node = new Node();
node.attachChild(spatial);
rootNode.attachChild(node);
bulletAppState.getPhysicsSpace().add(control);
node.setLocalRotation(q);
node.setLocalTranslation(Vector3f.ZERO);
return node;
}
private static Quaternion randomQuaternion() {
return new Quaternion().fromAngles(randomAngle(), randomAngle(), randomAngle());
}
private static float randomAngle() {
return (float)(Math.random() * 2 * PI);
}
@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);
/* If no collision is detected we abort (collisions are detected in 1 tick, 200 is an overkill) */
if(ticks - lastCollisionTick > 200){
System.out.println("Bug in physics! You can replace the random quaternion for the one printed on the previous line.");
System.exit(0);
}
ticks++;
}
/* If a collision is detected, remove the second cube and try again with another random rotation. */
@Override
public void collision(PhysicsCollisionEvent event) {
Quaternion q = randomQuaternion();
int ticksSinceLastCollision = ticks - lastCollisionTick;
System.out.println("Collision event in " + ticksSinceLastCollision + " ticks : retry with rotation quat " + q);
lastCollisionTick = ticks;
destroyBox(box2);
box2 = createBoxGivenRotation(q);
}
private void destroyBox(Node box) {
Spatial spatial = box.getChildren().get(0);
RigidBodyControl control = (RigidBodyControl) spatial.getControl(0);
control.getPhysicsSpace().removeCollisionObject(control);
box.getChildren().get(0).removeFromParent();
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the Bug2 reproduction entry point from the issue and compare collision behavior for the two implementations named: jme3-bullet and jme3-jbullet. Trace the RigidBodyControl and PhysicsCollisionListener paths for GImpact shapes under varying rotations. Done means collisions are consistently detected for the reproduced rotations in both implementations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100