Thank you for the quick reply, here is the code of the terrain mesh generation, ignore the first constructor, the second one does apply 1 color to the whole terrain (temporarily), i hope you find
what we are searching for:
package terrain;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.BufferUtils;
import java.awt.Color;
/**
* Generates a mesh where every triangle got there own
* corner points without sharing them with other triangles.
* The result is a flat shaded mesh.
*
* @author Simon Pointner
*/
public class FlatShadedTerrain extends Geometry {
float[][] heightmap;
int size;
private static final int SCALE = 5;
/*
* Generates the island shaped flat shaded mesh
*
* @param heightmap the heightmap used for building the mesh
* @param size the sidelength the heightmap got
*/
public FlatShadedTerrain(float[][] heightmap, int size) {
this.mesh = new Mesh();
this.heightmap = heightmap;
this.size = size;
generateMesh();
this.mesh.updateBound();
}
/*
* Generates the island shaped flat shaded mesh with the given
* color for all vertices
*
* @param heightmap the heightmap used for building the mesh
* @param size the sidelength the heightmap got
* @param color the color getting applied
*/
public FlatShadedTerrain(float[][] heightmap, int size, Color color) {
this.mesh = new Mesh();
this.heightmap = heightmap;
this.size = size;
generateMesh();
this.mesh.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(setVertexColors(color)));
this.mesh.updateBound();
}
/*
* Generates all needed values for and fits them together
* into the flat shaded mesh.
*/
private void generateMesh() {
/*
* Calculate the amount of points needed to generate
* each triangles corners inside the mesh.
* Each square got 6 points.
*/
int points = (size - 1) * (size - 1) * 6;
/*
* Those variables store the vertices, indexes and normals
* of the triangles describing the mesh.
*/
Vector3f[] vertices = new Vector3f[points];
int[] indexes = new int[points];
float[] normals = new float[points * 3];
/*
* All vertices are sorted already so the vertices are in
* the correct order and dont have to be set in a special order.
*/
for(int i = 0; i < points; i++) {
indexes[i] = i;
}
/*
* Sets and calculates all vertices and normals of the mesh
*/
for(int y = 0; y < size - 1; y++) {
for(int x = 0; x < size - 1; x++) {
setVertices(x, y, vertices);
Vector3f[] temp_normals = calculateNormals(x, y, vertices);
setNormals(x, y, normals, temp_normals);
}
}
/*
* Adds all calculated values to the mesh
*/
this.mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
this.mesh.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(indexes));
this.mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
}
/*
* Sets the vertices at position x and y for the mesh
*
* @param x the x coordinate
* @param y the y coordinate
* @param vertices the storage for the calculated vertices
*/
private void setVertices(int x, int y, Vector3f[] vertices) {
int position = ((y * (size - 1)) + x) * 6;
vertices[position ] = new Vector3f((x * SCALE) , heightmap[x][y] , (y * SCALE) );
vertices[position + 1] = new Vector3f((x * SCALE) , heightmap[x][y + 1] , (y * SCALE) + SCALE);
vertices[position + 2] = new Vector3f((x * SCALE) + SCALE, heightmap[x + 1][y] , (y * SCALE) );
vertices[position + 3] = new Vector3f((x * SCALE) , heightmap[x][y + 1] , (y * SCALE) + SCALE);
vertices[position + 4] = new Vector3f((x * SCALE) + SCALE, heightmap[x + 1][y + 1], (y * SCALE) + SCALE);
vertices[position + 5] = new Vector3f((x * SCALE) + SCALE, heightmap[x + 1][y] , (y * SCALE) );
}
/*
* Calculates the 2 normals of a square plate in the mesh
*
* @param x the x coordinate
* @param y the y coordinate
* @param vertices the vertices the normals are calculated from
*
* @return normals the 2 normals in an vector array
*/
private Vector3f[] calculateNormals(int x, int y, Vector3f[] vertices) {
Vector3f[] normals = new Vector3f[2];
Vector3f site_1 = vertices[((y * (size - 1)) + x) * 6].subtract(vertices[((y * (size - 1)) + x) * 6 + 1]);
Vector3f site_2 = vertices[((y * (size - 1)) + x) * 6].subtract(vertices[((y * (size - 1)) + x) * 6 + 2]);
Vector3f site_3 = vertices[((y * (size - 1)) + x) * 6 + 3].subtract(vertices[((y * (size - 1)) + x) * 6 + 4]);
Vector3f site_4 = vertices[((y * (size - 1)) + x) * 6 + 3].subtract(vertices[((y * (size - 1)) + x) * 6 + 5]);
normals[0] = site_1.cross(site_2);
normals[1] = site_3.cross(site_4);
return normals;
}
/*
* Sets the calculated normals for the mesh
*
* @param x the x coordinate
* @param y the y coordinate
* @param normals the normals storage
* @param temp_normals the vector array with the normals inside
*/
private void setNormals(int x, int y, float[] normals, Vector3f[] temp_normals) {
int position = ((y * (size - 1)) + x) * 6 * 3;
for(int i = 0; i < 6; i++) {
if(i < 3) {
normals[position + (i * 3) ] = temp_normals[0].getX();
normals[position + (i * 3) + 1] = temp_normals[0].getY();
normals[position + (i * 3) + 2] = temp_normals[0].getZ();
}
else {
normals[position + (i * 3) ] = temp_normals[1].getX();
normals[position + (i * 3) + 1] = temp_normals[1].getY();
normals[position + (i * 3) + 2] = temp_normals[1].getZ();
}
}
}
/*
* Applies the given color to all vertices
*
* @param color the color being applied
*
* @return colors the array with the colors inside
*/
private float[] setVertexColors(Color color) {
/*
* Calculate the amount of points needed to generate
* each triangles corners inside the mesh.
* Each square got 6 points.
*/
int points = (size - 1) * (size - 1) * 6;
float[] colors = new float[points * 4];
for(int y = 0; y < size - 1; y++) {
for(int x = 0; x < size - 1; x++) {
int position = ((y * (size - 1)) + x) * 6 * 4;
for(int i = 0; i < 6; i++) {
colors[position + (i * 4) ] = color.getRed();
colors[position + (i * 4) + 1] = color.getGreen();
colors[position + (i * 4) + 2] = color.getBlue();
colors[position + (i * 4) + 3] = color.getAlpha();
}
}
}
return colors;
}
}
And here is the Code in the main class that generates and adds it to the scene:
@Override
public void simpleInitApp() {
Material material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
material.setBoolean("UseVertexColor", true);
material.setColor("Ambient", ColorRGBA.Gray);
material.setColor("Diffuse", ColorRGBA.White);
material.setColor("Specular", ColorRGBA.White);
IslandHeightmap island = new IslandHeightmap(500, 0.0001, (int) (Math.random() * 100000));
heightmap = island.getHeightmap();
FlatShadedTerrain terrain = new FlatShadedTerrain(heightmap, 500, new Color(1, 0, 1, 1));
terrain.setMaterial(material);
rootNode.attachChild(terrain);
AmbientLight light = new AmbientLight();
light.setColor(ColorRGBA.DarkGray);
rootNode.addLight(light);
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.2f, -1,-0.5f));
rootNode.addLight(sun);
flyCam.setMoveSpeed(500);
}