Hi!
As someone of you already know, I’m learning about Minecraft-like engines, and I want to create one.
So, I’m good with most of the engine, but I have an issue with the terrain rendering. I was inspired by some other codes from other engines and this is the Mesh Generator:
public class MeshGenerator {
private static Vector3f[] positions;
private static short[] indices;
private static Vector2f[] textureCoordinates;
private static float[] normals;
public static Mesh generate(Chunk chunk, boolean isTransparent){
LinkedList<Vector3f> positionsList = new LinkedList<>();
LinkedList<Short> indicesList = new LinkedList<>();
LinkedList<Float> normalsList = new LinkedList<>();
LinkedList<Vector2f> textureCoordinatesList = new LinkedList<>();
World world = chunk.getWorld();
Vector3i tmpLocation = new Vector3i();
for(int i = 0; i < world.getSettings().getChunkDimension().x; i++){
for(int j = 0; j < world.getSettings().getChunkDimension().y; j++){
for(int k = 0; k < world.getSettings().getChunkDimension().z; k++){
tmpLocation.set(i, j, k);
short block = chunk.getBlock(tmpLocation);
if(block > 0){
Cube cube = new Cube(0.125f);
cube.prepare(isTransparent, positionsList, indicesList, normalsList, textureCoordinatesList);
cube.addTo(chunk, tmpLocation);
}
}
}
}
positions = new Vector3f[positionsList.size()];
Iterator<Vector3f> positionsIterator = positionsList.iterator();
for(int i=0;positionsIterator.hasNext();i++){
positions[i] = positionsIterator.next().mult(world.getSettings().getBlockyWidth());
}
indices = new short[indicesList.size()];
Iterator<Short> indicesIterator = indicesList.iterator();
for(int i=0;indicesIterator.hasNext();i++){
indices[i] = indicesIterator.next();
}
textureCoordinates = textureCoordinatesList.toArray(new Vector2f[0]);
normals = new float[normalsList.size()];
Iterator<Float> normalsIterator = normalsList.iterator();
for(int i=0;normalsIterator.hasNext();i++){
normals[i] = normalsIterator.next();
}
return generateMesh();
}
private static Mesh generateMesh(){
Mesh mesh = new Mesh();
mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(positions));
mesh.setBuffer(Type.Index, 1, BufferUtils.createShortBuffer(indices));
mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoordinates));
mesh.updateBound();
System.out.println("Chunk mesh successfully generated.");
return mesh;
}
}
And i’m calling it from:
public final void renderTerrain(){
for(Chunk[] row : chunks){
for(Chunk chunk : row){
Mesh mesh = MeshGenerator.generate(chunk, enabled);
Geometry geom = new Geometry("", mesh);
geom.setMaterial(settings.getAssetManager().loadMaterial("Materials/Test.j3m"));
chunk.getNode().attachChild(new Geometry("" + mesh));
}
}
}
Called in turn by the constructor after chunks initialization.
But I keep getting nothing on the screen.
I want to clarify that i’m not using textures yet. But I should get a black mesh, right?
Thanks for any reply.
EDIT:
I think you also need the Cube class code to help me…
public class Cube extends Cuboid{
public Cube(float side) {
super(new float[]{side, side, side, side, side, side});
}
}
public class Cuboid extends Shape{
float[] extents;
public Cuboid(float[] extents){
this.extents = extents;
}
@Override
public void addTo(Chunk chunk, Vector3i blockLocation) {
short block = chunk.getBlock(blockLocation);
Vector3f blockLocation3f = new Vector3f(blockLocation.getX(), blockLocation.getY(), blockLocation.getZ());
Vector3f faceLoc_Bottom_TopLeft = blockLocation3f.add(new Vector3f((0.5f - extents[2]), (0.5f - extents[1]), (0.5f - extents[5])));
Vector3f faceLoc_Bottom_TopRight = blockLocation3f.add(new Vector3f((0.5f + extents[3]), (0.5f - extents[1]), (0.5f - extents[5])));
Vector3f faceLoc_Bottom_BottomLeft = blockLocation3f.add(new Vector3f((0.5f - extents[2]), (0.5f - extents[1]), (0.5f + extents[4])));
Vector3f faceLoc_Bottom_BottomRight = blockLocation3f.add(new Vector3f((0.5f + extents[3]), (0.5f - extents[1]), (0.5f + extents[4])));
Vector3f faceLoc_Top_TopLeft = blockLocation3f.add(new Vector3f((0.5f - extents[2]), (0.5f + extents[0]), (0.5f - extents[5])));
Vector3f faceLoc_Top_TopRight = blockLocation3f.add(new Vector3f((0.5f + extents[3]), (0.5f + extents[0]), (0.5f - extents[5])));
Vector3f faceLoc_Top_BottomLeft = blockLocation3f.add(new Vector3f((0.5f - extents[2]), (0.5f + extents[0]), (0.5f + extents[4])));
Vector3f faceLoc_Top_BottomRight = blockLocation3f.add(new Vector3f((0.5f + extents[3]), (0.5f + extents[0]), (0.5f + extents[4])));
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.TOP)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Top_BottomLeft);
positions.add(faceLoc_Top_BottomRight);
positions.add(faceLoc_Top_TopLeft);
positions.add(faceLoc_Top_TopRight);
addSquareNormals(normals, 0, 1, 0);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.BOTTOM)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Bottom_BottomRight);
positions.add(faceLoc_Bottom_BottomLeft);
positions.add(faceLoc_Bottom_TopRight);
positions.add(faceLoc_Bottom_TopLeft);
addSquareNormals(normals, 0, -1, 0);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.LEFT)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Bottom_TopLeft);
positions.add(faceLoc_Bottom_BottomLeft);
positions.add(faceLoc_Top_TopLeft);
positions.add(faceLoc_Top_BottomLeft);
addSquareNormals(normals, -1, 0, 0);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.RIGHT)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Bottom_BottomRight);
positions.add(faceLoc_Bottom_TopRight);
positions.add(faceLoc_Top_BottomRight);
positions.add(faceLoc_Top_TopRight);
addSquareNormals(normals, 1, 0, 0);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.FRONT)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Bottom_BottomLeft);
positions.add(faceLoc_Bottom_BottomRight);
positions.add(faceLoc_Top_BottomLeft);
positions.add(faceLoc_Top_BottomRight);
addSquareNormals(normals, 0, 0, 1);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
if(shouldFaceBeAdded(chunk, blockLocation, BlockFace.REAR)){
addFaceIndices(indices, positions.size());
positions.add(faceLoc_Bottom_TopRight);
positions.add(faceLoc_Bottom_TopLeft);
positions.add(faceLoc_Top_TopRight);
positions.add(faceLoc_Top_TopLeft);
addSquareNormals(normals, 0, 0, -1);
addTextureCoordinates(chunk, texCoords, 0, 0);
}
}
private void addFaceIndices(List<Short> indices, int offset){
indices.add((short) (offset + 2));
indices.add((short) (offset + 0));
indices.add((short) (offset + 1));
indices.add((short) (offset + 1));
indices.add((short) (offset + 3));
indices.add((short) (offset + 2));
}
private void addSquareNormals(List<Float> normals, float normalX, float normalY, float normalZ){
for(int i=0;i<4;i++){
normals.add(normalX);
normals.add(normalY);
normals.add(normalZ);
}
}
private void addTextureCoordinates(Chunk chunk, List<Vector2f> textureCoordinates, int row, int col){
textureCoordinates.add(getTextureCoordinates(chunk, row, col, 0, 0));
textureCoordinates.add(getTextureCoordinates(chunk, row, col, 1, 0));
textureCoordinates.add(getTextureCoordinates(chunk, row, col, 0, 1));
textureCoordinates.add(getTextureCoordinates(chunk, row, col, 1, 1));
}
}