Converting to TerrainPage

Hi,



I’m having some troubles trying to convert from using TerrainBlock to TerrainPage.



I’ve tried creating the TerrainPage the same way as shown in TerrainDemo:

ImageBasedHeightMap heightMap = new ImageBasedHeightMap(
   new ImageIcon(mapImage).getImage());

TerrainPage terrainPage = new TerrainPage("Terrain", 33,
      heightMap.getSize(), mapScale, heightMap.getHeightMap(), false);



which resulted in: com.jme.system.JmeException: size given: 128 Terrain page sizes may only be (2^N + 1)

So I tried:

TerrainPage terrainPage = new TerrainPage(Terrain", 33,
      heightMap.getSize()+1, mapScale, heightMap.getHeightMap(), false);



which resulted in: java.lang.ArrayIndexOutOfBoundsException: 16384

So I tried:

TerrainPage terrainPage = new TerrainPage(Terrain", 33,
      3, mapScale, heightMap.getHeightMap(), false);



which resulted in that no terrain was shown at all, allthough there wasn't any problems starting the application.


Thanks!

You can’t just fudge and put in a “3” there, it throws off the whole map :slight_smile: How big is this terrain page you want, that it should throw an exception like that?



Show me the code where you create the heigthMap object, mapScale object, and I’ll try to see what’s happening.

Ok, I have really no idea of what TerrainPage is/does other than it splits up a TerrainBlock allowing it to be culled :slight_smile:



Here’s my method for loading a map:


/**
 * Loads a map from the map directory.
 * @param map The name of the folder where all the map data/files
 * are located. Note: not the whole path.
 * @param display
 * @return A Map object loaded from the passed filename.
 */
