I can't see my terrain! Scale/placement issue?

Here is my code so far.


package test;


import java.net.URL;

import javax.swing.ImageIcon;

import jmetest.renderer.TestSkybox;
import jmetest.terrain.TestTerrain;

import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
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.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

public class testTerrain extends BaseGame{

   //terrain block for the terrain
   private TerrainBlock tb;
   //the skybox
   private Skybox skybox;
   
   //timer for the game to obtain framerate
   protected Timer timer;
   //camera for the game
   private Camera cam;
   //variables for storing display properties
   private int width, height, depth, freq;
   //boolean for fullscreen
   private boolean fullscreen;
   //the root node of the scene graph
   private Node scene;
   //TextureState to show the monkey on the sphere.
   private TextureState ts;
   
   //entry point
   public static void main(String[] args) {
      
      //create and initialise new application
      testTerrain app = new testTerrain();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      app.start();

   }

   @Override
   /**
   * clean up the textures.
   *
   */
   protected void cleanup() {
         ts.deleteAll();
      
   }

   @Override
   protected void initGame() {
      
      scene = new Node("Scene graph node");
      /** Create a ZBuffer to display pixels closest to the camera above farther ones.  */
       ZBufferState buf = display.getRenderer().createZBufferState();
       buf.setEnabled(true);
       buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
       scene.setRenderState(buf);
      //Add terrain to the scene
        buildTerrain();
      //Light the world
       buildLighting();
       //Add the skybox
       buildSkyBox();
 
      // update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
      
   }

   @Override
   protected void initSystem() {
      
      //store the display properties information
      width = this.settings.getWidth();
      height = this.settings.getHeight();
      depth = this.settings.getDepth();
      freq = this.settings.getFrequency();
      fullscreen = this.settings.isFullscreen();

      
      //chech that display properties work, if not then exit
      try {
            display = DisplaySystem.getDisplaySystem(this.settings.getRenderer());
            display.createWindow(width, height, depth, freq, fullscreen);
         
            cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
            e.printStackTrace();
            System.exit(1);
      }
      
      //set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black);
      
      //initialize the camera
      cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
      Vector3f loc = new Vector3f(1.0f, 1.0f, 1.0f);
      Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
      cam.update();
      
      display.getRenderer().setCamera(cam);
      
      /** Get a high resolution timer for FPS updates. */
      timer = Timer.getTimer();

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

   @Override
   /**
   * will be called if the resolution changes
   *
   */
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
      
   }

   @Override
   /**
   * draws the scene graph
   */
   protected void render(float interpolation) {
      
      //Clear the screen
      display.getRenderer().clearBuffers();
      
      display.getRenderer().draw(scene);
      
   }

   @Override
   /**
   * During an update we only look for the escape button and update the timer
   * to get the framerate.
   */
   protected void update(float interpolation) {
      
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
      //if escape was pressed, we exit
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      
      //we want to keep the skybox around our eyes, so move it with
      //the camera
      skybox.setLocalTranslation(cam.getLocation());
      
   }
   
   private void buildTerrain() {
      
      URL heightMapImage = testTerrain.class.getClassLoader().getResource("data/heightmap.png");
      
      ImageBasedHeightMap heightMap = new ImageBasedHeightMap(
            new ImageIcon(heightMapImage).getImage()
            );
       
      // Scale the data
      Vector3f terrainScale = new Vector3f(1000, 0.0575f, 4);
      // create a terrainblock
      tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
            heightMap.getHeightMap(), new Vector3f(0, 0, 0));

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

      // 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 = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
            Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
      ts.setTexture(t1, 0);

      tb.setRenderState(ts);
      
   }
   
   
   /**
    * creates a light for the terrain.
    */
   private void buildLighting() {
      /** Set up a basic, default light. */
       DirectionalLight light = new DirectionalLight();
       light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
       light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
       light.setDirection(new Vector3f(1,-1,0));
       light.setEnabled(true);

         /** Attach the light to a lightState and the lightState to rootNode. */
       LightState lightState = display.getRenderer().createLightState();
       lightState.setEnabled(true);
       lightState.attach(light);
       scene.setRenderState(lightState);
   }
   
    /**
     * buildSkyBox creates a new skybox object with all the proper textures. The
     * textures used are the standard skybox textures from all the tests.
     *
     */
   private void buildSkyBox() {
        skybox = new Skybox("skybox", 10, 10, 10);

        Texture north = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/north.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture south = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/south.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture east = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/east.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture west = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/west.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture up = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/top.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture down = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/bottom.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);

        skybox.setTexture(Skybox.Face.North, north);
        skybox.setTexture(Skybox.Face.West, west);
        skybox.setTexture(Skybox.Face.South, south);
        skybox.setTexture(Skybox.Face.East, east);
        skybox.setTexture(Skybox.Face.Up, up);
        skybox.setTexture(Skybox.Face.Down, down);
        skybox.preloadTextures();
        scene.attachChild(skybox);
   }
   
}



