This page has been translated automatically.
Видеоуроки
Интерфейс
Основы
Продвинутый уровень
Подсказки и советы
Основы
Программирование на C#
Рендеринг
Профессиональный уровень (SIM)
Принципы работы
Свойства (properties)
Компонентная Система
Рендер
Режимы вывода изображения
Физика
Браузер SDK 2
Лицензирование и типы лицензий
Дополнения (Add-Ons)
Демонстрационные проекты
API Samples
Редактор UnigineEditor
Обзор интерфейса
Работа с ассетами
Контроль версий
Настройки и предпочтения
Работа с проектами
Настройка параметров ноды
Setting Up Materials
Настройка свойств
Освещение
Sandworm
Использование инструментов редактора для конкретных задач
Расширение функционала редактора
Встроенные объекты
Ноды (Nodes)
Объекты (Objects)
Эффекты
Декали
Источники света
Geodetics
World-ноды
Звуковые объекты
Объекты поиска пути
Player-ноды
Программирование
Основы
Настройка среды разработки
Примеры использования
C++
C#
UnigineScript
Унифицированный язык шейдеров UUSL (Unified UNIGINE Shader Language)
Плагины
Форматы файлов
Материалы и шейдеры
Rebuilding the Engine Tools
Интерфейс пользователя (GUI)
Двойная точность координат
API
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
Работа с контентом
Оптимизация контента
Материалы
Визуальный редактор материалов
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Учебные материалы
Внимание! Эта версия документация УСТАРЕЛА, поскольку относится к более ранней версии SDK! Пожалуйста, переключитесь на самую актуальную документацию для последней версии SDK.
Внимание! Эта версия документации описывает устаревшую версию SDK, которая больше не поддерживается! Пожалуйста, обновитесь до последней версии SDK.

Трава (Grass)

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

Смотрите также#

Добавление травы в сцену#

Чтобы добавить траву в мир, выполните следующие действия:

  1. В меню выберите пункт Create -> Grass -> Base.

  2. Поместите объект где-нибудь в мире.

Поле травы по умолчанию будет отображаться с присвоенным материалом grass_base.

Рендеринг травы#

Рендеринг травы в основном зависит от двух текстур:

  • текстура Diffuse определяет форму и цвет травы.
  • текстура Mask определяет отображение травы и распределение плотности на местности.

Для удобства диффузная текстура разделена на куски. Каждый фрагмент отображается в зависимости от используемых значений маски. Чтобы максимально использовать вариации видов травы, куски помещаются в текстуру следующим образом:

  • Горизонтальная строка может содержать до блоков 4. Каждый фрагмент соответствует красному, зеленому, синему и альфа-каналам маски.

  • Количество блоков в вертикальном столбце может быть от 1 до 4. Фрагменты в столбце представляют вариации травы для соответствующего канала маски. Обычно каждый канал соответствует определенному виду травы (более тонкой, густой, спутанной и т.д.). Если в вертикальном столбце есть несколько скоплений травы, они случайным образом распределяются по замаскированной области.

    Чтобы текстура была разделена на правильное количество фрагментов, в поле Num Textures должно быть указано количество фрагментов, которые вы использовали для каждого столбца. Например, для приведенной ниже диффузной текстуры следует указать значение Num Textures = 4.

Texture Type Setting
Diffuse RGBA:
  • значения RGB хранят информацию о цвете травы.
  • значение A хранит информацию о прозрачности и определяет, какие части кусков травы будут окрашены, а какие будут обрезаны при альфа-тестировании.
Устанавливается на вкладке Textures материала grass_base.
Mask

RGBA8: каждый канал управляет распределением фрагментов в вертикальном столбце диффузной текстуры травы.

  • Красный канал определяет области роста для 1-го столбца текстуры.
  • Зеленый — для 2-го столбца текстуры.
  • Синий — для 3-го столбца текстуры.
  • Альфа — для 4-го столбца текстуры.
Примечание
В случае, если в качестве маски используется текстура R8, RG8 или RGB8, диффузная текстура должна содержать только один, два или три столбца. Итак, если ваша диффузная текстура содержит, например, только 1 вертикальный столбец, следует использовать текстуру R8.

значения канала маски 0 (без цвета) создают области, где трава расти не должна. Ненулевые значения канала создают травянистую зону: чем выше значение, тем гуще растет трава.

Если текстура маски не задана, используется белая текстура по умолчанию. У него нет предопределенного количества каналов: тип этой текстуры зависит от значения, установленного в поле Num Textures. Итак, если Num Textures = 2, текстура маски по умолчанию будет RG8.

