• 3D
  • I need explanation on ArrayMesh (trying to create a simple cube)

I am working on a voxel-based project and I want to hide the sides that are covered to make the game run faster.

This is the first time I feel that lost as I can't find any good tutorials online on how to make a simple cube using ArrayMesh. There are many terms I don't understand, as I've never gotten that deep with geometry code before.

If the voxel is a cube, the plan is to only show the sides that are visible and not covered. I don't need help with the occlusion logic (I will figure it out). I only need someone to explain to me, like I am a 5-year old, how to create a simple cube via code.

P.S.: I don't intend to use the SurfaceTool, as I read that it is slow and speed is very crucial here to keep the FPS up.

16 days later

Well, this is one way to create a simple cube:

# I like to use this convention, but you can use whatever you like
#               010           110                         Y
#   Vertices     A0 ---------- B1            Faces      Top    -Z
#           011 /  |      111 /  |                        |   North
#             E4 ---------- F5   |                        | /
#             |    |        |    |          -X West ----- 0 ----- East X
#             |   D3 -------|-- C2                      / |
#             |  /  000     |  / 100               South  |
#             H7 ---------- G6                      Z    Bottom
#              001           101                          -Y

var a := Vector3(0, 1, 0) # if you want the cube centered on grid points
var b := Vector3(1, 1, 0) # you can subtract a Vector3(0.5, 0.5, 0.5)
var c := Vector3(1, 0, 0) # from each of these
var d := Vector3(0, 0, 0)
var e := Vector3(0, 1, 1)
var f := Vector3(1, 1, 1)
var g := Vector3(1, 0, 1)
var h := Vector3(0, 0, 1)

var vertices := [   # faces (triangles)
	b,a,d,  b,d,c,  # N
	e,f,g,  e,g,h,  # S
	a,e,h,  a,h,d,  # W
	f,b,c,  f,c,g,  # E
	a,b,f,  a,f,e,  # T
	h,g,c,  h,c,d,  # B
]

var colors := []
for i in range(vertices.size()):
	colors.append(Color.red)

var mesh := ArrayMesh.new()

var arrays := []
arrays.resize(Mesh.ARRAY_MAX)
arrays[Mesh.ARRAY_VERTEX] = PoolVector3Array(vertices)
arrays[Mesh.ARRAY_COLOR] = PoolColorArray(colors)

mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
# mesh.surface_set_material(0, your_material)   # will need uvs if using a texture
your_material.vertex_color_use_as_albedo = true # will need this for the array of colors

var mi := MeshInstance.new()
mi.mesh = mesh
add_child(mi) # don't forget to add it as child of something (I always forget, lol)

# if the texture is a tileset like minecraft's, then maybe you can use this 
# instead of setting the material for each surface
# mi.material_override = your_material      # will need uvs if using a texture

That's not using UVs, so it can't be textured, and it's also not using normals, so lighting won't work well on it. When using UVs you don't need to feed the mesh with an array of colors.

Normals for cubes are quite straightforward. It's one per vertex, and since you probably want hard edges, they can just point straight out from the face they belong to. If you want, you can even use the constants Vector3.LEFT, Vector3.UP, etc, depending on which face the respective vertex is. Just put them in a PoolVector3Array, and feed it to arrays[Mesh.ARRAY_NORMAL].

UVs can be tricky. You also need one per vertex, and the values go from 0 to 1. If you're using an atlas texture like those in minecraft, you'll have to do some math to figure out their position in the texture, since each face will encompass one tile. This will depend on the width/height of the texture, and the size of the tiles. You can put the UVs in a PoolVector2Array and feed it to arrays[Mesh.ARRAY_TEX_UV]. If you need I suppose I can elaborate on this.

Keep in mind that you need one surface per material. If you're using an atlas texture, then the whole mesh can be made of a single surface. If not, then you'll have to account for that.

---

Btw, you might like to take a look at the Voxel Core plugin and Zylann's Voxel Module.

And I presume these files might be relevant: Voxel Core/voxel_tool.gd Voxel Module/voxel_mesher_cubes.cpp

9 months later

Hi ! Thank you for your code woopdeedoo, I implemented it and I have just one problem I can't figure out: color doesn't show up, it's all white. I can change it if I add a material with a specific albedo color, but then all the arraymesh has the same color, and I want to choose the color of each triangle. Any tips that could help ?

You have to set use vertex as albedo in the material flags.