You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
12 KiB
298 lines
12 KiB
/*
|
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
package jme3test.bullet;
|
|
|
|
import com.jme3.bullet.BulletAppState;
|
|
import com.jme3.app.SimpleApplication;
|
|
import com.jme3.asset.TextureKey;
|
|
import com.jme3.bullet.PhysicsSpace;
|
|
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
|
|
import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
|
|
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
|
|
import com.jme3.bullet.control.RigidBodyControl;
|
|
import com.jme3.bullet.control.VehicleControl;
|
|
import com.jme3.bullet.joints.SliderJoint;
|
|
import com.jme3.input.KeyInput;
|
|
import com.jme3.input.controls.ActionListener;
|
|
import com.jme3.input.controls.KeyTrigger;
|
|
import com.jme3.material.Material;
|
|
import com.jme3.math.ColorRGBA;
|
|
import com.jme3.math.FastMath;
|
|
import com.jme3.math.Matrix3f;
|
|
import com.jme3.math.Quaternion;
|
|
import com.jme3.math.Vector3f;
|
|
import com.jme3.scene.Geometry;
|
|
import com.jme3.scene.Node;
|
|
import com.jme3.scene.shape.Box;
|
|
import com.jme3.scene.shape.Cylinder;
|
|
import com.jme3.texture.Texture;
|
|
|
|
/**
|
|
* Tests attaching/detaching nodes via joints
|
|
* @author normenhansen
|
|
*/
|
|
public class TestAttachDriver extends SimpleApplication implements ActionListener {
|
|
|
|
private VehicleControl vehicle;
|
|
private RigidBodyControl driver;
|
|
private RigidBodyControl bridge;
|
|
private SliderJoint slider;
|
|
private final float accelerationForce = 1000.0f;
|
|
private final float brakeForce = 100.0f;
|
|
private float steeringValue = 0;
|
|
private float accelerationValue = 0;
|
|
private Vector3f jumpForce = new Vector3f(0, 3000, 0);
|
|
private BulletAppState bulletAppState;
|
|
|
|
public static void main(String[] args) {
|
|
TestAttachDriver app = new TestAttachDriver();
|
|
app.start();
|
|
}
|
|
|
|
@Override
|
|
public void simpleInitApp() {
|
|
bulletAppState = new BulletAppState();
|
|
stateManager.attach(bulletAppState);
|
|
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
|
|
setupKeys();
|
|
setupFloor();
|
|
buildPlayer();
|
|
}
|
|
|
|
private PhysicsSpace getPhysicsSpace(){
|
|
return bulletAppState.getPhysicsSpace();
|
|
}
|
|
|
|
private void setupKeys() {
|
|
inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_H));
|
|
inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_K));
|
|
inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_U));
|
|
inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_J));
|
|
inputManager.addMapping("Space", new KeyTrigger(KeyInput.KEY_SPACE));
|
|
inputManager.addMapping("Reset", new KeyTrigger(KeyInput.KEY_RETURN));
|
|
inputManager.addListener(this, "Lefts");
|
|
inputManager.addListener(this, "Rights");
|
|
inputManager.addListener(this, "Ups");
|
|
inputManager.addListener(this, "Downs");
|
|
inputManager.addListener(this, "Space");
|
|
inputManager.addListener(this, "Reset");
|
|
}
|
|
|
|
public void setupFloor() {
|
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
TextureKey key = new TextureKey("Interface/Logo/Monkey.jpg", true);
|
|
key.setGenerateMips(true);
|
|
Texture tex = assetManager.loadTexture(key);
|
|
tex.setMinFilter(Texture.MinFilter.Trilinear);
|
|
mat.setTexture("ColorMap", tex);
|
|
|
|
Box floor = new Box(Vector3f.ZERO, 100, 1f, 100);
|
|
Geometry floorGeom = new Geometry("Floor", floor);
|
|
floorGeom.setMaterial(mat);
|
|
floorGeom.setLocalTranslation(new Vector3f(0f, -3, 0f));
|
|
|
|
floorGeom.addControl(new RigidBodyControl(new MeshCollisionShape(floorGeom.getMesh()), 0));
|
|
rootNode.attachChild(floorGeom);
|
|
getPhysicsSpace().add(floorGeom);
|
|
}
|
|
|
|
private void buildPlayer() {
|
|
Material mat = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
|
|
mat.getAdditionalRenderState().setWireframe(true);
|
|
mat.setColor("Color", ColorRGBA.Red);
|
|
|
|
//create a compound shape and attach the BoxCollisionShape for the car body at 0,1,0
|
|
//this shifts the effective center of mass of the BoxCollisionShape to 0,-1,0
|
|
CompoundCollisionShape compoundShape = new CompoundCollisionShape();
|
|
BoxCollisionShape box = new BoxCollisionShape(new Vector3f(1.2f, 0.5f, 2.4f));
|
|
compoundShape.addChildShape(box, new Vector3f(0, 1, 0));
|
|
|
|
//create vehicle node
|
|
Node vehicleNode=new Node("vehicleNode");
|
|
vehicle = new VehicleControl(compoundShape, 800);
|
|
vehicleNode.addControl(vehicle);
|
|
|
|
//setting suspension values for wheels, this can be a bit tricky
|
|
//see also https://docs.google.com/Doc?docid=0AXVUZ5xw6XpKZGNuZG56a3FfMzU0Z2NyZnF4Zmo&hl=en
|
|
float stiffness = 60.0f;//200=f1 car
|
|
float compValue = .3f; //(should be lower than damp)
|
|
float dampValue = .4f;
|
|
vehicle.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
|
|
vehicle.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
|
|
vehicle.setSuspensionStiffness(stiffness);
|
|
vehicle.setMaxSuspensionForce(10000.0f);
|
|
|
|
//Create four wheels and add them at their locations
|
|
Vector3f wheelDirection = new Vector3f(0, -1, 0); // was 0, -1, 0
|
|
Vector3f wheelAxle = new Vector3f(-1, 0, 0); // was -1, 0, 0
|
|
float radius = 0.5f;
|
|
float restLength = 0.3f;
|
|
float yOff = 0.5f;
|
|
float xOff = 1f;
|
|
float zOff = 2f;
|
|
|
|
Cylinder wheelMesh = new Cylinder(16, 16, radius, radius * 0.6f, true);
|
|
|
|
Node node1 = new Node("wheel 1 node");
|
|
Geometry wheels1 = new Geometry("wheel 1", wheelMesh);
|
|
node1.attachChild(wheels1);
|
|
wheels1.rotate(0, FastMath.HALF_PI, 0);
|
|
wheels1.setMaterial(mat);
|
|
vehicle.addWheel(node1, new Vector3f(-xOff, yOff, zOff),
|
|
wheelDirection, wheelAxle, restLength, radius, true);
|
|
|
|
Node node2 = new Node("wheel 2 node");
|
|
Geometry wheels2 = new Geometry("wheel 2", wheelMesh);
|
|
node2.attachChild(wheels2);
|
|
wheels2.rotate(0, FastMath.HALF_PI, 0);
|
|
wheels2.setMaterial(mat);
|
|
vehicle.addWheel(node2, new Vector3f(xOff, yOff, zOff),
|
|
wheelDirection, wheelAxle, restLength, radius, true);
|
|
|
|
Node node3 = new Node("wheel 3 node");
|
|
Geometry wheels3 = new Geometry("wheel 3", wheelMesh);
|
|
node3.attachChild(wheels3);
|
|
wheels3.rotate(0, FastMath.HALF_PI, 0);
|
|
wheels3.setMaterial(mat);
|
|
vehicle.addWheel(node3, new Vector3f(-xOff, yOff, -zOff),
|
|
wheelDirection, wheelAxle, restLength, radius, false);
|
|
|
|
Node node4 = new Node("wheel 4 node");
|
|
Geometry wheels4 = new Geometry("wheel 4", wheelMesh);
|
|
node4.attachChild(wheels4);
|
|
wheels4.rotate(0, FastMath.HALF_PI, 0);
|
|
wheels4.setMaterial(mat);
|
|
vehicle.addWheel(node4, new Vector3f(xOff, yOff, -zOff),
|
|
wheelDirection, wheelAxle, restLength, radius, false);
|
|
|
|
vehicleNode.attachChild(node1);
|
|
vehicleNode.attachChild(node2);
|
|
vehicleNode.attachChild(node3);
|
|
vehicleNode.attachChild(node4);
|
|
|
|
rootNode.attachChild(vehicleNode);
|
|
getPhysicsSpace().add(vehicle);
|
|
|
|
//driver
|
|
Node driverNode=new Node("driverNode");
|
|
driverNode.setLocalTranslation(0,2,0);
|
|
driver=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,.5f,0.2f)));
|
|
driverNode.addControl(driver);
|
|
|
|
rootNode.attachChild(driverNode);
|
|
getPhysicsSpace().add(driver);
|
|
|
|
//joint
|
|
slider=new SliderJoint(driver, vehicle, Vector3f.UNIT_Y.negate(), Vector3f.UNIT_Y, true);
|
|
slider.setUpperLinLimit(.1f);
|
|
slider.setLowerLinLimit(-.1f);
|
|
|
|
getPhysicsSpace().add(slider);
|
|
|
|
Node pole1Node=new Node("pole1Node");
|
|
Node pole2Node=new Node("pole1Node");
|
|
Node bridgeNode=new Node("pole1Node");
|
|
pole1Node.setLocalTranslation(new Vector3f(-2,-1,4));
|
|
pole2Node.setLocalTranslation(new Vector3f(2,-1,4));
|
|
bridgeNode.setLocalTranslation(new Vector3f(0,1.4f,4));
|
|
|
|
RigidBodyControl pole1=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,1.25f,0.2f)),0);
|
|
pole1Node.addControl(pole1);
|
|
RigidBodyControl pole2=new RigidBodyControl(new BoxCollisionShape(new Vector3f(0.2f,1.25f,0.2f)),0);
|
|
pole2Node.addControl(pole2);
|
|
bridge=new RigidBodyControl(new BoxCollisionShape(new Vector3f(2.5f,0.2f,0.2f)));
|
|
bridgeNode.addControl(bridge);
|
|
|
|
rootNode.attachChild(pole1Node);
|
|
rootNode.attachChild(pole2Node);
|
|
rootNode.attachChild(bridgeNode);
|
|
getPhysicsSpace().add(pole1);
|
|
getPhysicsSpace().add(pole2);
|
|
getPhysicsSpace().add(bridge);
|
|
|
|
}
|
|
|
|
@Override
|
|
public void simpleUpdate(float tpf) {
|
|
Quaternion quat=new Quaternion();
|
|
cam.lookAt(vehicle.getPhysicsLocation(), Vector3f.UNIT_Y);
|
|
}
|
|
|
|
public void onAction(String binding, boolean value, float tpf) {
|
|
if (binding.equals("Lefts")) {
|
|
if (value) {
|
|
steeringValue += .5f;
|
|
} else {
|
|
steeringValue += -.5f;
|
|
}
|
|
vehicle.steer(steeringValue);
|
|
} else if (binding.equals("Rights")) {
|
|
if (value) {
|
|
steeringValue += -.5f;
|
|
} else {
|
|
steeringValue += .5f;
|
|
}
|
|
vehicle.steer(steeringValue);
|
|
} else if (binding.equals("Ups")) {
|
|
if (value) {
|
|
accelerationValue += accelerationForce;
|
|
} else {
|
|
accelerationValue -= accelerationForce;
|
|
}
|
|
vehicle.accelerate(accelerationValue);
|
|
} else if (binding.equals("Downs")) {
|
|
if (value) {
|
|
vehicle.brake(brakeForce);
|
|
} else {
|
|
vehicle.brake(0f);
|
|
}
|
|
} else if (binding.equals("Space")) {
|
|
if (value) {
|
|
getPhysicsSpace().remove(slider);
|
|
slider.destroy();
|
|
vehicle.applyImpulse(jumpForce, Vector3f.ZERO);
|
|
}
|
|
} else if (binding.equals("Reset")) {
|
|
if (value) {
|
|
System.out.println("Reset");
|
|
vehicle.setPhysicsLocation(new Vector3f(0, 0, 0));
|
|
vehicle.setPhysicsRotation(new Matrix3f());
|
|
vehicle.setLinearVelocity(Vector3f.ZERO);
|
|
vehicle.setAngularVelocity(Vector3f.ZERO);
|
|
vehicle.resetSuspension();
|
|
bridge.setPhysicsLocation(new Vector3f(0,1.4f,4));
|
|
bridge.setPhysicsRotation(Quaternion.DIRECTION_Z.toRotationMatrix());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|