Установите на вкладке ObjectGrass -> Node → раздел Grass - поле > Mask Image.

Например, у нас есть следующие диффузные и маскирующие текстуры:

Диффузная текстура
RBG и каналы маски

Мы видим, что в первом столбце фрагменты зеленых оттенков соответствуют красному каналу маски, который представляет собой 9 красных ромбов; во втором столбце фрагменты реальной вариации травы соответствуют зеленому каналу маски, который представляет собой квадратную зеленую рамку маски; в третьем столбце, фрагменты красных оттенков соответствуют синему каналу маски, который является рамками синих ромбов; а в четвертом столбце фрагменты желтых оттенков соответствуют альфа-каналу маски, который является остальными черными областями (обратите внимание, что эти части не будут повторно отображаться, так как там нет данных об альфа-цвете).

Результат будет следующим:

Рандомизация травы#

Для рандомизации внешнего вида травинок используются два типа значений:

  • Mean Value (задается в основном поле параметра: Min/Max Bend, Min/Max Height, Aspect, Offset) определяет среднее значение распределения. Четыре поля соответствуют красному, зеленому, синему и альфа-каналам диффузной текстуры соответственно. Используя это значение, разработчик может установить контрольные точки для управления параметром.

  • Spread Value определяет диапазон возможного изменения параметра. Четыре поля соответствуют красному, зеленому, синему и альфа-каналам диффузной текстуры соответственно. Чем выше значение, тем разнообразнее конечный результат.

    Примечание
    Значение разброса является необязательным: если установлено значение 0, оно не влияет на процесс моделирования. В таком случае равномерно используется только среднее значение.

Пример использования Spread Value приведен для параметра Min/Max Height. Он применяется аналогично параметрам Min/Max Bend, Aspect и Offset.

Средние и разбросанные значения параметров рандомизации grass

Probability#

Вероятность появления фрагмента grass, принадлежащего определенному каналу маски (горизонтальная строка), зависит от параметра Probability. Вариации вида (вертикальный столбец) отображаются случайным образом.

Вероятность появления слотов травы, принадлежащих красному, зеленому, синему и альфа-каналам маски соответственно

Давайте проверим несколько вариантов параметра Probability для следующей диффузной текстуры:

Белая текстура RGBA8 по умолчанию используется в качестве маски (поскольку в диффузной текстуре 4 фрагмента, мы устанавливаем Num Textures равным 4). Значение маски равно white = 1, следовательно, вся область травы будет заполнена.

На рисунках ниже показаны различные варианты параметра Probability:

Probability = 1 1 1 1
Probability = 0.1 0 0 1
Probability = 0 1 0 1
Probability = 0.1 0.3 0.7 1

Min/Max Bend#

Изгиб означает наклон травяного квадрата вперед или назад под определенным углом.

Min Bend - это среднее значение уклона травы в областях с наименьшей плотностью в соответствии с маской. Max Bend - это среднее значение уклона травы в областях с наибольшей плотностью в соответствии с маской. Как Min/Max Bend, так и их значения spread устанавливаются для каждого столбца диффузной текстуры отдельно.

Min/Max Height#

Min Height - это среднее значение высоты травы в областях с наименьшей плотностью в соответствии с маской. Max Height - это среднее значение высоты травы в областях с наибольшей плотностью в соответствии с маской. Как Min/Max Height, так и их значения spread устанавливаются для каждого столбца диффузной текстуры отдельно.

Давайте сравним следующие примеры:

Если мы установим значение Min Height равным 1, а значение Spread равно 0.3, интервал высоты травы в областях с наименьшей плотностью составит от 0.7 (т.е. 1 - 0,3) до 1.3 (т.е. 1 + 0,3), что означает, что каждый травяной квадрат имеет свою собственную высоту, выбранную случайным образом из этого интервала. При минимальном значении высоты, равном 1.2, и значении разброса 1 интервал высоты травы в областях с наименьшей плотностью составляет от 0.2 (т.е. 1,2 - 1) до 2.2 (т.е. 1,2 + 1), это означает, что каждый травяной квадрат имеет свою собственную высоту, выбранную случайным образом из этого интервала.
Min Height = 1; Spread = 0.3
Min Height = 1.2; Spread = 1

Это работает так же для Max Height.

