VoxelEngine/doc/ru/world-generator.md
2024-10-16 03:08:40 +03:00

13 KiB
Raw Blame History

Генератор мира

Основные понятия

Понятия используемые далее по тексту.

  • Комбинируемый массив/объект - TOML или JSON файл, который комбинируется из нескольких версий в разных паках, что позволяет добавлять в него данные извне. Поля комбинированного объекта перезаписываются в порядке от первого к последнему, так же, как и другие ресурсы в паках. В случае комбинируемого массива, проверка на дубликаты не выполняется.
  • Биом - информация, определяющая то, из каких блоков и какими слоями генерируется ландшафт, а так же набор растений, структур.
  • Растение - случайно расставляемый на поверхности блок.
  • Малая структура - структура, размер которой не превышает размера чанка. Пример: деревья.

Файл конфигурации

Генератор мира распознается при наличии файла generators/имя_генератора.toml. Другие файлы, относящиеся к генератору, должны находиться в директории generators/имя_генератора.files/:

  • biomes.toml - объявления биомов
  • structures.toml - объявления структур
  • script.lua - скрипт генератора
  • fragments - директория в которой располагаются файлы фрагментов

Основные свойства, описываемые в файле конфигурации:

  • caption - отображаемое имя генератора. По-умолчанию генерируется из id.
  • biome-parameters - количество параметров выбора биомов (от 0 до 4). По-умолчанию: 0.
  • sea-level - уровень моря (ниже этого уровня вместо воздуха будут генерироваться слои моря (sea-layers)). По-умолчанию: 0.
  • biomes-bpd - количество блоков на точку карты параметра выбора биомов. По-умолчанию: 8.
  • heights-bpd - количество блоков на точку карты высот. По-умолчанию: 4.

Фрагменты

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

На данный момент, фрагмент может быть создан при помощи команды fragment.save, либо через функцию generation.create_fragment.

Фрагменты, используемые генератором, должны находиться в директории: generators/имя_генератора.files/fragments/

Структуры

Структура - набор правил по вставке фрагмента в мир генератором. На данный момент не имеет свойств, создаваясь в виде пустых объектов в файле generators/имя_генератора.files/structures.json. Пример:

{
    "tree0": {},
    "tree1": {},
    "tree2": {},
    "tower": {},
    "coal_ore0": {}
}

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

Биомы

Биом определяет то, из каких блоков и какими слоями генерируется ландшафт, а так же набор растений, структур.

Биомы объявляются в комбинируемом объекте: generators/имя_генератора.files/biomes.toml

Разберем структуру биома на примере леса из генератора base:demo:

[forest]
parameters = [
    {weight=1, value=1},
    {weight=0.5, value=0.2}
]
layers = [
    {below-sea-level=false, height=1, block="base:grass_block"},
    {below-sea-level=false, height=7, block="base:dirt"},
    {height=-1, block="base:stone"},
    {height=1, block="base:bazalt"}
]
sea-layers = [
    {height=-1, block="base:water"}
]
plant-chance = 0.4
plants = [
    {weight=1, block="base:grass"},
    {weight=0.03, block="base:flower"}
]
structure-chance = 0.032
structures = [
    {name="tree0", weight=1},
    {name="tree1", weight=1},
    {name="tree2", weight=1},
    {name="tower", weight=0.002}
]
  • ключ forest - имя биома
  • parameters - веса и центральные значения параметров для биома. См. раздел выбор биома. Количество записей должно соответствовать количеству параметров выбора биомов.
  • layers - слои блоков от верхнего к нижнему.
    • height - высота слоя в блоках. -1 используется для обозначения безразмерного (заполняющего) слоя, который может быть только один. Его высота вычисляется автоматически.
    • block - полное имя блока
    • below-sea-level - может ли слой быть сгенерированным ниже уровня моря (пример: дёрн). При значении false, при генерации ниже уровня моря, слой будет заменён на следующий.
  • sea-layers - слои океана. Положение верхнего слоя совпадает с высотой уровня моря.
  • plant-chance - вероятность генерации растения на блоке поверхности.
  • plants - растения, случайно расставляемые на поверхности.
    • weight - вес, напрямую влияющий на шанс выбора конкретного растения.
    • block - блок растения
  • structure-chance - вероятность генерации малой структуры на блоке поверхности.
  • structures - структуры, случайно расставляемые на поверхности.
    • name - имя структуры, объявленной в structures.json.
    • weight - вес, напрямую влияющий на шанс выбора конкретной структуры.