public Map loadMap(String mapName, DisplaySystem display) {
    // This grayscale image holds the height map.
   URL mapImage = getResource(MAP_DIR + mapName + "/" +
         MapProtocol.HEIGHTMAP_IMAGE);
   
   // From this file we'll load spawn points, map scale and fog color.
   URL config = getResource(MAP_DIR + mapName + "/" +
         MapProtocol.CONFIG_FILE);
   
   // From this file we'll load our texture settings.
   URL textureConfig = getResource(MAP_DIR + mapName + "/" +
         MapProtocol.TEXTURE_FILE);
   
   ArrayList spawnPoints = new ArrayList();
   ColorRGBA fogColor = null;
   Vector3f mapScale = null;
   
   /*** Start reading map config ***/
   try {
      String line;   
      BufferedReader reader = getBufferedReader(config);
      
      // Loop as long as there's information on the line
      while ( ( line = reader.readLine() ) != null) {
         String description;
         StringTokenizer tokenizer = new StringTokenizer(line, ",");
         description = tokenizer.nextToken();
         
         if (description.equals(MapProtocol.SPAWN_POINT)) {
            float x = Float.parseFloat( tokenizer.nextToken() );
            float y = Float.parseFloat( tokenizer.nextToken() );
            float z = Float.parseFloat( tokenizer.nextToken() );
            spawnPoints.add( new Vector3f(x, y, z) );
         }
         
         else if (description.equals(MapProtocol.MAP_SCALE)) {
            float x = Float.parseFloat( tokenizer.nextToken() );
            float y = Float.parseFloat( tokenizer.nextToken() );
            float z = Float.parseFloat( tokenizer.nextToken() );
            mapScale = new Vector3f(x, y, z);
         }
         
         else if (description.equals(MapProtocol.FOG_COLOR)) {
            float r = Float.parseFloat( tokenizer.nextToken() );
            float g = Float.parseFloat( tokenizer.nextToken() );
            float b = Float.parseFloat( tokenizer.nextToken() );
            float a = Float.parseFloat( tokenizer.nextToken() );
            fogColor = new ColorRGBA(r,g,b,a);
         }
      }
      
      reader.close();
   }
   // Catch any exceptions
   catch (FileNotFoundException e) {
      System.out.println("Map " + mapName + " could not be found");
   }
   catch (IOException e) {
      System.out.println("Map could not be loaded: " + e.getMessage());
   }
   /*** End reading map config ***/
   
   /*** Start creating terrain ***/
    // Create an image height map based on the gray scale of our image.
    ImageBasedHeightMap heightMap = new ImageBasedHeightMap(
            new ImageIcon(mapImage).getImage());
   
    // Create a terrain block from the image's grey scale     
    /*TerrainPage terrainPage = new TerrainPage("Map", heightMap.getSize(), mapScale,
          heightMap.getHeightMap(),
         new Vector3f(0, 0, 0), false);*/
   
   TerrainPage terrainPage = new TerrainPage("Map", 33,
         heightMap.getSize(), mapScale, heightMap.getHeightMap(), false);
   
    System.out.println(heightMap.getSize());
    /** End creating terrain **/
   
    terrainPage.setDetailTexture(1, 16);
   
    ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
   
   /*** Start reading texture config ***/
   try {
      String line;   
      BufferedReader reader = getBufferedReader(textureConfig);
      
      // Loop as long as there's information on the line
      while ( ( line = reader.readLine() ) != null) {
         String description;
         StringTokenizer tokenizer = new StringTokenizer(line, ",");
         description = tokenizer.nextToken();
         
         if (description.equals(MapProtocol.TEXTURE)) {
            URL texture = getResource(TEXTURE_DIR+tokenizer.nextToken());
            int start = Integer.parseInt( tokenizer.nextToken() );
            int conc = Integer.parseInt( tokenizer.nextToken() );
            int end = Integer.parseInt( tokenizer.nextToken() );
              pt.addTexture(new ImageIcon(texture), start, conc, end);
         }
         
         else if (description.equals(MapProtocol.DETAIL)) {               
            URL detail = getResource(TEXTURE_DIR+tokenizer.nextToken());
              pt.createTexture(512);
              TextureState ts = display.getRenderer().createTextureState();
              ts.setEnabled(true);
             
              Texture t1 = TextureManager.loadTexture(
                  pt.getImageIcon().getImage(),
                  Texture.MM_LINEAR_LINEAR,
                  Texture.FM_LINEAR,
                  true,
                  true);


              Texture t2 = TextureManager.loadTexture(detail,
                                                      Texture.MM_LINEAR_LINEAR,
                                                      Texture.FM_LINEAR,
                                                      true);
              ts.setTexture(t2, 1);
              ts.setTexture(t1, 0);
             
              t2.setWrap(Texture.WM_WRAP_S_WRAP_T);

              t2.setApply(Texture.AM_COMBINE);
              t2.setCombineFuncRGB(Texture.ACF_ADD_SIGNED);
              t2.setCombineSrc0RGB(Texture.ACS_TEXTURE);
              t2.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
              t2.setCombineSrc1RGB(Texture.ACS_PREVIOUS);
              t2.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
              t2.setCombineScaleRGB(1.0f);
              terrainPage.setRenderState(ts);
             
              // Give the terrain a bounding box
              terrainPage.setModelBound(new BoundingBox());
              terrainPage.updateModelBound();
              terrainPage.updateWorldBound();
         }
      }
      
      reader.close();
   }
   // Catch any exceptions
   catch (FileNotFoundException e) {
      System.out.println("Map " + mapName + " could not be found");
   }
   catch (IOException e) {
      System.out.println("Map could not be loaded: " + e.getMessage());
   }
   /*** End reading texture config ***/
    return new Map(mapName, spawnPoints, fogColor, terrainPage);
}



map.cfg looks like this:

scale,10,2,10
spawn,200,500,100
spawn,200,500,150
fogcolor,0.5,0.4,0.5,0.5



textures.cfg looks like this:

texture,grassb.png,-128,0,128
texture,dirt.jpg,0,128,255
texture,highest.jpg,128,255,384
detail,detail.jpg



And the heightmap image is 128*128 pixels.

Ok, here you are experiencing some of the… character… of my terrain stuff. Terrain Block requires a heightmap of 2^N while terrain page requires 2 ^ N + 1. So, that’s why you got the first error, so when you added 1 to the size (in your second attempt) you fooled the terrain page into thinking you had a 2 ^ N + 1 heightmap, but when it tried to access those edge values they didn’t exist in the heightmap itself… thus the exception.



It look like you are loading the heightmap from an image. I would recommend adding one row and one column to the image in an image program, most will even blend the color values for you on.

"mojomonk" wrote:
It look like you are loading the heightmap from an image. I would recommend adding one row and one column to the image in an image program, most will even blend the color values for you on.
that or simply resize the image to the proper size.

Resizing the image to 129*129 pixels worked!



Thanks!