How do I create ropes in jBullet for JME? - Newton's Cradle

Hi!

I going to create Newton’s cradle in JME, but I don’t know how to create ropes. Do you have some suggestions on which classes I should use to make this work?

Markering_040

1 Like

Not sure how well or not the balls in there would work with transferring momentum and what not but I’d start here: https://wiki.jmonkeyengine.org/jme3/faq.html#can-objects-swing-like-a-pendulums-chains-ropebridges

Know that ropes are essentially a series of joints so it’s more like a chain than it is a rope. The smaller the link the more rope like it’d be.

But ya. Essentially follow the physics tutorials and you should be able to get to this.

1 Like

Good tutorial!

But I don’t understand why the object PhysicsTestHelper gives me an error.

Markering_042

I can find PhysicsTestHelper in

But not a class or method about it.

What’s the error say though?

This.

Markering_044

Markering_045

You haven’t copied it or you haven’t imported it. It’s right there in the directory with the rest of the test code. If you have the test code in the SDK then you can simply hit the right key to follow it.

It’s also here on GIT:

I did, not did not found. Now I have imported the file into

Markering_046

It’s working now.

Hello again!

Is there any way to connect to a node to two joints?

Let’s say that I got a ball who going to swing in two nodes.
I first create the ball as a dynamic node:

Node Ball1Node = PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),1);

I place the ball on a specific place

Ball1Node.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(x, y, z);

Then I create two static nodes where the ball needs to hang into:

Node LeftWire1StaticNode = PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);
Node RigthWire1StaticNode = PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);

Then I move the static nodes

LeftWire1StaticNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(6f, 14.6214f,-7.56346f));
RigthWire1StaticNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(6f, 14.6214f,7.56346f));

Then I create the joints

HingeJoint LeftWire1Joint = new HingeJoint(LeftWire1StaticNode.getControl(RigidBodyControl.class),
                                                Ball1Node.getControl(RigidBodyControl.class),
                                                LeftWire1StaticNode.getLocalTranslation(),
                                                new Vector3f(x,y,z),
                                                Vector3f.UNIT_Z,
                                                Vector3f.UNIT_Z);
    
    
HingeJoint RightWire1Joint = new HingeJoint(RigthWire1StaticNode.getControl(RigidBodyControl.class),
                                                Ball1Node.getControl(RigidBodyControl.class),
                                                RigthWire1StaticNode.getLocalTranslation(),
                                                new Vector3f(x,y,z),
                                                Vector3f.UNIT_Z,
                                                Vector3f.UNIT_Z);
    
    // Add joint
    bulletAppState.getPhysicsSpace().add(LeftWire1Joint);
    bulletAppState.getPhysicsSpace().add(RightWire1Joint);

But the ball just fall through the floor if I have two joints. If I use one joint, then it works.

Hello!

Where can I send a bug report to JME developers? I found that I cannot attach two or more joints in JME.

If I do that, then the nodes will drop to the floor.

1 Like

https://wiki.jmonkeyengine.org/report_bugs.html

Before you report something as a bug you should get confirmation it is a bug here on the forum.

Hi!

I did open a issue at JME’s github and wrote my problem there.

And also here

Hi!

I paste this code so you can simulate it and see what’s happening. This is a easier code then above.

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.joints.HingeJoint;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 * @author normenhansen
 */
public class Main extends SimpleApplication implements AnalogListener {
    private BulletAppState bulletAppState;
    private HingeJoint joint;
    private HingeJoint joint2;
    

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

    private void setupKeys() {
        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_H));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_K));
        inputManager.addMapping("Swing", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addListener(this, "Left", "Right", "Swing");
    }
    
    @Override
    public void onAnalog(String binding, float value, float tpf) {
        if(binding.equals("Left")){
            joint.enableMotor(true, 1, .1f);
        }
        else if(binding.equals("Right")){
            joint.enableMotor(true, -1, .1f);
        }
        else if(binding.equals("Swing")){
            joint.enableMotor(false, 0, 0);
        }
    }

    @Override
    public void simpleInitApp() {
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.setDebugEnabled(true);
        setupKeys();
        setupJoint();
    }

    private PhysicsSpace getPhysicsSpace(){
        return bulletAppState.getPhysicsSpace();
    }

    public void setupJoint() {
        
        Node holderNode = createPhysicsTestNode(assetManager, "Node1", new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);
        holderNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,0,0f));
        rootNode.attachChild(holderNode);
        getPhysicsSpace().add(holderNode);

        Node hammerNode = createPhysicsTestNode(assetManager, "Node2", new BoxCollisionShape(new Vector3f( .3f, .3f, .3f)),1);
        hammerNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,-1,0f));
        rootNode.attachChild(hammerNode);
        getPhysicsSpace().add(hammerNode);

        joint=new HingeJoint(holderNode.getControl(RigidBodyControl.class), hammerNode.getControl(RigidBodyControl.class), Vector3f.ZERO, new Vector3f(0f,-1,0f), Vector3f.UNIT_Z, Vector3f.UNIT_Z);
        getPhysicsSpace().add(joint);
        
        // New pendelum
        Node holderNode2 = createPhysicsTestNode(assetManager, "Node3", new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0);
        holderNode2.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(5f,0,0f));
        rootNode.attachChild(holderNode2);
        getPhysicsSpace().add(holderNode2);
        
        Node hammerNode2 = createPhysicsTestNode(assetManager, "Node4", new BoxCollisionShape(new Vector3f( .3f, .3f, .3f)),1);
        hammerNode2.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(5f,-1,0f));
        rootNode.attachChild(hammerNode2);
        getPhysicsSpace().add(hammerNode2);
        
        // Joint2 won't work - Why?
        joint2 = new HingeJoint(holderNode2.getControl(RigidBodyControl.class), hammerNode2.getControl(RigidBodyControl.class), Vector3f.ZERO, new Vector3f(0f,-1,0f), Vector3f.UNIT_Z, Vector3f.UNIT_Z);
        getPhysicsSpace().add(joint2);
    }

    @Override
    public void simpleUpdate(float tpf) {

    }
    
    private Node createPhysicsTestNode(AssetManager manager, String nodeName, CollisionShape shape, float mass) {
        Node node = new Node(nodeName); // "PhysicsNode"
        RigidBodyControl control = new RigidBodyControl(shape, mass);
        node.addControl(control);
        return node;
    }

}