Please don't create too many different threads for the same problem, its hard to follow the problems 'storyline'.
terrain.getHeightFromWorld() returns the height of the terrain. but it seems does not take any terrains Y translation into account.
So when you set the enemies height, you also need to add the terrains Y translation.
terrain.getHeightFromWorld(node.getLocalTranslation())+terrainYTranslation,
here is a complete test.
i also altered your controller so it moves with linear interpolation towards the next target point.
package renegade;
import java.util.LinkedList;
import javax.swing.ImageIcon;
import jmetest.terrain.TestTerrain;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Controller;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.FaultFractalHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
public class TestTerrainMovement extends SimpleGame{
private LinkedList<Vector3f> movements = new LinkedList<Vector3f>();
private TerrainPage page;
@Override
protected void simpleInitGame() {
//Add terrain to the rootNode
buildTerrain();
buildEnemy();
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(45, 0, 45));
movements.add(new Vector3f(5, 0, 5));
movements.add(new Vector3f(-45, 0, -15));
movements.add(new Vector3f(0, 0, 45));
movements.add(new Vector3f(22, 0, -22));
movements.add(new Vector3f(0, 0, 0));
movements.add(new Vector3f(-15, 0, 30));
}
private void buildEnemy() {
Box b = new Box("enemy", new Vector3f(), 4, 2.5f, 10);
b.setModelBound(new BoundingBox());
b.updateModelBound();
rootNode.attachChild(b);
b.addController(new EnemyMovementController(b, movements, page ,-200 ));
b.getLocalTranslation().y = page.getHeightFromWorld(b.getWorldTranslation());
}
/**
* build the height map and terrain block.
*/
private void buildTerrain() {
FaultFractalHeightMap heightMap = new FaultFractalHeightMap(257, 32, 0, 255,
0.75f);
Vector3f terrainScale = new Vector3f(10,2,10);
heightMap.setHeightScale( 0.001f);
page = new TerrainPage("Terrain", 10, heightMap.getSize(), terrainScale,
heightMap.getHeightMap());
page.setModelBound(new BoundingBox());
page.updateModelBound();
page.setDetailTexture(1, 16);
rootNode.attachChild(page);
// generate a terrain texture with 2 textures
ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
heightMap);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/grassb.png")), -128, 0, 128);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/dirt.jpg")), 0, 128, 255);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/highest.jpg")), 128, 255,
384);
pt.createTexture(32);
// assign the texture to the terrain
TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
ts.setTexture(t1, 0);
//load a detail texture and set the combine modes for the two terrain textures.
Texture t2 = TextureManager.loadTexture(
TestTerrain.class.getClassLoader().getResource(
"jmetest/data/texture/Detail.jpg"),
Texture.MinificationFilter.Trilinear,
Texture.MagnificationFilter.Bilinear);
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);
page.setRenderState(ts);
//set the detail parameters.
page.setDetailTexture(1, 16);
page.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
rootNode.attachChild(page);
page.getLocalTranslation().x -= 50;
page.getLocalTranslation().y -= 200;
page.getLocalTranslation().z -= 50;
}
public static void main(String[] args) {
TestTerrainMovement game = new TestTerrainMovement();
game.setConfigShowMode(ConfigShowMode.AlwaysShow);
game.start();
}
}
class EnemyMovementController extends Controller{
private LinkedList<Vector3f> movements;
private TerrainPage terrain;
private Vector3f currentPoint;
private Spatial node;
private float terrainYTranslation;
public EnemyMovementController(Spatial node, LinkedList<Vector3f> movements, TerrainPage terrain, float terrainYTranslation){
this.movements = movements;
this.terrain = terrain;
this.node = node;
this.terrainYTranslation = terrainYTranslation;
}
@Override
public void update(float tpf) {
if(movements.isEmpty() == false){
currentPoint = movements.getFirst();
boolean moveComplete = checkIfReachedPoint();
if (moveComplete)
movements.remove();
updateMove(tpf);
}
}
public boolean checkIfReachedPoint(){
if((currentPoint.x <= node.getLocalTranslation().x+0.01f && currentPoint.x >= node.getLocalTranslation().x-0.01f) &&
currentPoint.z <= node.getLocalTranslation().z+0.01f && currentPoint.z >= node.getLocalTranslation().z-0.01f) {
return true;
} else {
return false;
}
}
public void updateMove(float tpf){
System.out.println("spatial location: " +node.getLocalTranslation());
System.out.println("current target: " +currentPoint +"; heigth: " +terrain.getHeightFromWorld(node.getLocalTranslation()));
node.getLocalTranslation().interpolate(new Vector3f(currentPoint.x,
terrain.getHeightFromWorld(node.getLocalTranslation())+terrainYTranslation,
currentPoint.z), 1f*tpf);
Vector3f normal = new Vector3f();
terrain.getSurfaceNormal(node.getLocalTranslation(), normal);
if(normal != null) {
node.rotateUpTo(normal);
}
}
}