I managed in getting the indexes at the right places.
Now I’m able to make my terrain visible, and so I did.
But, now I have another problem.
Here’s an image of the terrain: (top view)
Every time when I start the game and generate a terrain, there are some not-random heights like you see in the image. I always get an oblique line of low heights (the canyon) .
This is the tutorial I used: Realistic terrain in 130 lines
And the code of that tutorial: playfuljs-demos/index.html at gh-pages · hunterloftis/playfuljs-demos · GitHub
And here’s my own class that generates the terrain:
package terrain;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.scene.Geometry;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
public class TerrainGenerator {
private static final int TERRAIN_WIDTH = 100;
private static final int TERRAIN_HEIGHT = 100;
private static final float DEFAULT_HEIGHT = 1.0f;
private static final int DETAIL = 6;
private static final int SIZE = (int) Math.pow(2, DETAIL) + 1;
private static final int MAX = SIZE - 1;
private static final float ROUGHNESS = 0.1f;
private float[] heights;
private AssetManager assetManager;
public TerrainGenerator(AssetManager assetManager) {
this.assetManager = assetManager;
}
public float get(int x, int y) {
try {
if (x < 0 || x > MAX || y < 0 || y > MAX) {
return -1f;
}
return heights[x + SIZE * y];
} catch (Exception ex) {
System.out.println("Error! > " + ex.getMessage());
}
return 0;
}
public void set(int x, int y, float val) {
heights[x + SIZE * y] = val;
}
public void initArray() {
heights = new float[SIZE * SIZE];
set(0, 0, MAX);
set(MAX, 0, MAX / 2);
set(MAX, MAX, 0);
set(0, MAX, MAX / 2);
System.out.println("Size of heights array: " + heights.length);
}
public void generateTerrain() {
initArray();
divide(MAX);
}
public void divide(float size) {
System.out.println("d " + size);
int x, y, half = (int) (size / 2);
float scale = ROUGHNESS * size;
if(half < 1f) {
return;
}
for (y = half; y < MAX; y += size) {
for (x = half; x < MAX; x += size) {
float random = (float) Math.random();
square(x, y, half, random * scale * 2 - scale);
}
}
for (y = 0; y <= MAX; y += half) {
for (x = (int) ((y + half) % size); x <= MAX; x += size) {
float random = (float) Math.random();
diamond(x, y, half, random * scale * 2 - scale);
}
}
divide(size / 2); // Cycle
}
public float average(float[] values) {
float[] valid = new float[values.length];
// check valid values
for (int i = 0; i < values.length; i++) {
if (values[i] != -1.0f) {
valid[i] = values[i];
}
}
// calculate average
float total = 0f;
for (int n = 0; n < valid.length; n++) {
total += valid[n];
}
return total / valid.length;
}
public void square(int x, int y, int size, float offset) {
float ave = average(new float[]{
get(x - size, y - size), // upper left
get(x + size, y - size), // upper right
get(x + size, y + size), // lower right
get(x - size, y + size) // lower left
});
set(x, y, ave + offset);
}
public void diamond(int x, int y, int size, float offset) {
float ave = average(new float[]{
get(x, y - size), // top
get(x + size, y), // right
get(x, y + size), // bottom
get(x - size, y) // left
});
set(x, y, ave + offset);
}
public void debug() {
System.out.println("Open terrain debug window");
JFrame frm = new JFrame("Terrain debug map");
frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frm.setSize(TERRAIN_WIDTH * 10, TERRAIN_HEIGHT * 10);
frm.setLocationRelativeTo(null);
TerrainMapPanel panel = new TerrainMapPanel(heights, SIZE, MAX);
frm.setLayout(new BorderLayout());
frm.add(panel, BorderLayout.CENTER);
frm.setVisible(true);
}
private Color getColor(int x, int y) {
return Color.red;
}
/**
* This method is only to get an object to render
*/
public Geometry getGeneratedTerrain() {
Terrain terr = new Terrain();
terr.setHeights(heights, MAX);
Geometry geom = new Geometry("terrain", terr);
Material mat_terrain = new Material(assetManager,
"Common/MatDefs/Terrain/Terrain.j3md");
mat_terrain.setTexture("Alpha", assetManager.loadTexture(
"Textures/Terrain/splat/alphamap.png"));
Texture grass = assetManager.loadTexture(
"Textures/Terrain/splat/grass.png");
grass.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex1", grass);
mat_terrain.setFloat("Tex1Scale", 64f);
Texture dirt = assetManager.loadTexture(
"Textures/Terrain/splat/dirt.png");
dirt.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex2", dirt);
mat_terrain.setFloat("Tex2Scale", 32f);
Texture rock = assetManager.loadTexture(
"Textures/Terrain/splat/rocks.png");
rock.setWrap(WrapMode.Repeat);
mat_terrain.setTexture("Tex3", rock);
mat_terrain.setFloat("Tex3Scale", 128f);
geom.setMaterial(mat_terrain);
geom.setLocalTranslation(-16f, -10f, 0);
mat_terrain.getAdditionalRenderState().setWireframe(true);
return geom;
}
}