Saving terraingrid tiles

Hi, I’ve recently tried out the TerrainGrid, and really like it. I’m currently working on an in-game terrain editor, which seems to work quite good.



Problem: If I move the camera away from the edited part, the tile gets unloaded and is lost.



Is there a way to automatically save tiles that are unloaded to the hard drive and reload these tiles whenever the camera gets in range again?



I guess what I’m trying to do needs to happen inside an object implementing “TerrainGridListener”, but I’m not shure what to write in there.

TerrainGridListener alerts you when a tile is loaded and unloaded. Just implement it in the object which has the data, and on unload save your tile.

Thanks, only it is rather the saving part that is the problem for me, because I’ve never worked with saving in JME before.

theres some commented out code to generate the j3o files for the tiles test in one of the other terrain grid tests.

Ok, my program just saved some files in the heightmap folder. How do I now configure my TerrainGrid to use these files when loading tiles?



The code I used to create the files:

[java]public class TerrainGridSaver implements TerrainGridListener {



@Override

public void gridMoved(Vector3f newCenter) {

// TODO Auto-generated method stub



}



@Override

public void tileAttached(Vector3f cell, TerrainQuad quad) {

// TODO Auto-generated method stub



}



@Override

public void tileDetached(Vector3f cell, TerrainQuad quad) {

BinaryExporter exporter = BinaryExporter.getInstance();

File file = new File("assets/courses/test/heightmap/terrain_" + Math.round(cell.x) + "" + Math.round(cell.y) + "" + Math.round(cell.z) + ".j3o");

try {

exporter.save(quad, file);

} catch (IOException ex) {

Logger.getLogger("").log(Level.SEVERE, "Failed to save terrain tile!", ex);

}

}



}

[/java]

Yay snippets!



[snippet id=“19”]



Edit: oops, you seem to have answered your own question before I could :slight_smile:

Yes, it seems to be working like it should! Many thanks once again.

Hmmm… I’m getting some strange behavior once again, the terrain is not saving in the correct positions. This is my current TerrainGridListener.

Is the way I generate the file names correct?



[java]package be.werner291.racer.editor;



import java.io.File;

import java.io.IOException;

import java.util.logging.Level;

import java.util.logging.Logger;



import com.jme3.export.binary.BinaryExporter;

import com.jme3.math.Vector3f;

import com.jme3.terrain.geomipmap.TerrainGridListener;

import com.jme3.terrain.geomipmap.TerrainQuad;

import com.jme3.terrain.heightmap.AbstractHeightMap;



public class TerrainGridSaver implements TerrainGridListener {



@Override

public void gridMoved(Vector3f newCenter) {

// TODO Auto-generated method stub



}



@Override

public void tileAttached(Vector3f cell, TerrainQuad quad) {

// TODO Auto-generated method stub



}



@Override

public void tileDetached(Vector3f cell, TerrainQuad quad) {

BinaryExporter exporter = BinaryExporter.getInstance();

File file = new File(“assets/courses/test/heightmap/terrain_” + (long)(Math.floor(cell.x)) + “" + (long)(Math.floor(cell.y)) + "” + (long)(Math.floor(cell.z)) + “.j3o”);

try {

exporter.save(quad, file);

} catch (IOException ex) {

Logger.getLogger("").log(Level.SEVERE, “Failed to save terrain tile!”, ex);

}

}



}

[/java]

You probably want (long)(Math.floor(cell.z)), instead of cell.y.

It is a bit confusing, but the cells are in the x-z plane with y being up. I will change the tileDetached/attached methods to pass in a Vector2f. Vector3f makes no sense for them.

I will change the tileDetached/attached methods to pass in a Vector2f. Vector3f makes no sense for them.

It does make sense to avoid new Vector2f() / 3f() objects when you must convert cell coordinates to world coordinates all the time.

In the first TerrainGrid implementation, it was a Vector2f, and I truely prefer the new way with Vector3f. Makes the code less confuse. Also I remember @Anthyon wanted to use Y for something else in the future...

Ah right, good call ozonegrif. The Y could be used for a cave roof system, or something similar, where you will have terrains at various heights.

The order of the x,y and z values seem to be to be correct, because if I change it the terrain gets cut up and spread all over the place.



I rather think that this behavior is caused by “Math.floor()”, because when I make hills, the hills are rather shifted than cut up. Is Math.floor() the right function to use?



EDIT: Currently, math.ceil() seems to give a good result.

Math.floor() won’t work for negative cells.



Use this :

[java] /**

  • Returns the floorModulo, useful with negative numbers

    *
  • @param fValue
  •        The value to modulo<br />
    
  • @param fMod
  •        The modulo<br />
    
  • @return (float)

    */

    public static float floorMod( float fValue, float fMod )

    {

    return (fValue - (fMod * (float) floor( fValue / fMod )));

    }[/java]

I do have a similar problem, I managed to implement the save/load part, but with this weird behavior; whenever a tile is saved, when reloaded, it doesn’t appear where it used to be. For example, I load the application, modify the grid cell right where the camera is looking at, then move to the left until the tile get’s detached and saved, close the application, then restart it again; the tiles get loaded, but the modification to the terrain gets shifted around. I don’t understand.