Процедурная геометрия

В Godot существует несколько способов процедурной генерации геометрии. В этой серии туториалов мы рассмотрим некоторые из них. Каждая техника имеет свои плюсы и минусы, поэтому важно понимать, как и когда она может быть полезна.

Примечание

Все описанные здесь методы процедурной генерации геометрии выполняются на CPU. Генерация геометрии на GPU в Godot пока не поддерживается.

Что такое геометрия?

Геометрия - это причудливый способ обозначения формы. В компьютерной графике геометрия обычно представлена массивом позиций, называемых "вершинами". В Godot геометрия представлена сетками (Meshes).

Что такое меш?

Во многих вещах в Godot присутствует слово "mesh" в названии: Mesh, ArrayMesh, ImmediateMesh, MeshInstance3D, MultiMesh, и MultiMeshInstance3D. Хотя все они связаны между собой, их назначение немного различается.

Mesh и ArrayMesh — это ресурсы, которые отображаются с помощью узла MeshInstance3D. Такие ресурсы, как Mesh и ArrayMesh, нельзя добавлять в сцену напрямую. Узел MeshInstance3D представляет собой один экземпляр меша в вашей сцене. Один и тот же меш можно использовать в нескольких MeshInstance3D, чтобы отобразить его в разных частях сцены с разными материалами или преобразованиями (масштаб, вращение, позиция и т.д.).

Если вы собираетесь отрисовывать один и тот же объект много раз, имеет смысл использовать MultiMesh вместе с MultiMeshInstance3D. Узлы MultiMeshInstance3D позволяют очень эффективно отрисовывать меши тысячи раз, используя аппаратное инстансирование. Недостатком MultiMeshInstance3D является то, что каждая поверхность меша ограничена одним материалом для всех экземпляров. Для хранения различных цветов и преобразований используется массив экземпляров, но все экземпляры одной поверхности используют общий материал.

Что такое Сетка

Mesh состоит из одной или нескольких поверхностей. Поверхность — это массив, содержащий несколько подмассивов с вершинами, нормалями, UV-координатами и т.д. Обычно процесс создания поверхностей и мешей скрыт от пользователя и происходит внутри RenderingServer, но с помощью ArrayMesh пользователь может вручную создать Mesh, передав массив с информацией о поверхности.

Поверхности

Каждая поверхность имеет свой собственный материал. Также можно переопределить материал для всех поверхностей Mesh при использовании MeshInstance3D с помощью свойства material_override.

Массив поверхности

Массив поверхности представляет собой массив длины ArrayMesh.ARRAY_MAX. Каждая позиция в этом массиве содержит подмассив с информацией о вершинах. Например, массив по индексу ArrayMesh.ARRAY_NORMAL — это PackedVector3Array с нормалями вершин. Подробнее см. в Mesh.ArrayType.

Массив поверхности может быть индексированным или неиндексированным. Создать неиндексированный массив так же просто, как не назначать массив по индексу ArrayMesh.ARRAY_INDEX. Неиндексированный массив хранит уникальную информацию о вершине для каждого треугольника, что означает, что когда два треугольника имеют общую вершину, эта вершина дублируется в массиве. Индексированный массив поверхностей хранит информацию о вершинах только для каждой уникальной вершины, а затем также хранит массив индексов, которые указывают, как построить треугольники из массива вершин. В целом, использование индексированного массива быстрее, но это означает, что вам придётся обмениваться вершинными данными между треугольниками, что не всегда желательно (например, когда вам нужны нормали для каждой грани).

Инструменты

Godot предоставляет различные способы доступа к геометрии и работы с ней. Более подробная информация по каждому из них будет предоставлена в следующих уроках.

ArrayMеsh

Ресурс ArrayMesh расширяет Mesh, добавляя несколько различных функций качества жизни и, самое главное, возможность построения поверхности Mesh с помощью скриптов.

Для получения дополнительной информации об ArrayMesh, пожалуйста, смотрите ArrayMesh tutorial.

Инструмент "Данные Меша"

MeshDataTool - это ресурс, преобразующий данные Mesh в массивы вершин, граней и ребер, которые могут быть изменены во время выполнения.

Более подробную информацию о MeshDataTool можно найти в MeshDataTool tutorial.

SurfaceTool (Инструмент поверхности)

Инструмент SurfaceTool позволяет создавать сетки, используя интерфейс OpenGL 1.x в стиле немедленного режима.

Для получения дополнительной информации о SurfaceTool, пожалуйста, обратитесь к SurfaceTool tutorial.

ImmediateMesh (Немедленная сетка)

ImmediateMesh — это меш, использующий интерфейс в стиле режима немедленного рисования (как и SurfaceTool) для отображения объектов. Разница между ImmediateMesh и SurfaceTool заключается в том, что ImmediateMesh отрисовывается напрямую через код в реальном времени, тогда как SurfaceTool используется для генерации Mesh, с которым затем можно делать всё, что угодно.

ImmediateMesh полезен для прототипирования благодаря простому API, но работает медленно, поскольку геометрия пересоздаётся при каждом изменении. Чаще всего его используют для визуального отладки с простой геометрией (например, для отображения линий при визуализации физических лучей и т.п.).

Более подробную информацию о ImmediateMesh можно найти в руководстве по ImmediateMesh.

Какой из них мне следует использовать?

Какой подход вы используете, зависит от того, что вы пытаетесь сделать и какой вид процедуры вам удобен.

И SurfaceTool, и ArrayMesh отлично подходят для создания статической геометрии (сетки), которая не меняется со временем.

Использование ArrayMesh немного быстрее, чем использование SurfaceTool, но API немного сложнее. Кроме того, SurfaceTool имеет несколько методов качества жизни, таких как generate_normals() и index().

ImmediateMesh более ограничен, чем ArrayMesh и SurfaceTool. Однако если вам всё равно нужно изменять геометрию каждый кадр, он предоставляет гораздо более простой интерфейс, который может быть немного быстрее, чем генерация ArrayMesh каждый кадр.

MeshDataTool не является быстрым, но он даёт вам доступ ко всем видам свойств сетки, которые вы не можете получить с помощью других инструментов (рёбра, грани и т.д.). Он невероятно полезен, когда вам нужны такие данные для преобразования сетки, но его не стоит использовать, если эта дополнительная информация не нужна. Инструмент MeshDataTool лучше использовать, если вы собираетесь использовать алгоритм, требующий доступа к массиву граней или рёбер.