I cannot see the terrain!  :(

I have tried playing about with the numbers but really I have no idea which number does what so I have been at a loss with it.

I tried to look through the API for clues but that thing confuses me so much.

Anyway, my ventures into the unknown have left me with a few questions.

Firstly number one!

1 - Where is my Terrain? Can anyone tell why I can't see it? I'm sure it is a scaling issue or to do with the placement of something, either the camera or the terrain, but I don't know what is placed where and with respect to which point of the object. FYI heightmap.png is a 127x127, dunno if the resolution of this makes a difference.

2 - I have been looking at the Vector3f things the next few questions are a cascade of inquiries in this vein. My first question is, what actually is a Vector3f? I would assume that they are vectors (I came up with that one myself, no help at all) but then, just a vector is a bit abstract. Vectors need starting positions, scale and icecream. Then looking at the camera settings I have loc, left, up and dir each with their own associated vectors3f.  Some places they are used they seem not to be used as vectors but merely as arrays (like the scale for terrain scale) what's the deal with this?

3 - Is there a standard way that vector3f's are laid out? ie. Vector3f ( x value, y value, z value)

4 - What do the values represent here?

      // Scale the data
      Vector3f terrainScale = new Vector3f(1000, 0.0575f, 4);



5 - what is going on here? I'd like to think that I understand it but frankly I don't;

      //initialize the camera
      cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
      Vector3f loc = new Vector3f(1.0f, 1.0f, 1.0f);
      Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
      cam.update();



I'm fairly happy with the rest of it and think that I understand it well enough to get on, but the bits I have outlined, I just don't get and they are slowing up my progress so I'd appreciate any help.

Thanks

Neilos

Let me get you started…


Neilos said:

Where is my Terrain?

The camera is likely still sitting at the origin (in 3D space that is (0, 0, 0)). So you need to move you camera up and away from your terrain and then point it in the right direction. Look into these methods and their documentation...


camera.setLocation(new Vector3f(100, 100, 100));
camera.lookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y);




Neilos said:

What actually is a Vector3f?

It's simply an object that contains three scalar values. In this context, these values usually represent a point in 3D space defined by x,y,z.


Neilos said:

Is there a standard way that vector3f's are laid out? ie. Vector3f ( x value, y value, z value)

Yes, you got it right.


Neilos said:

What do the values represent here?

Code:
// Scale the data
Vector3f terrainScale = new Vector3f(1000, 0.0575f, 4);


The vector is going to be multiplied against the terrain data, to change its scale (stretch it, etc.). Say given a point (10, 10, 2.5) on your terrain data, it will be scaled to be at location (10000, 0.575, 10). All 'x' coordinates will be multiplied by 1000, all 'y' coordinates will be multiplied by 0.0575, and so on.


Neilos said:

What is going on here? (Camera code follows)

This is defining the shape of the camera frustum. This only needs to be done once, and the math is rather involved. For now, just accept that it works and use the methods provided above to move your camera around and point it at things.

Thanks for the answers they helped a lot. Unfortunately I am still having problems.


camera.setLocation(new Vector3f(100, 100, 100));
camera.lookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y);



Isn't this what is happening here?

      //initialize the camera
      cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
      Vector3f loc = new Vector3f(1.0f, 1.0f, 1.0f);
      Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
      cam.update();



With the Vector3f's loc and dir? If it is then I understand it enough to know which is controlling what. My problem would then be what do the values literally translate to?

loc seems pretty simple except for I don't know which vector component goes in which direction. Is it left/right is x, up/down is y and forward/back is z? Or is it that I have y and z confused?

dir, I think, should fall in to place after that as I think that it is the location to which the camera is pointing. Correct?

If I am right so far then I understand enough to point the camera. But I still didn't see the terrain. So I decided to add a player and a chase camera as described in the flagrush tutorial 5. I set the player to 0,0,0 and then updated the y coord to make him always above the ground (the camera also is always above the ground). I expected to see him sitting on the ground. No, no terrain, just a box floating in the air.

Then I decided to leave the box at 0,0,0 amd not update the height. The camera is still always above the ground. Now I see a box in the distance. So if my camera is always above the ground and the player is now below it surely I shouldn't be able to see him.

