Home | History | Annotate | Download | only in bullet
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package jme3test.bullet;
     34 
     35 import com.jme3.app.SimpleApplication;
     36 import com.jme3.asset.TextureKey;
     37 import com.jme3.bullet.BulletAppState;
     38 import com.jme3.bullet.PhysicsSpace;
     39 import com.jme3.bullet.collision.shapes.BoxCollisionShape;
     40 import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
     41 import com.jme3.bullet.collision.shapes.MeshCollisionShape;
     42 import com.jme3.bullet.control.RigidBodyControl;
     43 import com.jme3.bullet.control.VehicleControl;
     44 import com.jme3.bullet.joints.SliderJoint;
     45 import com.jme3.input.KeyInput;
     46 import com.jme3.input.controls.ActionListener;
     47 import com.jme3.input.controls.KeyTrigger;
     48 import com.jme3.material.Material;
     49 import com.jme3.math.*;
     50 import com.jme3.scene.Geometry;
     51 import com.jme3.scene.Node;
     52 import com.jme3.scene.shape.Box;
     53 import com.jme3.scene.shape.Cylinder;
     54 import com.jme3.texture.Texture;
     55 
     56 /**
     57  * Tests attaching/detaching nodes via joints
     58  * @author normenhansen
     59  */
     60 public class TestAttachDriver extends SimpleApplication implements ActionListener {
     61 
     62     private VehicleControl vehicle;
     63     private RigidBodyControl driver;
     64     private RigidBodyControl bridge;
     65     private SliderJoint slider;
     66     private final float accelerationForce = 1000.0f;
     67     private final float brakeForce = 100.0f;
     68     private float steeringValue = 0;
     69     private float accelerationValue = 0;
     70     private Vector3f jumpForce = new Vector3f(0, 3000, 0);
     71     private BulletAppState bulletAppState;
     72 
     73     public static void main(String[] args) {
     74         TestAttachDriver app = new TestAttachDriver();
     75         app.start();
     76     }
     77 
     78     @Override
     79     public void simpleInitApp() {
     80         bulletAppState = new BulletAppState();
     81         stateManager.attach(bulletAppState);
     82         bulletAppState.getPhysicsSpace().enableDebug(assetManager);
     83         setupKeys();
     84         setupFloor();
     85         buildPlayer();
     86     }
     87 
     88     private PhysicsSpace getPhysicsSpace(){
     89         return bulletAppState.getPhysicsSpace();
     90     }
     91 
     92     private void setupKeys() {
     93         inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_H));
     94         inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_K));
     95         inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_U));
     96         inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_J));
     97         inputManager.addMapping("Space", new KeyTrigger(KeyInput.KEY_SPACE));
     98         inputManager.addMapping("Reset", new KeyTrigger(KeyInput.KEY_RETURN));
     99         inputManager.addListener(this, "Lefts");
    100         inputManager.addListener(this, "Rights");
    101         inputManager.addListener(this, "Ups");
    102         inputManager.addListener(this, "Downs");
    103         inputManager.addListener(this, "Space");
    104         inputManager.addListener(this, "Reset");
    105     }
    106 
    107     public void setupFloor() {
    108         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    109         TextureKey key = new TextureKey("Interface/Logo/Monkey.jpg", true);
    110         key.setGenerateMips(true);
    111         Texture tex = assetManager.loadTexture(key);
    112         tex.setMinFilter(Texture.MinFilter.Trilinear);
    113         mat.setTexture("ColorMap", tex);
    114 
    115         Box floor = new Box(Vector3f.ZERO, 100, 1f, 100);
    116         Geometry floorGeom = new Geometry("Floor", floor);
    117         floorGeom.setMaterial(mat);
    118         floorGeom.setLocalTranslation(new Vector3f(0f, -3, 0f));
    119 
    120         floorGeom.addControl(new RigidBodyControl(new MeshCollisionShape(floorGeom.getMesh()), 0));
    121         rootNode.attachChild(floorGeom);
    122         getPhysicsSpace().add(floorGeom);
    123     }
    124 
    125     private void buildPlayer() {
    126         Material mat = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
    127         mat.getAdditionalRenderState().setWireframe(true);
    128         mat.setColor("Color", ColorRGBA.Red);
    129 
    130         //create a compound shape and attach the BoxCollisionShape for the car body at 0,1,0
    131         //this shifts the effective center of mass of the BoxCollisionShape to 0,-1,0
    132         CompoundCollisionShape compoundShape = new CompoundCollisionShape();
    133         BoxCollisionShape box = new BoxCollisionShape(new Vector3f(1.2f, 0.5f, 2.4f));
    134         compoundShape.addChildShape(box, new Vector3f(0, 1, 0));
    135 
    136         //create vehicle node
    137         Node vehicleNode=new Node("vehicleNode");
    138         vehicle = new VehicleControl(compoundShape, 800);
    139         vehicleNode.addControl(vehicle);
    140 
    141         //setting suspension values for wheels, this can be a bit tricky
    142         //see also https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&hl=en
    143         float stiffness = 60.0f;//200=f1 car
    144         float compValue = .3f; //(should be lower than damp)
    145         float dampValue = .4f;
    146         vehicle.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
    147         vehicle.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
    148         vehicle.setSuspensionStiffness(stiffness);
    149         vehicle.setMaxSuspensionForce(10000.0f);
    150 
    151         //Create four wheels and add them at their locations
    152         Vector3f wheelDirection = new Vector3f(0, -1, 0); // was 0, -1, 0
    153         Vector3f wheelAxle = new Vector3f(-1, 0, 0); // was -1, 0, 0
    154         float radius = 0.5f;
    155         float restLength = 0.3f;
    156         float yOff = 0.5f;
    157         float xOff = 1f;
    158         float zOff = 2f;
    159 
    160         Cylinder wheelMesh = new Cylinder(16, 16, radius, radius * 0.6f, true);
    161 
    162         Node node1 = new Node("wheel 1 node");
    163         Geometry wheels1 = new Geometry("wheel 1", wheelMesh);
    164         node1.attachChild(wheels1);
    165         wheels1.rotate(0, FastMath.HALF_PI, 0);
    166         wheels1.setMaterial(mat);
    167         vehicle.addWheel(node1, new Vector3f(-xOff, yOff, zOff),
    168                 wheelDirection, wheelAxle, restLength, radius, true);
    169 
    170         Node node2 = new Node("wheel 2 node");
    171         Geometry wheels2 = new Geometry("wheel 2", wheelMesh);
    172         node2.attachChild(wheels2);
    173         wheels2.rotate(0, FastMath.HALF_PI, 0);
    174         wheels2.setMaterial(mat);
    175         vehicle.addWheel(node2, new Vector3f(xOff, yOff, zOff),
    176                 wheelDirection, wheelAxle, restLength, radius, true);
    177 
    178         Node node3 = new Node("wheel 3 node");
    179         Geometry wheels3 = new Geometry("wheel 3", wheelMesh);
    180         node3.attachChild(wheels3);
    181         wheels3.rotate(0, FastMath.HALF_PI, 0);
    182         wheels3.setMaterial(mat);
    183         vehicle.addWheel(node3, new Vector3f(-xOff, yOff, -zOff),
    184                 wheelDirection, wheelAxle, restLength, radius, false);
    185 
    186         Node node4 = new Node("wheel 4 node");
    187         Geometry wheels4 = new Geometry("wheel 4", wheelMesh);
    188         node4.attachChild(wheels4);
    189         wheels4.rotate(0, FastMath.HALF_PI, 0);
    190         wheels4.setMaterial(mat);
    191         vehicle.addWheel(node4, new Vector3f(xOff, yOff, -zOff),
    192                 wheelDirection, wheelAxle, restLength, radius, false);
    193 
    194         vehicleNode.attachChild(node1);
    195         vehicleNode.attachChild(node2);
    196         vehicleNode.attachChild(node3);
    197         vehicleNode.attachChild(node4);
    198 
    199         rootNode.attachChild(vehicleNode);
    200         getPhysicsSpace().add(vehicle);
    201 
    202         //driver
    203         Node driverNode=new Node("driverNode");
    204         driverNode.setLocalTranslation(0,2,0);
    205         driver=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,.5f,0.2f)));
    206         driverNode.addControl(driver);
    207 
    208         rootNode.attachChild(driverNode);
    209         getPhysicsSpace().add(driver);
    210 
    211         //joint
    212         slider=new SliderJoint(driver, vehicle, Vector3f.UNIT_Y.negate(), Vector3f.UNIT_Y, true);
    213         slider.setUpperLinLimit(.1f);
    214         slider.setLowerLinLimit(-.1f);
    215 
    216         getPhysicsSpace().add(slider);
    217 
    218         Node pole1Node=new Node("pole1Node");
    219         Node pole2Node=new Node("pole1Node");
    220         Node bridgeNode=new Node("pole1Node");
    221         pole1Node.setLocalTranslation(new Vector3f(-2,-1,4));
    222         pole2Node.setLocalTranslation(new Vector3f(2,-1,4));
    223         bridgeNode.setLocalTranslation(new Vector3f(0,1.4f,4));
    224 
    225         RigidBodyControl pole1=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,1.25f,0.2f)),0);
    226         pole1Node.addControl(pole1);
    227         RigidBodyControl pole2=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,1.25f,0.2f)),0);
    228         pole2Node.addControl(pole2);
    229         bridge=new RigidBodyControl(new BoxCollisionShape(new Vector3f(2.5f,0.2f,0.2f)));
    230         bridgeNode.addControl(bridge);
    231 
    232         rootNode.attachChild(pole1Node);
    233         rootNode.attachChild(pole2Node);
    234         rootNode.attachChild(bridgeNode);
    235         getPhysicsSpace().add(pole1);
    236         getPhysicsSpace().add(pole2);
    237         getPhysicsSpace().add(bridge);
    238 
    239     }
    240 
    241     @Override
    242     public void simpleUpdate(float tpf) {
    243         Quaternion quat=new Quaternion();
    244         cam.lookAt(vehicle.getPhysicsLocation(), Vector3f.UNIT_Y);
    245     }
    246 
    247     public void onAction(String binding, boolean value, float tpf) {
    248         if (binding.equals("Lefts")) {
    249             if (value) {
    250                 steeringValue += .5f;
    251             } else {
    252                 steeringValue += -.5f;
    253             }
    254             vehicle.steer(steeringValue);
    255         } else if (binding.equals("Rights")) {
    256             if (value) {
    257                 steeringValue += -.5f;
    258             } else {
    259                 steeringValue += .5f;
    260             }
    261             vehicle.steer(steeringValue);
    262         } else if (binding.equals("Ups")) {
    263             if (value) {
    264                 accelerationValue += accelerationForce;
    265             } else {
    266                 accelerationValue -= accelerationForce;
    267             }
    268             vehicle.accelerate(accelerationValue);
    269         } else if (binding.equals("Downs")) {
    270             if (value) {
    271                 vehicle.brake(brakeForce);
    272             } else {
    273                 vehicle.brake(0f);
    274             }
    275         } else if (binding.equals("Space")) {
    276             if (value) {
    277                 getPhysicsSpace().remove(slider);
    278                 slider.destroy();
    279                 vehicle.applyImpulse(jumpForce, Vector3f.ZERO);
    280             }
    281         } else if (binding.equals("Reset")) {
    282             if (value) {
    283                 System.out.println("Reset");
    284                 vehicle.setPhysicsLocation(new Vector3f(0, 0, 0));
    285                 vehicle.setPhysicsRotation(new Matrix3f());
    286                 vehicle.setLinearVelocity(Vector3f.ZERO);
    287                 vehicle.setAngularVelocity(Vector3f.ZERO);
    288                 vehicle.resetSuspension();
    289                 bridge.setPhysicsLocation(new Vector3f(0,1.4f,4));
    290                 bridge.setPhysicsRotation(Quaternion.DIRECTION_Z.toRotationMatrix());
    291             }
    292         }
    293     }
    294 }
    295