ChaseCamera: player is not on the terrain

Hey…What's wrong with my code. I have a chaseCamera, a Terrain (midpointheightmap), a player node, but the player is always over the terrain and not "on" it. Can anyone help me?




/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package theracer;

import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.image.Texture.MagnificationFilter;
import com.jme.image.Texture.MinificationFilter;
import com.jme.input.ChaseCamera;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.ThirdPersonHandler;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.input.thirdperson.ThirdPersonRightAction;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

/**
 *
 * @author Jannis
 */
public class Main extends BaseGame {

    private int width, height, depth, freq;
    private boolean fullscreen;
    private Camera cam;
    private Node rootNode;
    private Timer timer;
    private TerrainBlock terrainBlock;
    private Node playerNode;
    private ChaseCamera chaser;
    private InputHandler input;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Main app = new Main();
        app.setConfigShowMode(ConfigShowMode.ShowIfNoConfig);
        app.start();
    }

    protected void initSystem() {
        width = settings.getWidth();
        height = settings.getHeight();
        depth = settings.getDepth();
        freq = settings.getFrequency();
        fullscreen = settings.isFullscreen();

        try {
            display = DisplaySystem.getDisplaySystem(settings.getRenderer());
            display.createWindow(width, height, depth, freq, fullscreen);

            cam = display.getRenderer().createCamera(width, height);
        } catch (JmeException e) {
        }

        display.getRenderer().setBackgroundColor(ColorRGBA.black.clone());

        cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
                1000);
        Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);

        cam.setFrame(loc, left, up, dir);

        cam.update();

        timer = Timer.getTimer();

        display.getRenderer().setCamera(cam);

        KeyBindingManager.getKeyBindingManager().set("Exit",
                KeyInput.KEY_ESCAPE);
    }

    public void initGame() {
        rootNode = new Node("RootNode");

        //Terrain
        setupTerrain();
        //Terrain

        //Player
        setupPlayer();
        //Player

        setupChaseCamera();
        setupInput();

        rootNode.updateGeometricState(0.0f, true);
        rootNode.updateRenderState();
    }

    public void reinit() {
    }

    public void cleanup() {
    }

    public void render(float interpolation) {
        display.getRenderer().clearBuffers();
        display.getRenderer().draw(rootNode);
    }

    public void update(float interpolation) {
        timer.update();
        interpolation = timer.getTimePerFrame();

        chaser.update(interpolation);
        input.update(interpolation);

           float camMinHeight = terrainBlock.getHeight(cam.getLocation()) + 2f;
        if (!Float.isInfinite(camMinHeight) && !Float.isNaN(camMinHeight)
                && cam.getLocation().y <= camMinHeight) {
            cam.getLocation().y = camMinHeight;
            cam.update();
        }

        float characterMinHeight = terrainBlock.getHeight(playerNode.getLocalTranslation()) + ((BoundingBox) playerNode.getWorldBound()).yExtent;
        if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
            playerNode.getLocalTranslation().y = characterMinHeight;
        }
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("Exit")) {
            System.exit(0);
        }
        rootNode.updateGeometricState(0.0f, true);
    }

    public void setupTerrain() {
        MidPointHeightMap heightMap = new MidPointHeightMap(64, 1.0f);
        terrainBlock = new TerrainBlock("midpoint block",
                heightMap.getSize(),
                new Vector3f(10, 0.5f, 10),
                heightMap.getHeightMap(),
                new Vector3f(-30, -20, -90));
        TextureState textureState = display.getRenderer().createTextureState();
        URL textureFile = null;
        try {
            textureFile = new File("Texture/Stone.jpg").toURI().toURL();
        } catch (MalformedURLException ex) {
            System.out.println("Error: " + ex);
        }
        Texture texture = TextureManager.loadTexture(textureFile,
                Texture.MinificationFilter.BilinearNearestMipMap,
                Texture.MagnificationFilter.Bilinear);
        textureState.setTexture(texture);
        terrainBlock.setRenderState(textureState);
        terrainBlock.updateRenderState();
        rootNode.attachChild(terrainBlock);
    }

    public void setupPlayer() {
        Box player = new Box("box", new Vector3f(), 5, 5, 5);
        player.setModelBound(new BoundingBox());
        player.updateModelBound();
        playerNode = new Node("Player Node");
        playerNode.attachChild(player);
        playerNode.updateWorldBound();
        rootNode.attachChild(playerNode);

    }

    private void setupChaseCamera() {
        Vector3f targetOffset = new Vector3f();
        targetOffset.y = ((BoundingBox) playerNode.getWorldBound()).yExtent * 1.5f;
        chaser = new ChaseCamera(cam, playerNode);
        chaser.setTargetOffset(targetOffset);
    }

    private void setupInput() {
        HashMap<String, Object> handlerProps = new HashMap<String, Object>();
        handlerProps.put(ThirdPersonHandler.PROP_DOGRADUAL, "true");
        handlerProps.put(ThirdPersonHandler.PROP_TURNSPEED, "" + (1.0f * FastMath.PI));
        handlerProps.put(ThirdPersonHandler.PROP_LOCKBACKWARDS, "false");
        handlerProps.put(ThirdPersonHandler.PROP_CAMERAALIGNEDMOVE, "true");
        input = new ThirdPersonHandler(playerNode, cam, handlerProps);
        input.setActionSpeed(100f);
    }
}