Hello there,
I’m a relative newcomer to JMonkey , but I’ve been through the tutorials and have a reasonable idea of the principles, although the Math is a bit daunting.
Anyway, my issue is that I’m trying to modify the TestFancyCar module to drive over my own terrain and road, but whatever I do I can’t seem to position the vehicle over my terrain. setLocalTranslation and move commands seem ineffective on both the vehicle and my terrain. The car drives ok, but always starts from the same position, no matter where I set its initial position. If I omit the SetupFloor routine, the car just sinks in oblivion.
The code follows. I can supply the Terrain.j3o file if someone can tell me where to put it (nicely). This is a WIP at the moment and will be refined later, I just want to get the basic game going.
I thank you in advance for any advice.
/* * Copyright (c) 2009-2012 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 mygame;import com.jme3.app.SettingsDialog;
import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.control.VehicleControl;
import com.jme3.bullet.objects.VehicleWheel;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
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.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.shape.Box;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture.WrapMode;
public class TestFancyCar extends SimpleApplication implements ActionListener {
private BulletAppState bulletAppState;
private VehicleControl player;
private VehicleWheel fr, fl, br, bl;
private Node node_fr, node_fl, node_br, node_bl;
public float wheelRadius;
public float steeringValue = 0;
public float accelerationValue = 0;
public Node carNode;
public Material mat;
public Box floor;
public Geometry floorGeom;
private RigidBodyControl floorPhy;
public Spatial roadGeo;
public RigidBodyControl roadPhysics;
public CameraNode camNode;
public static void main(String[] args) {
TestFancyCar app = new TestFancyCar();
app.start();
}
private void setupKeys() {
inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_LEFT));
inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_RIGHT));
inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_UP));
inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_DOWN));
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");
}
@Override
public void simpleInitApp()
{
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
// bulletAppState.getPhysicsSpace().enableDebug(assetManager);
if (settings.getRenderer().startsWith(“LWJGL”)) {
// BasicShadowRenderer bsr = new BasicShadowRenderer(assetManager, 512);
// bsr.setDirection(new Vector3f(-0.5f, -0.3f, -0.3f).normalizeLocal());
// viewPort.addProcessor(bsr);
}
viewPort.setBackgroundColor(ColorRGBA.Blue);
cam.setFrustumFar(550f);
flyCam.setMoveSpeed(10);
setupKeys();
// PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
setupFloor();
LoadRoad();
buildPlayer();
carNode.move(new Vector3f(-200f,30f,-100f)); // does not seem to work
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(0f, -1f, 0f).normalizeLocal());
rootNode.addLight(dl);
AmbientLight ambient = new AmbientLight();
ambient.setColor(ColorRGBA.White.mult(5f));
rootNode.addLight(ambient);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
//-------------------------------------------------
// Load the road
//-------------------------------------------------
public void LoadRoad()
{
roadGeo = assetManager.loadModel("Scenes/Terrain.j3o");
roadPhysics = new RigidBodyControl(0f); // make the road solid
roadGeo.addControl(roadPhysics);
bulletAppState.getPhysicsSpace().add(roadPhysics);
roadGeo.setLocalTranslation(new Vector3f(0,30,0)); // does not seem to have any effect
rootNode.attachChild(roadGeo);
}
//------------------------------------------------
// Set up the floor
//------------------------------------------------
public void setupFloor() {
mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall.j3m");
mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);
mat.getTextureParam("NormalMap").getTextureValue().setWrap(WrapMode.Repeat);
mat.getTextureParam("ParallaxMap").getTextureValue().setWrap(WrapMode.Repeat);
mat.setBoolean("UseMaterialColors", false); // with Lighting.j3md
mat.setColor("Diffuse", ColorRGBA.White ); // with Lighting.j3md
mat.setColor("Ambient", ColorRGBA.White ); // with Lighting.j3md
floor = new Box(Vector3f.ZERO, 500, 1f, 500);
floor.scaleTextureCoordinates(new Vector2f(112.0f, 112.0f));
floorGeom = new Geometry("Floor", floor);
floorGeom.setShadowMode(ShadowMode.Receive);
floorGeom.setMaterial(mat);
/* Make the floor physical with mass 0.0f! */
floorPhy = new RigidBodyControl(0.0f);
floorGeom.addControl(floorPhy);
// floorGeom.setLocalTranslation(new Vector3f(0f,-20f,0f));
floorGeom.setLocalTranslation(Vector3f.ZERO);
floorGeom.move(0f,20f,0f); // Does not seem to have any effect
bulletAppState.getPhysicsSpace().add(floorPhy);
this.rootNode.attachChild(floorGeom);
}
//----------------------------------------------------------------
private Geometry findGeom(Spatial spatial, String name)
{
if (spatial instanceof Node) {
Node node = (Node) spatial;
for (int i = 0; i < node.getQuantity(); i++) {
Spatial child = node.getChild(i);
Geometry result = findGeom(child, name);
if (result != null) {
return result;
}
}
} else if (spatial instanceof Geometry) {
if (spatial.getName().startsWith(name)) {
return (Geometry) spatial;
}
}
return null;
}
//--------------------------------------------------------------
private void buildPlayer()
{
float stiffness = 120.0f;//200=f1 car
float compValue = 0.2f; //(lower than damp!)
float dampValue = 0.3f;
final float mass = 400;
//Load model and get chassis Geometry
carNode = (Node) assetManager.loadModel(“Models/Ferrari/Car.scene”);
carNode.setShadowMode(ShadowMode.Cast);
Geometry chasis = findGeom(carNode, “Car”);
BoundingBox box = (BoundingBox) chasis.getModelBound();
//Create a hull collision shape for the chassis
CollisionShape carHull = CollisionShapeFactory.createDynamicMeshShape(chasis);
//Create a vehicle control
player = new VehicleControl(carHull, mass);
//Setting default values for wheels
player.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
player.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
player.setSuspensionStiffness(stiffness);
player.setMaxSuspensionForce(10000);
//Create four wheels and add them at their locations
//note that our fancy car actually goes backwards…
Vector3f wheelDirection = new Vector3f(0, -1, 0);
Vector3f wheelAxle = new Vector3f(-1, 0, 0);
Geometry wheel_fr = findGeom(carNode, “WheelFrontRight”);
wheel_fr.center();
box = (BoundingBox) wheel_fr.getModelBound();
wheelRadius = box.getYExtent();
float back_wheel_h = (wheelRadius * 1.7f) - 1f;
float front_wheel_h = (wheelRadius * 1.9f) - 1f;
player.addWheel(wheel_fr.getParent(), box.getCenter().add(0, -front_wheel_h, 0),
wheelDirection, wheelAxle, 0.2f, wheelRadius, true);
Geometry wheel_fl = findGeom(carNode, “WheelFrontLeft”);
wheel_fl.center();
box = (BoundingBox) wheel_fl.getModelBound();
player.addWheel(wheel_fl.getParent(), box.getCenter().add(0, -front_wheel_h, 0),
wheelDirection, wheelAxle, 0.2f, wheelRadius, true);
Geometry wheel_br = findGeom(carNode, “WheelBackRight”);
wheel_br.center();
box = (BoundingBox) wheel_br.getModelBound();
player.addWheel(wheel_br.getParent(), box.getCenter().add(0, -back_wheel_h, 0),
wheelDirection, wheelAxle, 0.2f, wheelRadius, false);
Geometry wheel_bl = findGeom(carNode, “WheelBackLeft”);
wheel_bl.center();
box = (BoundingBox) wheel_bl.getModelBound();
player.addWheel(wheel_bl.getParent(), box.getCenter().add(0, -back_wheel_h, 0),
wheelDirection, wheelAxle, 0.2f, wheelRadius, false);
player.getWheel(2).setFrictionSlip(4);
player.getWheel(3).setFrictionSlip(4);
//-- Create a camera and attach it to the car
carNode.addControl(player);
rootNode.attachChild(carNode);
bulletAppState.getPhysicsSpace().add(player);
}
//---------------------------------------------------------------------
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Lefts")) {
if (value) {
steeringValue += .5f;
} else {
steeringValue += -.5f;
}
player.steer(steeringValue);
} else if (binding.equals("Rights")) {
if (value) {
steeringValue += -.5f;
} else {
steeringValue += .5f;
}
player.steer(steeringValue);
} //note that our fancy car actually goes backwards..
else if (binding.equals("Ups")) {
if (value) {
accelerationValue -= 800;
} else {
accelerationValue += 800;
}
player.accelerate(accelerationValue);
player.setCollisionShape(CollisionShapeFactory.createDynamicMeshShape(findGeom(carNode, "Car")));
} else if (binding.equals("Downs")) {
if (value) {
player.brake(40f);
} else {
player.brake(0f);
}
} else if (binding.equals("Reset")) {
if (value) {
System.out.println("Reset");
player.setPhysicsLocation(Vector3f.ZERO);
player.setPhysicsRotation(new Matrix3f());
player.setLinearVelocity(Vector3f.ZERO);
player.setAngularVelocity(Vector3f.ZERO);
player.resetSuspension();
} else {
}
}
}
@Override
public void simpleUpdate(float tpf) {
// cam.lookAt(carNode.getWorldTranslation(), Vector3f.UNIT_Y);
camNode = new CameraNode("CamNode", cam);
camNode.setControlDir(CameraControl.ControlDirection.SpatialToCamera);
camNode.setLocalTranslation(new Vector3f(0, 4, 0));
Quaternion quat = new Quaternion();
quat.lookAt(Vector3f.UNIT_Z.mult(-1), Vector3f.UNIT_Y);
camNode.setLocalRotation(quat);
carNode.attachChild(camNode);
camNode.setEnabled(true);
flyCam.setEnabled(false);
}
}