I then thought that maybe the ground was invisible as it was being textured incorrectly so I put new textures in the data file and linked them. Alas, still no terrain.

So this all leads me to thinking that there are two possible reasons why I can't see my ground. Either it is too small to see, or it is just not there.

For the first problem I have tried all sorts of scaling for the terrain to make it visible, from the very small to the very large. Then I noticed that if I scale the y axis without updating the y coord or the player then the camera shoots off skyward with the terrain  leaving the box below. So the terrain must be there as it is having an effect on the environment.

So I must conclude that the terrain is invisible. Why? Here is the texture code for the terrain;

      // generate a terrain texture with 2 textures
      ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
            heightMap);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/green.png")), -128, 0, 128);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/red.png")), 0, 128, 255);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/blue.png")), 128, 255,
            384);
      pt.createTexture(32);
      
      // assign the texture to the terrain
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
            Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
      ts.setTexture(t1, 0);

      tb.setRenderState(ts);



This worked perfectly when I pulled it out of the flagrush tutorial. Only after I changed the terrain to ImageBasedHeightMap have I never seen it. Should this code not work in this case?

I have been stuck on this for 2 days nearly now lol.

Thanks

Neilos

Here is the full code.

package test;


import java.net.URL;
import java.util.HashMap;

import javax.swing.ImageIcon;

import jmetest.renderer.TestSkybox;
import jmetest.terrain.TestTerrain;

import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.light.DirectionalLight;
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.Skybox;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
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.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

public class testTerrain extends BaseGame{

   //terrain block for the terrain
   private TerrainBlock tb;
   //the skybox
   private Skybox skybox;
   //the player
    private Node player;
    //the chase camera
    private ChaseCamera chaser;
   
   //timer for the game to obtain framerate
   protected Timer timer;
   //camera for the game
   private Camera cam;
   //variables for storing display properties
   private int width, height, depth, freq;
   //boolean for fullscreen
   private boolean fullscreen;
   //the root node of the scene graph
   private Node scene;
   //TextureState to show the monkey on the sphere.
   private TextureState ts;
   
   //entry point
   public static void main(String[] args) {
      
      //create and initialise new application
      testTerrain app = new testTerrain();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      app.start();

   }

   @Override
   /**
   * clean up the textures.
   *
   */
   protected void cleanup() {
         ts.deleteAll();
      
   }

   @Override
   protected void initGame() {
      
      scene = new Node("Scene graph node");
      /** Create a ZBuffer to display pixels closest to the camera above farther ones.  */
       ZBufferState buf = display.getRenderer().createZBufferState();
       buf.setEnabled(true);
       buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
       scene.setRenderState(buf);
      //Add terrain to the scene
        buildTerrain();
      //Light the world
       buildLighting();
       //Add the skybox
       buildSkyBox();
       //Add the player
       buildPlayer();
       //Add the chase camera
       buildChaseCamera();
 
      // update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
      
      CullState cs = display.getRenderer().createCullState();
      cs.setCullFace(CullState.Face.Back);
      scene.setRenderState(cs);
      
   }

   @Override
   protected void initSystem() {
      
      //store the display properties information
      width = this.settings.getWidth();
      height = this.settings.getHeight();
      depth = this.settings.getDepth();
      freq = this.settings.getFrequency();
      fullscreen = this.settings.isFullscreen();

      
      //chech that display properties work, if not then exit
      try {
            display = DisplaySystem.getDisplaySystem(this.settings.getRenderer());
            display.createWindow(width, height, depth, freq, fullscreen);
         
            cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
            e.printStackTrace();
            System.exit(1);
      }
      
      //set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black);
      
      //initialize the camera
      cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
      Vector3f loc = new Vector3f(0.0f, 0.0f, 0.0f);
      Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(0.0f, 0.0f, 0.0f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
      cam.update();
      
      display.getRenderer().setCamera(cam);
      
      /** Get a high resolution timer for FPS updates. */
      timer = Timer.getTimer();

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

   @Override
   /**
   * will be called if the resolution changes
   *
   */
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
      
   }

   @Override
   /**
   * draws the scene graph
   */
   protected void render(float interpolation) {
      
      //Clear the screen
      display.getRenderer().clearBuffers();
      
      display.getRenderer().draw(scene);
      
   }

   @Override
   /**
   * During an update we only look for the escape button and update the timer
   * to get the framerate.
   */
   protected void update(float interpolation) {
      
      //update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
      //update the camera
      chaser.update(interpolation);
      
        //We don't want the chase camera to go below the world, so always keep
        //it 2 units above the level.
        if(cam.getLocation().y < (tb.getHeight(cam.getLocation())+2)) {
            cam.getLocation().y = tb.getHeight(cam.getLocation()) + 2;
            cam.update();
        }
      
      //if escape was pressed, we exit      
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }
      
      //we want to keep the skybox around our eyes, so move it with
      //the camera
      skybox.setLocalTranslation(cam.getLocation());
      
      //make sure that if the player left the level we don't crash. When we add collisions,
      //the fence will do its job and keep the player inside.
      float characterMinHeight = tb.getHeight(player
                      .getLocalTranslation())+((BoundingBox)player.getWorldBound()).yExtent;
      if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
                  player.getLocalTranslation().y = characterMinHeight;
      }
      
