TerrainGrid not displayed

Hi,



im programming a network based simulation game. So the terrain is downloaded from the sever in 64x64 chunks (as hightmap). This hightmap gets interpolated so i have 128x128 and i used Terrain Grid to display the terrain. All is like i want so far. With one Chunk



Now i want to display multiple chunks. Depending on the Kamera Position the chunks are loaded from the server and added to a custom node. But I can’t see anything. I see the polygon count getting bigger. I added a cube to the scene. That is displayed correctly.



Any suggestions?



(tile = chunk - we had to refactor)







[java]package conveyance.client.map;



import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.renderer.Camera;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Spatial;

import com.jme3.scene.control.AbstractControl;

import com.jme3.scene.control.Control;

import com.jme3.terrain.heightmap.HeightMap;

import conveyance.common.messages.MapUpdate;

import conveyance.common.types.TileCoordinate;

import java.util.List;



/**

*

  • @author Drummer

    /

    public class NetworkTerrainControl extends AbstractControl implements TileProvider.TileupdateListener{

    List<Camera> cameras;

    float distanceInMemory;

    float sqrDistanceInMemory;

    TileProvider tileprovider;

    TileBasedTerrain terrain;



    public NetworkTerrainControl(TileProvider tileprovider, List<Camera> cameras, float distanceInMemory) {

    this.tileprovider = tileprovider;

    this.cameras = cameras;

    this.distanceInMemory = distanceInMemory;

    this.sqrDistanceInMemory = distanceInMemory
    distanceInMemory;

    }



    private NetworkTerrainControl(NetworkTerrainControl n) {

    this.terrain = n.terrain;

    this.tileprovider = n.tileprovider;

    this.cameras = n.cameras;

    this.distanceInMemory = n.distanceInMemory;

    this.sqrDistanceInMemory = n.sqrDistanceInMemory;

    }



    @Override

    protected void controlUpdate(float tpf) {

    for (Camera camera : cameras) {

    Vector3f cloc = camera.getLocation().clone();

    cloc.y = 0.0f;

    int x = (int)cloc.x;

    int z = (int)cloc.z;

    int dist = (int)FastMath.ceil(distanceInMemory);

    for (int i = x-dist; i < x+dist; i++) {

    for (int j = z-dist; j < z+dist; j++) {

    if (!terrain.containsQuad(i, j)

    && i>=0 && j>=0) {

    tileprovider.requestTile(new TileCoordinate(i, j));

    }

    }



    //TODO remove tiles

    //Math.floor(-0.5);

    }

    }

    }



    public void tileUpdate(HeightMap h, TileCoordinate t) {

    terrain.addQuad(h, t.getX(), t.getZ());

    }



    @Override

    protected void controlRender(RenderManager rm, ViewPort vp) {

    }



    public Control cloneForSpatial(Spatial spatial) {

    NetworkTerrainControl n = new NetworkTerrainControl(this);

    setSpatial(spatial);

    n.terrain = (TileBasedTerrain)spatial;

    return n;

    }



    @Override

    public void setSpatial(Spatial spatial) {

    if (!(spatial instanceof TileBasedTerrain))

    throw new IllegalArgumentException("only for TileBasedTerrain");



    super.setSpatial(spatial);

    terrain = (TileBasedTerrain)spatial;

    }

    }[/java]



    [java]

    package conveyance.client.map;



    import com.jme3.material.Material;

    import com.jme3.math.Vector3f;

    import com.jme3.renderer.Camera;

    import com.jme3.scene.Node;

    import com.jme3.terrain.geomipmap.TerrainLodControl;

    import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;

    import com.jme3.terrain.heightmap.HeightMap;

    import java.util.HashMap;

    import java.util.List;



    /**

    *
  • @author Drummer

    */

    public class TileBasedTerrain extends Node{



    int patchSize;

    int size;

    Vector3f scale;

    HashMap<Long, TileBasedTerrainQuad> quads; //Key: concatinated x and y coordinates of the tile



    float lodMultiplicator;

    List<Camera> cameras;



    Material material;





    public TileBasedTerrain(String name, int patchSize, int size, Vector3f scale, float lodMultiplicator, List<Camera> cameras) {

    super(name);

    quads = new HashMap<Long, TileBasedTerrainQuad>();



    this.lodMultiplicator = lodMultiplicator;

    this.cameras = cameras;



    }





    public TileBasedTerrainQuad getQuad(int x, int z) {

    return quads.get((long)x<<Integer.SIZE +z);

    }



    public void addQuad(HeightMap h, int x, int z) {

    TileBasedTerrainQuad q = new TileBasedTerrainQuad(x, z,

    "terrain (" + x + ", " + z + ")",

    patchSize, size, scale, h.getHeightMap());

    quads.put((long)x<<Integer.SIZE +z, q);



    q.setMaterial(material);



    TerrainLodControl control = new TerrainLodControl(q, cameras);

    control.setLodCalculator(new DistanceLodCalculator(patchSize, lodMultiplicator)); // patch size, and a multiplier

    q.addControl(control);

    attachChild(q);

    }



    public void removeQuad(int x, int z) {

    TileBasedTerrainQuad q = quads.remove((long)x<<Integer.SIZE +z);

    if (q != null)

    detachChild(q);

    }



    public boolean containsQuad(int x, int z) {

    return quads.containsKey((long)x<<Integer.SIZE +z);

    }





    public HashMap<Long, TileBasedTerrainQuad> getQuads() {

    return quads;

    }



    @Override

    public void setMaterial(Material mat) {

    material = mat;

    super.setMaterial(mat);

    }

    }

    [/java]



    [java]package conveyance.client.map;



    import com.jme3.math.Vector3f;

    import com.jme3.scene.Node;

    import com.jme3.terrain.geomipmap.TerrainQuad;



    /**

    *
  • @author Drummer

    */

    public class TileBasedTerrainQuad extends TerrainQuad{



    private final int positionX;

    private final int positionZ;



    public TileBasedTerrainQuad(int x, int z, String name, int patchSize, int size, Vector3f scale, float[] heightMap) {

    super(name, patchSize, size, scale, heightMap);

    this.positionX = x;

    this.positionZ = z;



    setLocalTranslation(x, 0, z);

    }



    @Override

    protected TerrainQuad findDownQuad() {

    Node parent = getParent();

    if (parent == null)

    return null;



    if (!(parent instanceof TileBasedTerrain ))

    return super.findDownQuad();



    TileBasedTerrain t = (TileBasedTerrain)parent;

    return t.getQuad(positionX, positionZ - 1);

    }



    @Override

    protected TerrainQuad findLeftQuad() {

    Node parent = getParent();

    if (parent == null)

    return null;



    if (!(parent instanceof TileBasedTerrain ))

    return super.findLeftQuad();



    TileBasedTerrain t = (TileBasedTerrain)parent;

    return t.getQuad(positionX + 1, positionZ);

    }



    @Override

    protected TerrainQuad findRightQuad() {

    Node parent = getParent();

    if (parent == null)

    return null;



    if (!(parent instanceof TileBasedTerrain ))

    return super.findRightQuad();



    TileBasedTerrain t = (TileBasedTerrain)parent;

    return t.getQuad(positionX - 1, positionZ);

    }



    @Override

    protected TerrainQuad findTopQuad() {

    Node parent = getParent();

    if (parent == null)

    return null;



    if (!(parent instanceof TileBasedTerrain ))

    return super.findTopQuad();



    TileBasedTerrain t = (TileBasedTerrain)parent;

    return t.getQuad(positionX, positionZ + 1);

    }



    }[/java]

