Hello,
I prepared a test with a cameranode, input keys are arrows to select direction and z to apply speed,
pratically when I turn in any direction the object starts to jump… please can you help me to find
why the object is jumping?
package test;
import static com.jme.input.KeyInput.*;
import java.util.ArrayList;
import java.util.logging.Logger;
import com.jme.bounding.BoundingBox;
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.light.PointLight;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.CameraNode;
import com.jme.scene.Controller;
import com.jme.scene.Geometry;
import com.jme.scene.Line;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jmex.game.StandardGame;
import com.jmex.game.state.BasicGameState;
import com.jmex.game.state.BasicGameStateNode;
import com.jmex.game.state.GameStateManager;
public class TestGame {
private static StandardGame instance;
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run() {
System.runFinalizersOnExit(true);
}
});
instance = new StandardGame("Test Game", StandardGame.GameType.GRAPHICAL, null);
instance.start();
BasicGameStateNode<BasicGameState> base = new BasicGameStateNode<BasicGameState>("Test View");
GameStateManager.getInstance().attachChild(base);
TestGS stateTest = new TestGS();
stateTest.setActive(true);
base.attachChild(stateTest);
base.setActive(true);
}
}
class TestGS extends BasicGameState {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(TestGS.class.getName());
private float gridFactor = 1000F;
private float frustumNear = 0.00000001F;
private float frustumFar = 1000000000F;
private void addGridNode(float spacing, float extent) {
//Node gridNode = ObjectLibrary.createGridNode(Vector3f.ZERO.clone(), gridFactor*100F, gridFactor);
Node gridNode = new Node("grid");
ArrayList<Vector3f> regularVertices = new ArrayList<Vector3f>();
for (int i = 0; i * spacing <= extent; i++) {
regularVertices.add(new Vector3f(-extent, 0, i * spacing));
regularVertices.add(new Vector3f(extent, 0, i * spacing));
regularVertices.add(new Vector3f(-extent, 0, -i * spacing));
regularVertices.add(new Vector3f(extent, 0, -i * spacing));
regularVertices.add(new Vector3f(i * spacing, 0, -extent));
regularVertices.add(new Vector3f(i * spacing, 0, extent));
regularVertices.add(new Vector3f(-i * spacing, 0, -extent));
regularVertices.add(new Vector3f(-i * spacing, 0, extent));
}
Geometry regularGrid = new Line("regularLine", regularVertices
.toArray(new Vector3f[] {}), null, null, null);
regularGrid.getDefaultColor().set(ColorRGBA.darkGray);
gridNode.attachChild(regularGrid);
super.getRootNode().attachChild(gridNode);
}
private CameraNode createCameraNode(final float boxExtent) {
// movable object
Box box = new Box("Box", Vector3f.ZERO.clone(), boxExtent,boxExtent,boxExtent);
box.setModelBound(new BoundingBox());
box.updateModelBound();
box.setRandomColors();
box.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
Node boxNode = new Node("node");
boxNode.attachChild(box);
boxNode.updateWorldBound();
boxNode.getLocalTranslation().set(
0F,
0F,
((BoundingBox) boxNode.getWorldBound()).zExtent*10F
);
CameraNode camNode = new CameraNode("view",DisplaySystem.getDisplaySystem().getRenderer().getCamera());
camNode.setLocalTranslation(0F, 10F, 0F);
camNode.attachChild(boxNode);
camNode.getCamera().setFrustumPerspective(55F, (float) DisplaySystem.getDisplaySystem().getWidth() / (float) DisplaySystem.getDisplaySystem().getHeight(), frustumNear, frustumFar);
return camNode;
}
private void addLightNode() {
PointLight light = new PointLight();
light.setAttenuate(true);
light.setDiffuse(new ColorRGBA(1.0F, 1.0F, 0.25F, 1.0F));
light.setAmbient(new ColorRGBA(0.1F, 0.1F, 0.1F, 1.0F));
light.setLocation(new Vector3f(0F, 0F, 0F));
light.setEnabled(true);
LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
lightState.setEnabled(true);
lightState.attach(light);
super.getRootNode().setRenderState(lightState);
}
public TestGS() {
super("gsTest");
// world grid
this.addGridNode(gridFactor/10F, gridFactor*100F);
// camera node
CameraNode cameraNode = this.createCameraNode(0.1F);
super.getRootNode().attachChild(cameraNode);
TestController controller = new TestController(cameraNode);
super.getRootNode().addController(controller);
//light
this.addLightNode();
super.getRootNode().updateGeometricState(0, true);
}
@Override
public void update(float tpf) {
super.getRootNode().updateWorldData(tpf);
super.update(tpf);
}
@Override
public void render(float tpf) {
super.render(tpf);
}
}
abstract class AController extends Controller {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(AController.class.getName());
enum ETravelAction {
LEFT, RIGHT, UP, DOWN,
INCREASE, DECREASE,
STRAFE_UP,STRAFE_DOWN,STRAFE_LEFT,STRAFE_RIGHT,
ULTRAZOOMIN, ULTRAZOOMOUT, ZOOMIN, ZOOMOUT,
TARGET_SHIP,
EXIT}
protected GameControlManager manager;
protected void bindKey(ETravelAction action, int...keys) {
final GameControl control = manager.getControl(action.name());
for (int key : keys) {
control.addBinding(new KeyboardBinding(key));
}
}
protected float enumValue(ETravelAction action) {
return manager.getControl(action.name()).getValue();
}
}
class TestController extends AController {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(TestController.class.getName());
private static final float TURN_SPEED = 2F;
private CameraNode cameraNode;
private float hAngle;
private float vAngle;
private float speedcam = 1F;
private Quaternion q = new Quaternion();
public TestController(CameraNode cameraNodePar) {
this.cameraNode = cameraNodePar;
this.manager = new GameControlManager();
//create all actions
for (ETravelAction action : ETravelAction.values()) {
manager.addControl(action.name());
}
bindKey(ETravelAction.EXIT, KEY_ESCAPE);
bindKey(ETravelAction.INCREASE, KEY_Z);
bindKey(ETravelAction.DECREASE, KEY_X);
bindKey(ETravelAction.TARGET_SHIP, KEY_SPACE);
bindKey(ETravelAction.ZOOMIN, KEY_ADD);
bindKey(ETravelAction.ZOOMOUT, KEY_MINUS);
bindKey(ETravelAction.UP, KEY_UP);
bindKey(ETravelAction.DOWN, KEY_DOWN);
bindKey(ETravelAction.LEFT, KEY_LEFT);
bindKey(ETravelAction.RIGHT, KEY_RIGHT);
bindKey(ETravelAction.STRAFE_UP, KEY_W);
bindKey(ETravelAction.STRAFE_DOWN, KEY_S);
bindKey(ETravelAction.STRAFE_LEFT, KEY_A);
bindKey(ETravelAction.STRAFE_RIGHT, KEY_D);
}
@Override
public void update(float time) {
if (enumValue(ETravelAction.EXIT) > 0) {
System.exit(0);
}
if (enumValue(ETravelAction.LEFT) > 0||enumValue(ETravelAction.RIGHT) > 0
||enumValue(ETravelAction.UP) > 0||enumValue(ETravelAction.DOWN) > 0) {
hAngle += TURN_SPEED * time * (enumValue(ETravelAction.LEFT) - enumValue(ETravelAction.RIGHT));
vAngle += TURN_SPEED * time * (enumValue(ETravelAction.DOWN) - enumValue(ETravelAction.UP));
this.cameraNode.getLocalRotation().set( q.fromAngles(vAngle, hAngle, 0f) );
}
if (enumValue(ETravelAction.INCREASE) > 0
/*||enumValue(ETravelAction.DECREASE) > 0*/) {
Vector3f shipDirection = new Vector3f();
Vector3f observedPosition = this.cameraNode.getLocalTranslation();
observedPosition.addLocal(this.cameraNode.getLocalRotation().getRotationColumn(2, shipDirection).multLocal(speedcam));
}
}
}