Camera jerking around

Ok, I have this code:

import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import com.game.camera.CharacterChaser;
import com.game.resources.ResourceFile;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
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.input.thirdperson.ThirdPersonMouseLook;
import com.jme.input.util.SyntheticButton;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial;
import com.jme.scene.Text;
import com.jme.scene.shape.Box;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.PhysicsUpdateCallback;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.contact.ContactInfo;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

/**
 * This lesson shows a very simple example of modelling physics for a jump-and-run-like player character. It uses a box
 * with an altered center of gravity. Moving the player is done with surface motion, jumping by directly applying
 * forces.
 * <p/>
 * Important: this is, of course, not meant as <i>the</i> way to go! The actual physical representation that is chosen
 * for characters in a game strongly depends on the abilities the character should have and the other effects you want
 * to achieve. E.g. you could make a racing game with the approach shown here, but it will disregard many aspects you
 * might want to have in a racing game...
 * <p/>
 * Especially not regarded here: character cannot be turned, rotation of the character is not restricted - it may turn
 * when acting a while.
 * @author Irrisor
 */
public class MyGame extends SimplePhysicsGame {

   private ResourceFile dataFile;
   private TerrainBlock tb;

    private static final Vector3f ZERO = new Vector3f( 0, 0, 0 );

    private StaticPhysicsNode floor;
    private DynamicPhysicsNode player;

    private boolean playerOnFloor = false;
   private CharacterChaser chaser;
   