Why not just use TerrainGrid? It already loads tiles off a network.

Because the terrainGrid displays only 4 Tiles at a time. For a better overview and better network efficiency I want do display more than 4 tiles.

Well I can’t dig into all of your code, but if the polygons are there in the count but not rendering, then it could be that there is no alpha map, or that alpha map is entirely transparent: won’t render any textures.

Try applying a wireframe texture to see what is there.

@michael-eckes said:
Because the terrainGrid displays only 4 Tiles at a time. For a better overview and better network efficiency I want do display more than 4 tiles.

No you don't :) If you need an overview the technique used by TerrainGrid is not feasible, create another terrain that you switch to when you zoom out. TerrainGrid is for loading terrain, displaying too many Terrain tiles would be too much overhead.

I don’t want to use it for an overview map.



I want to display ~ 3 by 3 tiles arround the camera. So you can see a little bit more of the terrain.



I am using only wireframe material at the moment.



eventually we’ll switch to biggerchunks so wie can use the Grid,

well all I can think of is that the tiles you are loading are really small, way far away, you are underneath and they are being backfaced-culled… not sure what else.

I also have not been able to make terraingrid work. I can’t get the tiles to fade in from behind the far clipping range. I tried many different settings, scales etc., but no matter what I do they keep plopping up and disappearing while still in sight.



I get the same problem in the demos. Maybe it’s related.

One tile should be so big that it goes til the horizon.

Well he is using custom code and not using TerrainGrid directly. I don’t see any popping issues androlo, which test do you see it in?

@normen

@sploreg

I just checked TerrainGridTileLoader.java again, for example. It’s pretty easy to describe the problem.



When I start moving the camera forward, no terrain is being added. It’s as if there’s no grid, only the visible tile. After some time a new tile “pops” up, instead of it being added outside range. It then works for some time, as I keep moving forward, and I can see terrain being culled. Then it stops being culled again (as if the terrain ends), and after some time there’s another pop, etc.



I tried scaling the terrain up 10 times. Same problem.



I got an ok graphics card (Radeon HD 6k-something.)

yea still not seeing that. And I’m not entirely clear what you are describing.

There are only ever 4 tiles loaded at once (each one a full TerrainQuad tree)

What you describe isn’t possible when one tile is going til’ the horizon.

@sploreg

@normen

Heh maybe not a good description after all. I made a vid instead to show. I think it’s from terraingridtileloader test.



I was not sure how to count tho, but I think I understand now. This test uses a maximum visible size of 257, scaled 2 times by default. I scaled it 10 times in the vid and assumed it would work.



There are four tiles in the scene, so i figured there should be no problems staying outside the culling range (1000). The terrain should be 2x257x10 in each dir I thought, counting four 257 tiles scaled by 2x, but i should have calculated the entire terrain as being 257 scaled 2 times?



That would make terrain about 2570 units squared (using 10x scale), which gives a “radius” of about 1300 in each dir, and half of that is about 750 (which is where the terrain-grid goes to work).



When scaling it 15 times, the popping goes away (as expected). Still not sure I fully get it tho. :slight_smile:



http://www.youtube.com/watch?v=YN4faEACZBM

Well what you see in the video might also be due to the fact that you race so quickly across one terrain tile so loading the next takes too long… At any instance its only 4 tiles, so the size of one tile should be > viewport distance * 2 so that the terrain is loaded before it gets into view.

yea what you saw there was just it taking a while to load in the tile. I guess some pre-cacheing or aggressive cacheing might be needed for the first few tiles.

Got it now, thanks :slight_smile: I forgot tiles are loaded at half the tile size.



Time to start making some properly scaled scenes.