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