Usando SurfaceTool

The SurfaceTool provides a useful interface for constructing geometry. The interface is similar to the ImmediateMesh class. You set each per-vertex attribute (e.g. normal, uv, color) and then when you add a vertex it captures the attributes.

El SurfaceTool también proporciona algunas funciones auxiliares útiles como index() y generate_normals().

Los atributos se agregan antes de agregar cada vértice:

var st = SurfaceTool.new()

st.begin(Mesh.PRIMITIVE_TRIANGLES)

st.set_normal() # Overwritten by normal below.
st.set_normal() # Added to next vertex.
st.set_color() # Added to next vertex.
st.add_vertex() # Captures normal and color above.
st.set_normal() # Normal never added to a vertex.

When finished generating your geometry with the SurfaceTool, call commit() to finish generating the mesh. If an ArrayMesh is passed to commit(), then it appends a new surface to the end of the ArrayMesh. While if nothing is passed in, commit() returns an ArrayMesh.

# Add surface to existing ArrayMesh.
st.commit(mesh)

# -- Or Alternatively --

# Create new ArrayMesh.
var mesh = st.commit()

The code below creates a triangle without indices.

var st = SurfaceTool.new()

st.begin(Mesh.PRIMITIVE_TRIANGLES)

# Prepare attributes for add_vertex.
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 0))
# Call last for each vertex, adds the above attributes.
st.add_vertex(Vector3(-1, -1, 0))

st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 1))
st.add_vertex(Vector3(-1, 1, 0))

st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(1, 1))
st.add_vertex(Vector3(1, 1, 0))

# Commit to a mesh.
var mesh = st.commit()

You can optionally add an index array, either by calling add_index() and adding vertices to the index array manually, or by calling index() once, which generates the index array automatically and shrinks the vertex array to remove duplicate vertices.

# Suppose we have a quad defined by 6 vertices as follows
st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))

st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(1, -1, 0))
st.add_vertex(Vector3(-1, -1, 0))

# We can make the quad more efficient by using an index array and only utilizing 4 vertices

# Suppose we have a quad defined by 6 vertices as follows
st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))

st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(1, -1, 0))
st.add_vertex(Vector3(-1, -1, 0))

# We can make the quad more efficient by using an index array and only utilizing 4 vertices

# Creates a quad from four corner vertices.
# add_index() can be called before or after add_vertex()
# since it's not an attribute of a vertex itself.
st.add_index(0)
st.add_index(1)
st.add_index(2)

st.add_index(1)
st.add_index(3)
st.add_index(2)

# Alternatively we can use ``st.index()`` which will create the quad for us and remove the duplicate vertices
st.index()

De manera similar, si tienes un array de índices pero deseas que cada vértice sea único (por ejemplo, porque deseas utilizar normales o colores únicos por cara en lugar de por vértice), puedes llamar a deindex().

st.deindex()

Si no agregas normales personalizadas tú mismo, puedes añadirlas usando generate_normals(), que debe ser llamado después de generar la geometría y antes de confirmar la malla utilizando commit() o commit_to_arrays(). Llamar a generate_normals(true) invertirá las normales resultantes. Como nota adicional, generate_normals() solo funciona si el tipo primitivo está establecido en Mesh.PRIMITIVE_TRIANGLES.

You may notice that normal mapping or other material properties look broken on the generated mesh. This is because normal mapping requires the mesh to feature tangents, which are separate from normals. You can either add custom tangents manually, or generate them automatically with generate_tangents(). This method requires that each vertex have UVs and normals set already.

st.generate_normals()
st.generate_tangents()

st.commit(mesh)

By default, when generating normals, they will be calculated on a per-vertex basis (i.e. they will be "smooth normals"). If you want flat vertex normals (i.e. a single normal vector per face), when adding vertices, call add_smooth_group(i) where i is a unique number per vertex. add_smooth_group() needs to be called while building the geometry, e.g. before the call to add_vertex().