Для значения Max Height, равного 3, и значения разброса, равного 0.3, интервал высоты травы в областях с наибольшей плотностью составляет от 2.7 (т.е. 3 - 0,3) до 3.3 (т.е. 3 + 0,3), это означает, что каждый травяной квадрат имеет свою собственную высоту, выбранную случайным образом из этого интервала. Для значения Max Height, равного 3, и значения разброса, равного 1, интервал высоты травы в областях с наибольшей плотностью составляет от 2 (т.е. 3 - 1) до 4 (т.е. 3 + 1), это означает, что каждый травяной квадрат имеет свою собственную высоту, выбранную случайным образом из этого интервала.
Max Height = 3; Spread = 0.3
Max Height = 3; Spread = 1

Aspect#

Чтобы отобразить предполагаемый квадрат травы, в дополнение к высоте, у него также должна быть установлена ширина. Чтобы сохранить пропорции квадрата, ширина задается не напрямую, а с помощью параметра aspect. Таким образом, конечная ширина вычисляется путем умножения Max Height на Aspect.

Aspect устанавливается для каждого столбца диффузной текстуры отдельно. Как и параметр Height, значение Aspect может изменяться случайным образом, если в дополнение к значению Mean задано значение Spread. Например, установка значения spread равным 0 приводит к следующему результату:

  • Если для среднего значения задано значение 1, трава отображается в квадратных пропорциях, при этом высота равна ширине.
  • Если среднее значение равно 2, ширина квадрата травы в два раза превышает его высоту.
Aspect = 1; Spread = 0
Aspect = 2; Spread = 0

Offset#

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

Rotation#

Чередование травяных квадратов добавляет больше разнообразия. Этот параметр определяет поворот квадратов травы в градусах в произвольных направлениях. Он устанавливается значением mean (только положительным) и дополнительным значением spread (положительным или отрицательным), если требуется изменение. Значения устанавливаются для каждого столбца диффузной текстуры отдельно.

Слоты для текстур#

