Hi , i have just started out with jme physics and am trying to make a simple game where you roll a ball over bumpy terrain (much like the tutorials). I have made a model terrain in blender and imported it fine however the genratePhysicsGeometry() method simply creates a large sphere around the terrain which the ball rolls on. Is there a way to do it so the physics geometry is exactly the same shape as the terrain, allowing the ball to roll down hills etc?
this is what i have so far (A jumble of different tutorial classes!!)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import com.jme.app.AbstractGame;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Sphere;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.ObjToJme;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.PhysicsUpdateCallback;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.util.SimplePhysicsGame;
public class TestObjJmeWrite extends SimplePhysicsGame {
TriMesh model;
private DynamicPhysicsNode dynamicNode;
private InputHandler physicsStepInputHandler;
public static void main(String[] args) {
TestObjJmeWrite app = new TestObjJmeWrite();
app
.setDialogBehaviour(AbstractGame.FIRSTRUN_OR_NOCONFIGFILE_SHOW_PROPS_DIALOG);
app.start();
}
protected void simpleInitGame() {
ObjToJme converter = new ObjToJme();
try {
URL objFile = TestObjJmeWrite.class.getClassLoader().getResource(
"world.obj");
converter.setProperty("mtllib", objFile);
converter.setProperty("texdir",objFile);
ByteArrayOutputStream BO = new ByteArrayOutputStream();
System.out.println("Starting to convert .obj to .jme");
converter.convert(objFile.openStream(), BO);
//load as a TriMesh if single object
model = (TriMesh) BinaryImporter.getInstance().load(
new ByteArrayInputStream(BO.toByteArray()));
//load as a node if multiple objects
//Node model=(Node)BinaryImporter.getInstance().load(
// new ByteArrayInputStream(BO.toByteArray()));
model.setModelBound(new BoundingSphere());
model.updateModelBound();
} catch (IOException e) {
e.printStackTrace();
}
StaticPhysicsNode staticNode = getPhysicsSpace().createStaticNode();
rootNode.attachChild( staticNode );
model.getLocalScale().set( 20, 10f, 20 );
staticNode.attachChild(model);
staticNode.generatePhysicsGeometry();
dynamicNode = getPhysicsSpace().createDynamicNode();
rootNode.attachChild( dynamicNode );
Sphere bSphere = new Sphere("ball sphere", new Vector3f(), 20, 20, 3f);
dynamicNode.attachChild(bSphere);
dynamicNode.generatePhysicsGeometry();
dynamicNode.getLocalTranslation().set(0, 50, 0);
// we want to take in account now what was already mentioned in Lesson3:
// forces must be applied for each physics step if you want a constant force applied
// thus we create an input handler that gets invoked each physics step
physicsStepInputHandler = new InputHandler();
getPhysicsSpace().addToUpdateCallbacks( new PhysicsUpdateCallback() {
public void beforeStep( PhysicsSpace space, float time ) {
physicsStepInputHandler.update( time );
}
public void afterStep( PhysicsSpace space, float time ) {
}
} );
physicsStepInputHandler.addAction( new MyInputAction( new Vector3f( 70, 0, 0 ) ),
InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_L, InputHandler.AXIS_NONE, true );
physicsStepInputHandler.addAction( new MyInputAction( new Vector3f( -70, 0, 0 ) ),
InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_J, InputHandler.AXIS_NONE, true );
physicsStepInputHandler.addAction( new MyInputAction( new Vector3f( 0, 0, -70 ) ),
InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_K, InputHandler.AXIS_NONE, true );
physicsStepInputHandler.addAction( new MyInputAction( new Vector3f( 0, 0, 70 ) ),
InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_I, InputHandler.AXIS_NONE, true );
showPhysics = true;
display.getRenderer().setBackgroundColor(ColorRGBA.gray);
//needed for specular lighting(reflective light)
lightState.setSeparateSpecular(true);
}
private class MyInputAction extends InputAction {
private final Vector3f direction;
private final Vector3f appliedForce = new Vector3f();
/**
* The action get the node it should move and the direction it should move in.
*
* @param direction force that should be applied on each invocation of the action
*/
public MyInputAction( Vector3f direction ) {
// simply remember in member variables
this.direction = direction;
}
/**
* This method gets invoked upon key event
*
* @param evt more data about the event (we don't need it)
*/
public void performAction( InputActionEvent evt ) {
appliedForce.set( direction ).multLocal( evt.getTime() );
// the really important line: apply a force to the moved node
dynamicNode.addForce( appliedForce );
}
}
protected void simpleUpdate() {
// as the user can steer the sphere only in one direction it will fall off the floor after a short time
// we want to put it back up then
if ( dynamicNode.getWorldTranslation().y < -20 ) {
// ok it has definately fallen off the floor
// clear speed and forces
dynamicNode.clearDynamics();
// then put it over the floor again
dynamicNode.getLocalTranslation().set( 0, 5, 0 );
}
}
}
thanks for your help!