    protected void simpleInitGame() {
       try {
         dataFile = new ResourceFile("data.fdb");
      } catch (ZipException e) {
      } catch (IOException e) {
      }
       
        try {
         createFloor();
      } catch (IOException e) {
         e.printStackTrace();
      }

        // second we create a box - as we create multiple boxes this time the code moved into a separate method
        player = createBox();
        player.setName( "player" );
        color( player, new ColorRGBA( 0, 0, 1, 1 ) );
        player.getLocalTranslation().set( 8, 18, 0 );
        player.setCenterOfMass( new Vector3f( 0, -0.5f, 0 ) );

        final Material playerMaterial = new Material( "player material" );
        player.setMaterial( playerMaterial );
        buildChaseCamera();
        input.removeAllActions();
        input.addAction( new MoveAction( new Vector3f( -5, 0, 0 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_A, InputHandler.AXIS_NONE, false );
        input.addAction( new MoveAction( new Vector3f( 5, 0, 0 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_D, InputHandler.AXIS_NONE, false );

        input.addAction( new MoveAction( new Vector3f( 0, 0, 5 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_W, InputHandler.AXIS_NONE, false );
        input.addAction( new MoveAction( new Vector3f( 0, 0, -5 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_S, InputHandler.AXIS_NONE, false );

        input.addAction( new InputAction() {
            public void performAction( InputActionEvent evt ) {
                if ( playerOnFloor && evt.getTriggerPressed() ) {
                    player.addForce( new Vector3f( 0, 500, 0 ) );
                }
            }
        }, InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_SPACE, InputHandler.AXIS_NONE, false );

        SyntheticButton playerCollisionEventHandler = player.getCollisionEventHandler();
        input.addAction( new InputAction() {
            public void performAction( InputActionEvent evt ) {
                ContactInfo contactInfo = (ContactInfo) evt.getTriggerData();
                if ( contactInfo.getNode1() == floor || contactInfo.getNode2() == floor ) {
                    playerOnFloor = true;
                }
            }
        }, playerCollisionEventHandler, false );

        // and a very simple callback to set the variable to false before each step
        getPhysicsSpace().addToUpdateCallbacks( new PhysicsUpdateCallback() {
            public void beforeStep( PhysicsSpace space, float time ) {
                playerOnFloor = false;
            }

            public void afterStep( PhysicsSpace space, float time ) {

            }
        } );

        // finally print a key-binding message
        Text infoText = Text.createDefaultTextLabel( "key info", "[del] and [page down] to move, [home] to jump" );
        infoText.getLocalTranslation().set( 0, 20, 0 );
        statNode.attachChild( infoText );
    }
    private void buildChaseCamera() {
        HashMap props = new HashMap();
        props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "6");
        props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
        props.put(ThirdPersonMouseLook.PROP_MAXASCENT, ""+45 * FastMath.DEG_TO_RAD);
        props.put(ThirdPersonMouseLook.PROP_MOUSEBUTTON_FOR_LOOKING, "0");
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(5, 0, 30 * FastMath.DEG_TO_RAD));
        props.put(ChaseCamera.PROP_STAYBEHINDTARGET, true);
        props.put(ChaseCamera.PROP_MAINTAINAZIMUTH, true);
        System.out.println(ThirdPersonMouseLook.DEFAULT_MOUSEBUTTON_FOR_LOOKING);
        chaser = new CharacterChaser(cam, player, props);
        chaser.setMinDistance(20);
        chaser.setMaxDistance(25);
        chaser.setActionSpeed(.75f);
    }
    private void createFloor() throws IOException {
        floor = getPhysicsSpace().createStaticNode();
        rootNode.attachChild( floor );
       
        //Add Terrain
        MidPointHeightMap heightMap = new MidPointHeightMap(64, .5f);
      Vector3f terrainScale = new Vector3f(20, 0.05f, 20);
      tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale, heightMap.getHeightMap(), new Vector3f(0, 0, 0));


      tb.setModelBound(new BoundingBox());
      tb.updateModelBound();

      ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
      pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("grassb.png").getStream())), -128, 0, 128);
      pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("dirt.jpg").getStream())), 0, 128, 255);
      pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("highest.jpg").getStream())), 128, 255,384);
      pt.createTexture(32);

      TextureState ts = display.getRenderer().createTextureState();
      Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(), Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
      ts.setTexture(t1, 0);

      Texture t2 = TextureManager.loadTexture(ImageIO.read(dataFile.getEntryByName("Detail.jpg").getStream()),Texture.MinificationFilter.Trilinear,Texture.MagnificationFilter.Bilinear, true);

      ts.setTexture(t2, 1);
      t2.setWrap(Texture.WrapMode.Repeat);

      t1.setApply(Texture.ApplyMode.Combine);
      t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
      t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
      t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
      t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
      t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

      t2.setApply(Texture.ApplyMode.Combine);
      t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
      t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
      t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
      t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
      t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

      tb.setRenderState(ts);
      tb.setDetailTexture(1, 16);
      tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
       
      floor.attachChild(tb);
      
        floor.generatePhysicsGeometry();
    }

    private DynamicPhysicsNode createBox() {
        DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
        rootNode.attachChild( dynamicNode );
        final Box visualFallingBox = new Box( "falling box", new Vector3f(), 0.5f, 0.5f, 0.5f );
        dynamicNode.attachChild( visualFallingBox );
        dynamicNode.generatePhysicsGeometry();
        return dynamicNode;
    }

    @Override
    protected void simpleUpdate() {
       chaser.update(tpf);
       if(cam.getLocation().y < (tb.getHeight(cam.getLocation())+3)) {
          cam.getLocation().y = tb.getHeight(cam.getLocation()) + 3;
          cam.update();
       }
       cam.lookAt(player.getLocalTranslation(), Vector3f.UNIT_Y);
    }
   
    private class MoveAction extends InputAction {
        private Vector3f direction;

        public MoveAction( Vector3f direction ) {
            this.direction = direction;
        }

        public void performAction( InputActionEvent evt ) {
            if ( evt.getTriggerPressed() ) {
                player.getMaterial().setSurfaceMotion( direction );
            } else {
                player.getMaterial().setSurfaceMotion( ZERO );
            }
        }
    }

    private void color( Spatial spatial, ColorRGBA color ) {
        final MaterialState materialState = display.getRenderer().createMaterialState();
        materialState.setDiffuse( color );
        if ( color.a < 1 ) {
            final BlendState blendState = display.getRenderer().createBlendState();
            blendState.setEnabled( true );
            blendState.setBlendEnabled( true );
            blendState.setSourceFunction( BlendState.SourceFunction.SourceAlpha );
            blendState.setDestinationFunction( BlendState.DestinationFunction.OneMinusSourceAlpha );
            spatial.setRenderState( blendState );
            spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
        }
        spatial.setRenderState( materialState );
    }

    public static void main( String[] args ) {
        Logger.getLogger( "" ).setLevel( Level.WARNING ); // to see the important stuff
        new MyGame().start();
    }
}



When I move my character around the camera does awkward stuff like moving forward andd backward ALOT. Is it because the TriMeshs of the terrain are bouncing with physics or what?

You do not seem to call super.update(time) in your implementation, I do not understand how the physics get updated at all.

Also, you seem to use a chase cam controller and update the cam location yourself at the same time. The chase cam controller is supposed to set the location of the camera.

In general, its mostly some update order problem when for example some objects or the skybox lag behind in the camera.