+1 vote

I'm a bit confused on how to make a voxel terrain with Arraymesh. How would I go about setting up the arrays? Currently I'm storing the voxels as a 1s and 0s in a 3dimensional list.
My code is below:

extends Spatial


var voxel = []

var verts = PoolVector3Array()
var normals = PoolVector3Array()
var indices = PoolIntArray()

func _ready():
    #terrain generation code

    var arr_mesh = ArrayMesh.new()
    var mesh_arrays = []
    mesh_arrays.resize(ArrayMesh.ARRAY_MAX)
    for x in range(16):
        for z in range(16):
            for y in range(16):
                if voxel[x][z][y]==1:
                    if x-1<0 || voxel[x-1][z][y]==0:
                        make_quad(Vector3(x,y,z), Vector3(x,y+1,z), Vector3(x,y+1,z+1), Vector3(x,y,z+1))
                    if x+1>15 || voxel[x+1][z][y]==0:
                        make_quad(Vector3(x+1,y,z+1), Vector3(x+1,y+1,z+1), Vector3(x+1,y+1,z), Vector3(x+1,y,z))
                    if y-1<0 || voxel[x][z][y-1]==0:
                        make_quad(Vector3(x+1,y,z), Vector3(x,y,z), Vector3(x,y,z+1), Vector3(x+1,y,z+1))
                    if y+1>15 || voxel[x][z][y+1]==0:
                        make_quad(Vector3(x+1,y+1,z+1), Vector3(x,y+1,z+1), Vector3(x,y+1,z), Vector3(x+1,y+1,z))
                    if z-1<0 || voxel[x][z-1][y]==0:
                        make_quad(Vector3(x+1,y,z), Vector3(x+1,y+1,z), Vector3(x,y+1,z), Vector3(x,y,z))
                    if z+1>15 || voxel[x][z+1][y]==0:
                        make_quad(Vector3(x,y,z+1), Vector3(x,y+1,z+1), Vector3(x+1,y+1,z+1), Vector3(x+1,y,z+1))
    mesh_arrays[Mesh.ARRAY_VERTEX] = verts
    mesh_arrays[Mesh.ARRAY_NORMAL] = normals
    mesh_arrays[Mesh.ARRAY_INDEX] = indices
    arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, mesh_arrays)
    get_node("MeshInstance").mesh = arr_mesh

func make_quad(a,b,c,d):
    var length = len(verts)
    indices.append_array([length, length+1, length+2, length, length+2, length+3])
    verts.append_array([a,b,c,d])
    normals.append_array([a.normalized(),b.normalized(),c.normalized(),d.normalized()])

This should generate a voxel world 16x16x16. The problem is that the terrain it generates is all white. How can I add textures to the terrain? I'm also not sure how I would go about changing the terrain? If I want to add a block would I have to go over the whole loop to calculate new arrays, but that would be to inefficient.

in Engine by (429 points)

While I cannot fully help with everything you've asked, I have found a way to apply a texture. However, you will need to also define UVs for the surfaces you are adding to the ArrayMesh. You can do this by simply adding a PoolVector2Array called something like "uvs", then adding Vector2's with their X and Y values ranging from 0 to 1 (inclusively). This will tell Godot where each vertex associated with the UV where on the texture it needs to look. Based on your make_quad function, you could add the snippet uvs.append_array([Vector2(0, 0), Vector2(1, 0), Vector3(1, 1), Vector3(0, 1)]) (this assumes you're adding the vertices in a clockwise order starting top-left).

(Edit to add a few sentences:)
Now, as for actually setting the material for the surfaces, I've added a code snippet I used before.
I've changed the variables I used to what you used.

for surface in range(arr_mesh.get_surface_count()):
        # ``arr_mesh`` is from your _ready function.
        # ``spatial_material`` is whatever Spatial Material you've chosen
        # (with your texture already loaded)
        arr_mesh.surface_set_material(surface, spatial_material)

I've found that the above works pretty well for what I was doing, even though it was not voxel-based. Based on the code you have shown, I would put the above snippet into your ready function. Do it after you call arr_mesh.add_surface_from_arrays, though, or it will not work.

Hopefully this helps you out in regards to applying a texture to your mesh.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.