        //Because we are changing the scene (moving the skybox and player) we need to update
        //the graph.
        scene.updateGeometricState(interpolation, true);
      
   }
   
   private void buildTerrain() {
      
      URL heightMapImage = testTerrain.class.getClassLoader().getResource("data/heightmap.png");
      
      ImageBasedHeightMap heightMap = new ImageBasedHeightMap(
            new ImageIcon(heightMapImage).getImage()
            );
       
      // Scale the data
      Vector3f terrainScale = new Vector3f(10000.0f, 2.0f, 10000.0f);
      // create a terrainblock
      tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
            heightMap.getHeightMap(), new Vector3f(0, 0, 0));

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

      // generate a terrain texture with 2 textures
      ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
            heightMap);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/green.png")), -128, 0, 128);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/red.png")), 0, 128, 255);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/blue.png")), 128, 255,
            384);
      pt.createTexture(32);
      
      // assign the texture to the terrain
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
            Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
      ts.setTexture(t1, 0);

      tb.setRenderState(ts);
      
   }
   
   
   /**
    * creates a light for the terrain.
    */
   private void buildLighting() {
      /** Set up a basic, default light. */
       DirectionalLight light = new DirectionalLight();
       light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
       light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
       light.setDirection(new Vector3f(1,-1,0));
       light.setEnabled(true);

         /** Attach the light to a lightState and the lightState to rootNode. */
       LightState lightState = display.getRenderer().createLightState();
       lightState.setEnabled(true);
       lightState.attach(light);
       scene.setRenderState(lightState);
   }
   
    /**
     * buildSkyBox creates a new skybox object with all the proper textures. The
     * textures used are the standard skybox textures from all the tests.
     *
     */
   private void buildSkyBox() {
        skybox = new Skybox("skybox", 10, 10, 10);

        Texture north = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/north.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture south = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/south.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture east = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/east.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture west = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/west.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture up = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/top.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
        Texture down = TextureManager.loadTexture(
            TestSkybox.class.getClassLoader().getResource(
            "jmetest/data/texture/bottom.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);

        skybox.setTexture(Skybox.Face.North, north);
        skybox.setTexture(Skybox.Face.West, west);
        skybox.setTexture(Skybox.Face.South, south);
        skybox.setTexture(Skybox.Face.East, east);
        skybox.setTexture(Skybox.Face.Up, up);
        skybox.setTexture(Skybox.Face.Down, down);
        skybox.preloadTextures();
        scene.attachChild(skybox);
   }
   
   private void buildPlayer() {
        //box stand in
        Box b = new Box("box", new Vector3f(), 0.35f,0.25f,0.5f);
        b.setModelBound(new BoundingBox());
        b.updateModelBound();
 
        player = new Node("Player Node");
        player.setLocalTranslation(new Vector3f(0, 0, 0));
        scene.attachChild(player);
        player.attachChild(b);
        player.updateWorldBound();
   }
   
   
   private void buildChaseCamera() {
           Vector3f targetOffset = new Vector3f();
           targetOffset.y = ((BoundingBox) player.getWorldBound()).yExtent * 1.5f;
           HashMap props = new HashMap();
           props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "6");
           props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
           props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);
           props.put(ThirdPersonMouseLook.PROP_MAXASCENT, ""+45 * FastMath.DEG_TO_RAD);
           props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(5, 0, 30 * FastMath.DEG_TO_RAD));
           props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);
           chaser = new ChaseCamera(cam, player, props);
           chaser.setMaxDistance(8);
           chaser.setMinDistance(2);
   }
   
}

The problem might be that you didn't attach the terrain to your scene.





something like

scene.attachChild(terrain);


can help there.

Ahh, ok. I understand now.



Well that was a fun experience and a good bit of learning dissecting the code.



Trust it to have been something simple though that I hadn't even thought of  :stuck_out_tongue:



Thanks for your help



Neilos

You won't believe how often I forgot to add my spatial to the graph and think of everything but the obvious… :smiley: