Collision with a complex model

I’m just looking for a general pointer on what to do: I’ve got a complex model (a spacestation) which has lots of gaps where a spaceship could fly through. If I just add a boundingbox, then a collision occurs as soon as a spaceship enters the station’s area. What’s the solution here so that a spaceship can fly through the gaps without registering a collision? Do I need to manually create lots of smaller bounding areas for each section of the station?

Thanks in advance.

Could you post a photo of the model?

Just use a RigidBodyControl.

Please read the tutorial:
http://davidb.github.io/sandbox_wiki_jme/jme3/advanced/physics.html

Quote:

A mesh-accurate shape for static or kinematic Spatials. Can have complex shapes with openings and appendages.

Limitations: Collisions between two mesh-accurate
shapes cannot be detected, only non-mesh shapes can collide with this
shape. This Shape does not work with dynamic Spatials.

Quote:

A mesh-accurate shape for dynamic Spatials. It uses http://gimpact.sourceforge.net/.

Limitations: CPU intensive, use sparingly! We recommend
using HullCollisionShape (or CompoundShape) instead to improve
performance. Collisions between two mesh-accurate shapes cannot be
detected, only non-mesh shapes can collide with this shape.

As you can see, there are some complications. Maybe someone else knows the complete answer.

You may also look this:

This is the model:

Thanks for the replies, you’ve given me a lot of stuff to research. It’s a shame the wiki is still down.

1 Like

The wiki is down, but there is a backup (future version?) online

Home: http://davidb.github.io/sandbox_wiki_jme/jme3.html


Nice model btw

Use a compoundCollisionShape for your ship or , if your use case permits it, a simple sphereShape, boxShape, etc.
Then, it will collide fine with a complex shape (space station).

You really only have 2 limitations:

  • complex shapes can’t collide together (nb: a compoundCollisionShape is not a “complex shape”)
  • performances should keep you away from GImpactCollisionShape for the station. In your case, I’d use a MeshCollisionShape for your station… you will be astonished by how performant and easy to use bullet is with jme. I’m still in awe lol.

I know the wiki says this, but it’s not true… gimpact vs meshshape works and i’m pretty sure that also gimpact vs gimpact works. The weird behaviour of the gimpact shapes was due a bug in the bullet native bindings that has been fixed in the master, so if you want to use them atm you should recompile the bullet bindings with the source available on github or use jbullet.

If you need a movable rigidbody for the station i suggest (as ali already did) to use vhacd.

1 Like

Hi again, I’ve spent the best part of a month trying to get “complex” collisions to work and I’m still no closer. I’ve written the following bare-bones test code which creates two boxes which are overlapping and AFAIK does everything correctly, but no collisions are registered. Could someone tell me what I’m doing wrong?

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.bounding.BoundingBox;
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.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

public class JMECollisionTest extends SimpleApplication implements PhysicsCollisionListener {

    private Geometry ship1, ship2;
    private BulletAppState bulletAppState;
    private RigidBodyControl rbc1, rbc2;
    private CollisionShape sceneShape1, sceneShape2;

    public static void main(String[] args){
        JMECollisionTest app = new JMECollisionTest();
        app.showSettings = false;
        app.start();
    }


    @Override
    public void simpleInitApp() {
        assetManager.registerLocator("assets/", FileLocator.class); // default
        
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Red);

        Box b1 = new Box(1f, 1f, 1f);
        ship1 = new Geometry();
        ship1.setMaterial(mat);
        ship1.setMesh(b1);
        ship1.setModelBound(new BoundingBox());
        ship1.updateModelBound();
        ship1.setLocalTranslation(0, 0, 0);
        ship1.updateGeometricState();
        ship1.updateModelBound();
        rootNode.attachChild(ship1);

        Box b2 = new Box(1f, 1f, 1f);
        ship2 = new Geometry();
        ship2.setMaterial(mat);
        ship2.setMesh(b2);
        ship2.setModelBound(new BoundingBox());
        ship2.updateModelBound();
        ship2.setLocalTranslation(.5f, .5f, .5f);
        rootNode.attachChild(ship2);

        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.setDebugEnabled(true);
        bulletAppState.setEnabled(true);
        bulletAppState.getPhysicsSpace().addCollisionListener(this);
        
        sceneShape1 = CollisionShapeFactory.createMeshShape(ship1);
        rbc1 = new RigidBodyControl(sceneShape1, 0);
        rbc1.setSpatial(ship1);
        rbc1.setKinematic(true);
        ship1.addControl(rbc1);
        bulletAppState.getPhysicsSpace().add(rbc1);
        
        sceneShape2 = CollisionShapeFactory.createMeshShape(ship2);
        rbc2 = new RigidBodyControl(sceneShape2, 0);
        rbc2.setSpatial(ship2);
        rbc2.setKinematic(true);
        ship2.addControl(rbc2);
        bulletAppState.getPhysicsSpace().add(rbc2);
        
        inputManager.setCursorVisible(true);

    }

    @Override
    public void simpleUpdate(float tpf) {
        bulletAppState.update(tpf);
        rbc1.update(tpf);
        rbc2.update(tpf);
        bulletAppState.getPhysicsSpace().distributeEvents();
    }

    @Override
    public void collision(PhysicsCollisionEvent arg0) {
        System.out.println(arg0);
    }


}
@Override
    public void simpleUpdate(float tpf) {
        bulletAppState.update(tpf);
        rbc1.update(tpf);
        rbc2.update(tpf);
        bulletAppState.getPhysicsSpace().distributeEvents();
    }

Why this?

I’ve got to the stage where I’m trying everything. I had a look at the JME source and saw these methods so I thought I’d try them. I couldn’t find any code anywhere on the net that showed how to do complex collisions but without using all the physics and character controls etc… I want to keep direct control of all the spatials, but somehow know when they have collided.

I don’t think you can do it in this way.
Just use bullet normally and set the transformations with rigidbody.setPhysics* methods

Are you planning a case where two spacestations can collide into each other? If not, then a static collider is the way to go. They provide dead accurate collisions with super good performance.

You can move them around normally without any problems like everything else, they just can’t collide with other static which shouldn’t be a problem if you keep different spacestations away from each other.

It works pretty damn well for me:

I once asked why this works so well even when you move the static colliders (which shouldn’t be possible), but apparently nobody has a clue.

The only important part of code:

yourPhysicsControl.setCollisionShape(CollisionShapeFactory.createMeshShape(yourStationNode));

Then I suppose you can use dynamic mesh colliders for ships or compound shapes if you need more performance.

Thanks again for everybody’s response. I think I’ve found the solution thanks to your help!

In my earlier code, it turns out that you need to give it a mass of 1.0, even though I’m not using any actual physics. However, I’m now using a CollisionShapeFactory.createMeshShape() and a createDynamicMeshShape for each of my objects, and attaching them to a GhostControl. Now I get full control of the Spatials, and when there’s a collision, my PhysicsCollisionListener gets fired. (BTW, I get NPE’s if both my objects are using createMeshShape()).

My only (minor) issue now is the fact that the collisions are fired outside the main game loop, but that just means a bit of code refactoring. Cheers!

Great!

Well yes, static/static collisions don’t work. Doing that in physics will crash it. Only dynamic/static and dynamic/dynamic work.