Параметры биомов

Параметр генератора biome-parameters определяет количество параметров биомов, используемых при их выборе (примеры: температура, влажность).

Карты значений параметров биомов генеруются так же, как и карты высот.

Требуется реализовать функцию:

-- x, y - позиция начала карты (в точках)
-- w, h - ширина и высота карты (в точках)
-- bpd  - (blocks per dot) число блоков на точку (масштаб)
function generate_biome_parameters(x, y, w, h, seed, bpd)
	-- создание карт высот (Heightmap) для каждого параметра биомов
	-- ...
	return картыерез_запятую
end

-- пример
function generate_biome_parameters(x, y, w, h, seed, s)
	-- карта температур
    local tempmap = Heightmap(w, h)
    tempmap.noiseSeed = seed + 5324
    tempmap:noise({x, y}, 0.04*s, 6)
    tempmap:pow(3)
    -- карта влажности
    local hummap = Heightmap(w, h)
    hummap.noiseSeed = seed + 953
    hummap:noise({x, y}, 0.04*s, 6)
    hummap:pow(3)
    
    return tempmap, hummap
end

Выбор биома

После генерации карт параметров для каждого биома вычисляются оценки по всем параметрам:

score = \frac{|V - V_b|}{W_b}

Где V - значение параметра, V_b центральное значение параметра для биома, W_b - вес биома для параметра.

Генератор выбирает биом с наименьшей суммой оценок для параметров.

Warning

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

В случае биомов, узор выглядит случайным из-за искривления этих 'поверхностей' шумом, используемым при генерации карт параметров.

Для избавления от эффекта можно либо скорректировать веса или значения параметров биомов, либо увеличить разницу в генерации карт параметров.

Heightmap (карта высот)

Heightmap это класс для работы с картами высот (матрицами чисел с плавающей точкой произвольного размера).

Конструктор

Конструктор карты высот требует указания целочисленных ширины и высоты.

local map = Heightmap(ширина, высота)

heightmap:dump(...)

Метод используемый для отладки, создает изображение на основе карты высот переводя значения из дипазона [-1.0, 1.0] в значения яркости [0, 255], сохраняя в указанный файл.

map:dump('export:test.png')

heightmap:noise(...)

Метод генерирующий симплекс-шум, прибавляя его к имеющимся значениям.

Зерно шума может быть указано в поле map.noiseSeed.

map:noise(
	-- смещение координат
	offset: {number, number},
	-- коэфициент масштабирования координат
	scale: number,
	-- число октав шума (по-умолчанию: 1)
	[опционально] octaves: integer,
	-- множитель амплитуды шума (по-умолчанию: 1.0)
	[опционально] multiplier: number,
	-- карта смещений координаты X при генерации шума
	[опционально] shiftMapX: Heightmap,
	-- карта смещений координаты Y при генерации шума
	[опционально] shiftMapY: Heightmap,
) -> nil

Визуализация шума с октавами 1, 2, 3, 4 и 5.

image

heightmap:cellnoise(...)

Аналог heightmap:noise генерирующий клеточный шум.

Зерно шума может быть указано в поле map.noiseSeed.

image

VoxelFragment (фрагмент)

Фрагмент создается вызовом функции:

generation.create_fragment(
	-- точка A
	a: vec3,
	-- точка B
	b: vec3,
	-- автоматически обрезать фрагмент, если возможно
	crop: bool
) -> VoxelFragment

Фрагмент может быть загружен из файла:

generation.load_fragment(
	-- файл фрагмента
	filename: str
) -> VoxelFragment

Фрагмент может быть сохранен в файл:

generation.save_fragment(
	-- сохраняемый фрагмент
	fragment: VoxelFragment,
	-- файл
	filename: str
) -> nil

Размер фрагмента доступен как свойство size.

Фрагмент может быть обрезан до размеров содержимого (воздух игнорируется) вызовом метода fragment:crop().

Структурный воздух

core:struct_air - блок, которые следует использовать в фрагментах для обозначения пустого пространства, которое не должно заполняться блоками при генерации в мире.