Moving an object at low world unit causes a "jumping" on Y axis... how to solve?

Hi, I have an object. I move it at costant speed with low world unit values, eg 0.0000001, 0.0000002 and so on.

But it jumps (always on Y axis)… like it was not fixed on its new position, please can you give me som hint how to solve it?

In the final body of update() I put the following, and I removed it, without any successful fix:

       observerNode.getCamera().setLocation( observedPosition.clone().addLocal(0, SCALE/2F, SCALE/2F) );
       //LOOKAT, without does not jump
       observerNode.getCamera().lookAt(observedPosition, IJmeConsts3D.UP);
       //chaser.update(time); // also chaser jumps


       // ==> FROM HERE
       observedNode.updateGeometricState(time, true);

       observerNode.updateGeometricState(time, true);
       InfoRegistry.class.cast(SingletonRegistry.getInfoRegistry()).set(InfoRegistry.KEY_XYZ, observedPosition.clone());
        InfoRegistry.class.cast(SingletonRegistry.getInfoRegistry()).set(InfoRegistry.KEY_SPEED, speedcam);

I am not able to figure out if the cause is my implementation, pratically I am using
several gamestates, but every object is rendered by distinct RenderPasses,
one for background, one for HUD and so on. Could it be the cause?

Maybe it's a precision problem, as the JME coordinate system is using floats?

This is probably a long shot, but the bit about calling lookAt reminded me : you have to call camera.update() sometimes after you've changed the camera parameters.  I had a problem that sounded similar as the camera does get updated at other times, which can cause a little jump in the frame it gets updated.  So try throwing this in after the lookAt call :


Sooner or later I'll make a suggestion that actually works out, hope this is the one :)

Thank you for suggestion, it works, but unfortunately only when I rescale up the object.

Tumaini said:

Maybe it's a precision problem, as the JME coordinate system is using floats?

Yes everywhere for what I know, but I don't know well JME2 and JOGL/LWJGL to say
if it can influence coordinates under 1.E-7 or 0.000001. Effectively I noticed the same
anomaly when moving only the camera in some other test, when passed up 1.E-7
frame jumping disappeared.


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;

public class TestGame {
   private static StandardGame instance;
    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread(){
            public void run() {
        instance = new StandardGame("Test Game", StandardGame.GameType.GRAPHICAL, null);
        BasicGameStateNode<BasicGameState> base = new BasicGameStateNode<BasicGameState>("Test View");
        TestGS stateTest = new TestGS();


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);
   private CameraNode createCameraNode(final float boxExtent) {
      // movable object
      Box box = new Box("Box", Vector3f.ZERO.clone(), boxExtent,boxExtent,boxExtent);
        box.setModelBound(new BoundingBox());
        Node boxNode = new Node("node");
            ((BoundingBox) boxNode.getWorldBound()).zExtent*10F
      CameraNode camNode = new CameraNode("view",DisplaySystem.getDisplaySystem().getRenderer().getCamera());
      camNode.setLocalTranslation(0F, 10F, 0F);

      camNode.getCamera().setFrustumPerspective(55F, (float) DisplaySystem.getDisplaySystem().getWidth() / (float) DisplaySystem.getDisplaySystem().getHeight(), frustumNear, frustumFar);
      return camNode;
   private void addLightNode() {
      PointLight light = new PointLight();
        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));
        LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
   public TestGS() {
      // world grid
      this.addGridNode(gridFactor/10F, gridFactor*100F);
      // camera node
      CameraNode cameraNode = this.createCameraNode(0.0001F);
        TestController controller = new TestController(cameraNode);
      super.getRootNode().updateGeometricState(0, true);

   public void update(float tpf) {
   public void render(float 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,
   protected GameControlManager manager;
   protected void bindKey(ETravelAction action, int...keys) {
        final GameControl control = manager.getControl(;
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
   protected float enumValue(ETravelAction action) {
        return manager.getControl(;

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()) {
        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);  
   public void update(float time) {
        if (enumValue(ETravelAction.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));


your frustum values are also very big, which makes the z-buffer imprecise.

private float frustumNear = 0.00000001F;

private float frustumFar =  1000000000F;

try to use some smaller values (frustum near should be as big as possible)