1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package jme3test.bullet;
6
7import com.jme3.app.SimpleApplication;
8import com.jme3.bullet.BulletAppState;
9import com.jme3.bullet.PhysicsSpace;
10import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
11import com.jme3.bullet.control.RigidBodyControl;
12import com.jme3.bullet.joints.ConeJoint;
13import com.jme3.bullet.joints.PhysicsJoint;
14import com.jme3.input.controls.ActionListener;
15import com.jme3.input.controls.MouseButtonTrigger;
16import com.jme3.math.Vector3f;
17import com.jme3.scene.Node;
18
19/**
20 *
21 * @author normenhansen
22 */
23public class TestRagDoll extends SimpleApplication implements ActionListener {
24
25    private BulletAppState bulletAppState = new BulletAppState();
26    private Node ragDoll = new Node();
27    private Node shoulders;
28    private Vector3f upforce = new Vector3f(0, 200, 0);
29    private boolean applyForce = false;
30
31    public static void main(String[] args) {
32        TestRagDoll app = new TestRagDoll();
33        app.start();
34    }
35
36    @Override
37    public void simpleInitApp() {
38        bulletAppState = new BulletAppState();
39        stateManager.attach(bulletAppState);
40        bulletAppState.getPhysicsSpace().enableDebug(assetManager);
41        inputManager.addMapping("Pull ragdoll up", new MouseButtonTrigger(0));
42        inputManager.addListener(this, "Pull ragdoll up");
43        PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
44        createRagDoll();
45    }
46
47    private void createRagDoll() {
48        shoulders = createLimb(0.2f, 1.0f, new Vector3f(0.00f, 1.5f, 0), true);
49        Node uArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f, 0.8f, 0), false);
50        Node uArmR = createLimb(0.2f, 0.5f, new Vector3f(0.75f, 0.8f, 0), false);
51        Node lArmL = createLimb(0.2f, 0.5f, new Vector3f(-0.75f, -0.2f, 0), false);
52        Node lArmR = createLimb(0.2f, 0.5f, new Vector3f(0.75f, -0.2f, 0), false);
53        Node body = createLimb(0.2f, 1.0f, new Vector3f(0.00f, 0.5f, 0), false);
54        Node hips = createLimb(0.2f, 0.5f, new Vector3f(0.00f, -0.5f, 0), true);
55        Node uLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f, -1.2f, 0), false);
56        Node uLegR = createLimb(0.2f, 0.5f, new Vector3f(0.25f, -1.2f, 0), false);
57        Node lLegL = createLimb(0.2f, 0.5f, new Vector3f(-0.25f, -2.2f, 0), false);
58        Node lLegR = createLimb(0.2f, 0.5f, new Vector3f(0.25f, -2.2f, 0), false);
59
60        join(body, shoulders, new Vector3f(0f, 1.4f, 0));
61        join(body, hips, new Vector3f(0f, -0.5f, 0));
62
63        join(uArmL, shoulders, new Vector3f(-0.75f, 1.4f, 0));
64        join(uArmR, shoulders, new Vector3f(0.75f, 1.4f, 0));
65        join(uArmL, lArmL, new Vector3f(-0.75f, .4f, 0));
66        join(uArmR, lArmR, new Vector3f(0.75f, .4f, 0));
67
68        join(uLegL, hips, new Vector3f(-.25f, -0.5f, 0));
69        join(uLegR, hips, new Vector3f(.25f, -0.5f, 0));
70        join(uLegL, lLegL, new Vector3f(-.25f, -1.7f, 0));
71        join(uLegR, lLegR, new Vector3f(.25f, -1.7f, 0));
72
73        ragDoll.attachChild(shoulders);
74        ragDoll.attachChild(body);
75        ragDoll.attachChild(hips);
76        ragDoll.attachChild(uArmL);
77        ragDoll.attachChild(uArmR);
78        ragDoll.attachChild(lArmL);
79        ragDoll.attachChild(lArmR);
80        ragDoll.attachChild(uLegL);
81        ragDoll.attachChild(uLegR);
82        ragDoll.attachChild(lLegL);
83        ragDoll.attachChild(lLegR);
84
85        rootNode.attachChild(ragDoll);
86        bulletAppState.getPhysicsSpace().addAll(ragDoll);
87    }
88
89    private Node createLimb(float width, float height, Vector3f location, boolean rotate) {
90        int axis = rotate ? PhysicsSpace.AXIS_X : PhysicsSpace.AXIS_Y;
91        CapsuleCollisionShape shape = new CapsuleCollisionShape(width, height, axis);
92        Node node = new Node("Limb");
93        RigidBodyControl rigidBodyControl = new RigidBodyControl(shape, 1);
94        node.setLocalTranslation(location);
95        node.addControl(rigidBodyControl);
96        return node;
97    }
98
99    private PhysicsJoint join(Node A, Node B, Vector3f connectionPoint) {
100        Vector3f pivotA = A.worldToLocal(connectionPoint, new Vector3f());
101        Vector3f pivotB = B.worldToLocal(connectionPoint, new Vector3f());
102        ConeJoint joint = new ConeJoint(A.getControl(RigidBodyControl.class), B.getControl(RigidBodyControl.class), pivotA, pivotB);
103        joint.setLimit(1f, 1f, 0);
104        return joint;
105    }
106
107    public void onAction(String string, boolean bln, float tpf) {
108        if ("Pull ragdoll up".equals(string)) {
109            if (bln) {
110                shoulders.getControl(RigidBodyControl.class).activate();
111                applyForce = true;
112            } else {
113                applyForce = false;
114            }
115        }
116    }
117
118    @Override
119    public void simpleUpdate(float tpf) {
120        if (applyForce) {
121            shoulders.getControl(RigidBodyControl.class).applyForce(upforce, Vector3f.ZERO);
122        }
123    }
124}
125