Simple way to create a physic prism (RigidBodyControl)

Hello community!

I’m trying to port my game in JME3 and right now I create a wrapper for a creation of a simple RigidBodyControl.

I need to implement three methods to have the ability to create RigidBodyControl for all the simple geometric primitives, which can be met in my game:

private RigidBodyControl createCapsuleBody(float diameter, float height) {
    CollisionShape collisionShape = new CapsuleCollisionShape(diameter, height, AXIS_FOR_HEIGHT_IN_CAPSULE);
    RigidBodyControl rigidBodyControl = new RigidBodyControl(collisionShape);
    return rigidBodyControl;
}

private RigidBodyControl createRectPrismBody(int width, int height, float deep) {
    CollisionShape collisionShape = new BoxCollisionShape(width, height, deep);
    RigidBodyControl rigidBodyControl = new RigidBodyControl(collisionShape);
    return rigidBodyControl;
}

private RigidBodyControl createTrianglePrismBody(float width, float deep) {
    CollisionShape collisionShape;  //What should I do here to init the rigidBodyControl in the next line?
    RigidBodyControl rigidBodyControl = null;   
    return rigidBodyControl;
}

I didn’t find any suitable class to create a prism body I need. The physic body form I need is shown on the image.

I have only two variable dimensions - width=length and deep. I think only one way to create this form - load a mesh, created in an external editor, scale it, and create the RigidBodyControl using this Spatial, but after that - unbind the RigidBodyControl from the mesh (to use the Spatial for the creation of another triangle prisms). This method corrupts my code architecture, but if it is the only one way for me - OK, but how to implement this correct to avoid unused linking of the mesh and RigidBodyControl?

What can you advise me? Are there classes to create this prism so simple as a BoxCollisionShape?

Hey!

The simplest way to go is use MeshCollisionShape and use a jme3utilities.mesh.Prism class. But first you need to understand some basics: JMonkeyEngine uses Bullet physics engine. In order for the JME engine to interact with Bullet, there needs to be a ‘binding’ for the Bullet library. There are two binding currently:

  • One built-in with the engine that comes by default and you are probably using this one. It’s called jme3-bullet.
  • One written by @stephengold called Minie. Minie comes with a Prism Mesh shape. Minie is an improved binding and compatible with the default engine binding meaning that you don’t need to rewrite anything, you just need to update a dependency.

Minie has a built-in prism class. You need to change your dependencies to use Minie instead of jme3-bullet. For example I use maven so for me it’s this:

        <dependency>
            <groupId>com.github.stephengold</groupId>
            <artifactId>Minie</artifactId>
            <version>9.0.1</version>
        </dependency>

If you managed to change the dependency then try this simple app I wrote for you:

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;
import jme3utilities.mesh.Prism;

public class PrismApp extends SimpleApplication {

    public static void main(String[] args) {
        AppSettings appSettings = new AppSettings(true);
        appSettings.setTitle("Prism App");
        appSettings.setResolution(1366, 768);
        appSettings.setResizable(true);

        PrismApp app = new PrismApp();
        app.setSettings(appSettings);
        app.start();
    }

    @Override
    public void simpleInitApp() {
        cam.setLocation(new Vector3f(-1.9533403f, 7.765786f, 8.14174f));
        cam.setRotation(new Quaternion(0.04891587f, 0.925089f, -0.35426357f, 0.12772992f));

        getFlyByCamera().setMoveSpeed(8f * getFlyByCamera().getMoveSpeed());

        // Relevant part for you
        CollisionShape collisionShape = new MeshCollisionShape(new Prism(3, 1f, 4f, true));
        RigidBodyControl rigidBodyControl = new RigidBodyControl(collisionShape, 0f);
        Spatial spatial = new Node("prism");
        spatial.addControl(rigidBodyControl);
        rootNode.attachChild(spatial);

        BulletAppState bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);

        bulletAppState.getPhysicsSpace().addAll(spatial);
        bulletAppState.setDebugEnabled(true);
    }
}

Result:

Some last words regarding rigidbodies: If you have 10 prisms in your game, you will have 10 spatials with 10 RigidBodyControl attached to them. Don’t unbind the RigidBodyControl to create other Prisms.

@kruze

The prism, that you have created, is not the same as I need. I need a prism which has a right triangle as the cross section. You have created a equilateral triangle as the cross section.

Oh you are right, I missed that part. In that case you have to implement one Prism class yourself. Without changing any dependencies or anything: Create a Prism class by extending the com.jme3.scene.Mesh class and assemble the vertices and indices yourself. You need to fill a Position and Indices vertex buffers with appropriate floats. You can calculate the sizes by passing in floats in the Prism class constructor for width, height and depth. You can see examples how the com.jme3.scene.shape.Box class does it for a Box and then implement your own version for the Prism. Then use this Prism mesh with a MeshCollisionShape and you’re done.

@kruze
I have found an another constructor in the jme3utilities.mesh.Prism-class, which creates a right prism - this is what I need! Thanks for help!

1 Like

Nice! Happy to help! :monkey_face: