The jMonkeyEngine3 has built-in support for jBullet physics via the com.jme3.bullet
package.
Game Physics are not only employed to calculate collisions, but they can also simulate hinges and joints. Think of pulley chains, shaky rope bridges, swinging pendulums, or (trap)door and chest hinges. Physics are a great addition to e.g. an action or puzzle game.
In this example, we will create a pendulum. The joint is the (invisible) connection between the pendulum body and the hook. You will see that you can use what you learn from the simple pendulum and apply it to other joint/hinge objects (rope bridges, etc).
hookNode
and a dynamic pendulumNode
.joint.enableMotor();
The hookNode is the fixed point from which the pendulum hangs. It has no mass.
Node hookNode=PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .1f, .1f, .1f)),0); hookNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,0,0f)); rootNode.attachChild(hookNode); getPhysicsSpace().add(hookNode);
For a rope bridge, there would be two fixed nodes where the bridge is attached to the mountainside.
The pendulumNode is the dynamic part of the construction. It has a mass.
Node pendulumNode=PhysicsTestHelper.createPhysicsTestNode(assetManager, new BoxCollisionShape(new Vector3f( .3f, .3f, .3f)),1); pendulumNode.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f,-1,0f)); rootNode.attachChild(pendulumNode); getPhysicsSpace().add(pendulumNode);
For a rope bridge, each set of planks would be one dynamic node.
A PhysicsHingeJoint is an invisible connection between two nodes – here between the pendulum body and the hook. Why are hinges and joints represented by the same class? Hinges and joints have something in common: They constrain the mechanical degree of freedom (DOF) of another object.
Consider a free falling, "unchained" object in physical 3D space: It has 6 DOFs:
Now consider some examples of objects with joints:
You'll understand that, when creating any type of joint, it is important to correctly specify the DOFs that the joint restricts, and the DOFs that the joint allows. For the typical DOF of a ragDoll character's limbs, jME even offers a special joint, PhysicsConeJoint
.
You create the PhysicsHingeJoint after you have created the nodes that are to be chained together. In the code snippet you see that the PhysicsHingeJoint constructor requires the two node objects. You also have to specify axes and pivots – they are the degrees of freedom that you just heard about.
private HingeJoint joint; ... public void simpleInitApp() { ... // hookNode and pendulumNode are created here... ... joint=new HingeJoint(hookNode.getControl(RigidBodyControl.class), // A pendulumNode.getControl(RigidBodyControl.class), // B new Vector3f(0f, 0f, 0f), // pivot point of A new Vector3f(0f,-1f, 0f), // pivot point of B Vector3f.UNIT_Z, // DoF Axis of A (Z axis) Vector3f.UNIT_Z ); // DoF Axis of B (Z axis)
Specify the following parameters for each joint:
Remember to add all joint objects to the physicsSpace, just like you would do with any physical objects.
bulletAppState.getPhysicsSpace().add(joint);
Tip: If you want the joint to be visible, attach a geometry to the dynamic node, and translate it to its start position.
You can apply forces to dynamic nodes (the ones that have a mass), and see how other joined ("chained") objects are dragged along.
Alternatively, you can also apply forces to the joint itself. In a game, you may want to spin an automatic revolving door, or slam a door closed in a spooky way, or dramatically open the lid of a treasure chest.
The method to call on the joint is enableMotor()
.
joint.enableMotor(true, 1, .1f); joint.enableMotor(true, -1, .1f);
true
When you disable the motor, the chained nodes are exposed to gravity again:
joint.enableMotor(false, 0, 0);