Использование SurfaceTool

SurfaceTool предоставляет удобный интерфейс для создания геометрии. Этот интерфейс похож на класс ImmediateMesh. Вы задаёте атрибуты для каждой вершины (например, нормаль, UV-координаты, цвет), а при добавлении вершины она захватывает эти атрибуты.

SurfaceTool также предоставляет некоторые полезные вспомогательные функции, такие как index() и generate_normals().

Атрибуты добавляются перед добавлением каждой вершины:

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.

Когда вы закончите генерировать свою геометрию с помощью SurfaceTool, вызовите commit(), чтобы завершить генерацию сетки. Если ArrayMesh передается в commit(), то он добавляет новую поверхность в конец ArrayMesh. В то время как, если ничего не передано, commit() возвращает ArrayMesh.

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

# -- Or Alternatively --

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

Приведенный ниже код создает треугольник без индексов.

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()

При желании вы можете добавить массив индексов, вызвав add_index() и добавив вершины в массив индексов вручную, или вызвав index() один раз, что автоматически сгенерирует массив индексов и сократит массив вершин для удаления повторяющихся вершин.

# 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:

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

# 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()

Аналогично, если у вас есть массив индексов, но вы хотите, чтобы каждая вершина была уникальной (например, потому что вы хотите использовать уникальные нормали или цвета для каждой грани, а не для каждой вершины), вы можете вызвать deindex().

st.deindex()

Если вы не добавляете пользовательские нормали самостоятельно, вы можете добавить их с помощью generate_normals(0), который следует вызывать после генерации геометрии и перед фиксацией сетки с помощью commit() или commit_to_arrays(). Вызов generate_normals(true) перевернет результирующие нормали. В качестве дополнительного примечания, generate_normals() работает только в том случае, если для примитивного типа задано значение "Mesh.PRIMITIVE_TRIANGLES`.

Вы можете заметить, что нормалмаппинг или другие свойства материала выглядят некорректно на сгенерированной сетке. Это происходит потому, что нормалмаппинг требует наличия касательных в сетке, которые отличаются от нормалей. Вы можете либо добавить пользовательские касательные вручную, либо автоматически сгенерировать их с помощью generate_tangents(). Этот метод требует, чтобы для каждой вершины уже были заданы UV-координаты и нормали.

st.generate_normals()
st.generate_tangents()

st.commit(mesh)

По умолчанию при генерации нормалей они рассчитываются для каждой вершины отдельно (т.е. это будут «гладкие нормали»). Если вам нужны плоские нормали вершин (т.е. один вектор нормали на грань), при добавлении вершин вызовите add_smooth_group(i), где i — уникальный номер для каждой вершины. add_smooth_group() необходимо вызывать во время построения геометрии, например, перед вызовом add_vertex().