[SOLVED] Custom mesh not rendering?

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));
}
}

The first thing I do to debug meshes that aren’t showing is use the unshaded material and enable wireframe mode. If it shows as intended disable backface culling to see if the winding order is correct.

Then I generate a normal mesh to see if I’ve done normal calculations properly when I get to lighting.

2 Likes

And if that doesn’t instantly shed light, reduce it to a single cube mesh and print the values of the buffers.

…pretty sure you’ll spot the issue then. And if not then we might if you paste it here.

1 Like

Not sure what that line is supposed to do but it isn’t attaching the geometry you created a few lines beforehand.

4 Likes

Oh yes! I used a “+” instead of a comma. How stupid is this? :smiley:
I should write chunk.getNode().attachChild(geom);
Also I’m not sure if I have attached chunks’ node to the root node, so I have to check this. But i’ll do it tomorrow. I’ll let you know!
Thanks!

Okay, I did it!
The incorrect attach to the node wasn’t the only problem, but I was also creating blocks with an invalid ID, so it was generating empty meshes. Thank you for all your help!

1 Like