На одном поле может потребоваться имитировать траву, которая росла в хороших и плохих условиях, снимая молодые травинки и пожухлую солому. Диффузная текстура травы может иметь слоты 4(nbs)x(nbs)n, каждый из которых содержит отдельный пучок травы, растение или цветок. Количество горизонтальных строк в текстуре может быть от 1 до 4. Однако количество вертикальных столбцов может варьироваться в зависимости от способа определения распределения травы:

  • Если маска изображения используется для указания распределения плотности травы, количество столбцов диффузной текстуры может быть меньше , чем 4.

    Примечание
    Количество столбцов диффузной текстуры в этом случае определяется количеством каналов в текстуре маски (например, диффузная текстура должна иметь столбец 1, если используется маска R8).
  • Если для указания распределения травы используется mesh-маска , количество столбцов диффузной текстуры должно быть равно 4.
  • Если используются обе маски (маска изображения задает распределение плотности травы, а Mesh-маска используется для исключения некоторых областей, таких как дороги, количество столбцов диффузной текстуры также должно быть равно 4.

Параметр Num Textures задает количество горизонтальных строк с кластерами травы, растений или цветов, доступных в диффузной текстуре, и это значение не может превышать 4. После указания номера каждый кластер травы отображается как отдельный квадрат на поле.

4 Texture Slots; Num Textures = 1
8 Texture Slots; Num Textures = 2

Variation#

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

Два возможных варианта для травы (автоматическое горизонтальное переворачивание)

Ориентация квадратов травы#

Чтобы травяные квадраты повторяли рельеф, настраиваются следующие параметры:

  • Orientation. Травяной квадрат может быть ориентирован либо вдоль его собственного вектора нормали, либо вдоль вектора нормали его родительской ноды (обычно рельефа). Однако на крутых холмах трава, ориентированная вдоль нормали рельефа, может выглядеть неестественно (поскольку направление роста травы вверх), поэтому вам нужно будет выбрать подходящее значение для параметра Angle.

    На правом рисунке ниже параметр Angle установлен неправильно, и трава растет почти перпендикулярно склону:

    Многоугольники травы, ориентированные по нормали к объекту травы
    Травяные полигоны, ориентированные по нормали к объекту рельефа
  • Angle. Этот параметр влияет на распределение травы, которое меняется в зависимости от угла наклона грунта. Этот параметр имитирует естественную тенденцию травы укореняться на более ровных местах.
  • Intersection. Воспроизводя холмистый ландшафт, важно, чтобы трава повторяла рельеф, на котором она растет. Для того чтобы трава была нанесена на землю, необходимо следующее:

    1. Сделайте траву дочерним элементом ландшафта или любого произвольного меша (статического или динамического). Если в иерархии есть несколько нод между нодой ландшафта или меша и травой, пересечения все равно будут проверены.
    2. Включите опцию Intersection.

Размер травяного поля#

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

  • Size X задает длину участка травы вдоль оси X.
  • Size Y задает длину участка травы вдоль оси Y.

Этап для деления клеток#

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

Чтобы получить результирующее количество ячеек, Size поля (как по осям X, так и Y) разбивается с использованием значения Step.

Примечание
  • Size поля должно быть ровно разделено на Step. В противном случае, если есть остаток от деления, это может привести к визуальным артефактам и неожиданным визуальным эффектам.
  • Для каждой ячейки требуется DIP-вызов 1, поэтому, чем больше количество ячеек (т.е. чем меньше шаг), тем ниже производительность. Однако для создания одной большой ячейки травы требуется больше времени. Когда камера движется достаточно быстро, маленькие ячейки создаются одна за другой очень быстро и плавно, но большие могут заметно появляться в поле зрения и вызывать небольшую задержку рендеринга. Обычно значение Step устанавливается между 10 и 25 (для обычной травы; если трава используется в качестве удаленного LOD, значение World Clutter или Mesh Clutter, Step может отличаться).

Управление шагом разделения поля на ячейки позволяет изменять размер поля, не влияя на заданную плотность посадки травяных стеблей. С другой стороны, если мы изменим шаг и, следовательно, количество ячеек без изменения значения плотности, количество отображаемых квадратов травы будет другим.

Если значение Step слишком мало, а максимальное расстояние видимости велико, рендеринг ячеек занимает некоторое время, а количество вызовов DIP значительно увеличивается. С другой стороны, очень высокое значение Step вызывает скачки производительности из-за увеличения количества объектов в ячейке.

Подразделение ячейки#

Каждую ячейку также можно разделить на более мелкие части, указав значение Subdivision. Разделение обычно требуется, когда трава используется в качестве низкополигонального удаленного LOD леса, созданного с помощью World Clutter или ObjectMeshClutter с меньшим размером ячейки: параметр Subdivision подразделяет большие ячейки травы так, чтобы они соответствовали меньшим ячейкам беспорядка. Таким образом, позиции случайно разбросанных объектов будут совпадать с позициями самозванцев на траве. Диапазон доступных значений составляет от 1 до 32.

Маски для травяного поля#

Маска изображения для травяного поля#

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

Маска представляет собой текстуру RGBA8. Каждый канал этой текстуры управляет распределением травы по вертикальному столбцу диффузной текстуры grass (в диффузной текстуре может быть до 4 столбцов).

  • Красный канал определяет области роста для 1-го столбца текстуры. Если в вертикальном столбце есть несколько скоплений травы, они случайным образом распределяются по замаскированной области.
  • Зеленый — для 2-го столбца текстуры.
  • Синий - для 3-го столбца текстуры.
  • Альфа - для 4-го столбца текстуры.
Примечание
В случае, если в качестве маски используется текстура R8, RG8 или RGB8, диффузная текстура должна иметь только один, два или три столбца соответственно. Итак, если ваша диффузная текстура содержит, например, только 1 вертикальный столбец, следует использовать текстуру R8.

Для каждого канала в отдельности области, где трава не должна расти, имеют значение канала 0 (нет данных о цвете или альфа). Ненулевое значение канала создает травянистую зону: чем выше значение, тем гуще растет трава.

Маска изображения характеризуется следующими параметрами:

  • Threshold, который определяет, начиная с какой плотности (в соответствии с маской) должна расти трава.
  • Min value и Max value, которые задают диапазон плотности цвета.
  • Flip X и Flip Y, которые переворачивают текстуру по горизонтали и вертикали (соответственно).
Примечание
Чтобы нарисовать маску изображения непосредственно в сцене, используйте Mask Editor.

Минимальные и Максимальные значения маски#

В качестве решения для расширенного заполнения объектов и оптимизации потребления памяти к объекту можно частично применить маску. Это означает, что разные множественные объекты могут использовать одну и ту же маску, но использовать разные уровни.

По умолчанию каждый канал маски изображения определяет области и плотность роста в диапазоне плотности цвета [0;255]. Однако, используя Min value и Max value, вы можете изменить определенный диапазон плотности цвета, и часть маски, содержащая указанный диапазон плотности, будет использоваться для посева травы.

Например, существует следующая маска изображения R8:

Несколько объектов травы, представляющих траву разной высоты, могут совместно использовать эту маску следующим образом:

  • В диапазоне от 100 до 200 может быть сохранена плотность короткой травы. Часть маски изображения, в которой сохранен указанный диапазон цветовой градации, будет применена к объекту с короткой травой.
  • В диапазоне от 160 до 230 может быть сохранена плотность травы средней высоты.
  • В диапазоне от 190 до 255 может сохраняться плотность высокой травы.

Маска местности#

Так же, как и с помощью произвольной маски изображения, распределение плотности травы может быть определено с помощью ObjectLandscapeTerrain masks. Если объект Landscape Terrain присутствует в мире и имеет некоторые предоставленные маски, имена масок доступны в параметре Mask Terrain, поэтому вы можете указать определенную ландшафтную маску для каждого слота текстуры травы (тип травы).

Параметр местности маски

Распределение травы на основе ландшафтной маски. включен помощник Landscape Masks

Маска на основе меша#

Векторное маскирование позволяет создавать дороги, реки и т.д. с чрезвычайно высокой точностью, поскольку она не зависит от разрешения текстуры маски. Для травы можно установить mesh-маску, чтобы указать области, где должна или не должна расти трава.

Примечание
Меш для маски должна быть простым и плоским.

Меш, используемый в качестве маски

Маскирование на основе меша
Примечание
При использовании Mesh-маски для указания распределения травы количество столбцов диффузная текстура должно быть равно 4. В противном случае диффузная текстура будет нанесена неправильно.

Mesh-маску можно инвертировать, переключив флаг Inverse.

Обратная маскировка

Field Mask#

Любая область травяного поля может быть анимирована с помощью Field Animation. Field Spacer используется для указания областей травы, которые не должны отображаться. Такие участки травы задаются параметром Field Mask (окно Parameters → раздел Grass).

Примечание
Значение Field Mask, установленное для объекта grass, должно соответствовать значению Field Mask ноды Field, примененного к grass.

Смотрите пример анимации травы с помощью поля анимации здесь.

Плотность роста и рандомизация травы#

Чтобы добиться достаточной насыщенности травяного поля, параметр Density можно настроить. Плотность определяет, сколько квадратов травы должно быть отображено на единицу площади.

  • Чем выше значение, тем больше квадратов травы отображается и тем ближе они расположены. Но следует иметь в виду, что конечный результат также зависит от Step деления и количества ячеек, которые он определяет.

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

Примечание
Одно и то же значение Seed всегда генерирует одни и те же последовательности чисел.

Установка значения Seed необходима, когда в мире существует более одного объекта grass. Это позволяет расположить травяные квадраты по-разному, чтобы 2 квадрата не имели одинаковых координат.

Чтобы добиться преобладания одного типа травы над другими типами, вы можете использовать параметр Probability. Этот параметр задает вероятность рендеринга травы для каждого столбца диффузной текстуры: вы можете указать коэффициент вероятности для каждого столбца диффузной текстуры отдельно.

Например, если вы установите коэффициент вероятности равным 5 для 1-го столбца диффузной текстуры, квадраты травинок, сохраненные в ячейках этого столбца, будут появляться чаще.

Probability = 1
Probability for the 1st column = 5

Оптимизация травы#

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

Поле травы может быть уменьшено с помощью расстояния: вы можете установить флажок Thinning, чтобы не отображать случайные многоугольники травы на расстоянии Fade от травы.

Примечание
При изменении настроек, описанных выше, вы можете сравнить предыдущее и текущее количество треугольников травы: просто проверьте счетчик Triangles.

Выбор оптимального значения Step для деления клеток также важен при оптимизации grass. Для обычной травы (которая используется должным образом) оптимальный шаг находится в диапазоне [10, 25].

Использование травы в качестве низкополигонального ЛОДА#

При использовании объекта grass в качестве низкополигонального LOD (например, для создания удаленного LOD для леса) ячейки clutter и grass должны совпадать. Итак, вам нужно убедиться, что следующие параметры совпадают:

  • Seed обоих объектов, чтобы они располагались одинаково.
  • Size X и Size Y обоих объектов.
  • Clutter Step соответствует соотношению значений Step/Subdivision травы.
  • флаг Orientation включен/отключен для обоих объектов.
  • флаг Intersection включен/отключен для обоих объектов.
  • Flip X и Flip Y включены/отключены для обоих объектов (в случае использования маски изображения).
  • Inverse включен/отключен для обоих объектов (в случае использования Mesh-маски).
  • Min Value и Max Value обоих объектов (в случае, если используется маска изображения).
  • Angle, Threshold, Density и Probability обоих объектов.
Последнее обновление: 16.08.2024
Build: ()