Генерация местности - интерполяция между несколькими картами высоты биома - PullRequest
0 голосов
/ 18 октября 2018

В последнее время я прошел какое-то поколение ландшафтов, используя движок Unity и C #, я смог преодолеть большинство проблем, с которыми столкнулся, но этот застрял без эффективного решения:

прежде чем я объясню свою проблему, я объясню, чего я достиг;Используя перлин-шум, я смог создать сетку и применить разные высоты к ее вершинам, комбинируя несколько карт высот.Я также могу генерировать и уничтожать фрагменты ландшафта, а также управлять LOD фрагментов на основе позиции зрителя в целях оптимизации.Затем я обратился к системе распределения областей биома, для распределения областей я использовал комбинацию из 2 функций шума Перлина, представляющих уровни температуры и влажности, с распределением клеток вороной, мир делится на виртуальные квадраты по модулю, а другая функция шума Перлина -используется для создания функции, которая возвращает контрольную точку voronoi на основе виртуального квадрата, который она получает в качестве входных данных, до сих пор только алгоритм распределения контрольных точек voronoi, который я имел в виду, пока все хорошо ...

ДалееЯ хотел сделать местность более интересной (она предназначена для игры на выживание), поэтому я начал свой путь к созданию уникальной комбинации шумовых функций для каждого биома (каждой клетки вороной), но это будет не так просто ...швы между биомами наверняка начнут проявляться, и поэтому необходима система интерполяции биом, сначала я подумал, что простая весовая функция сделает всю работу, то есть для каждой вершины вычислит свое расстояние от соседнего элемента биома.ls и вычислите вес каждой ячейки в этой вершине: значение от 0 до 1, 0 = самый низкий эффект (точка биома действительно далеко, слишком далеко, чтобы иметь какое-либо влияние на вершину);1 = самый высокий эффект (точка биома находится в том же положении, что и вершина, таким образом, она будет иметь максимальный эффект на высоту вершины и будет исключительно составлена ​​из уникальной шумовой функции биома), а затем вычислит сумму умножения каждоговес биома на вершине с помощью функции шума биома в положении вершины (Примечание: сумма всех весовых точек биомов всегда должна быть 1).

Пример расчета веса для соседних точек:

An example of weight calculation for adjacent points

На рисунке: вес биома, на который указывает синяя стрелка, будет примерно 0,1f (малое значение, поскольку он находится далеко от точки отбора, поэтому он будетоказывают минимальное влияние на высоту точки отбора проб).Вес биома, на который указывает зеленая стрелка, будет около 0,45f.Вес биома, на который указывает розовая стрелка, будет примерно 0,45f (такой же, как у зеленого заостренного биома, потому что он находится на том же расстоянии от точки отбора).Оранжевая точка = точка выборки, для которой будут рассчитываться веса в соответствии с ней.

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

Пример карты высоты шума сотовой связи:

An example of Cellular noise heightmap

Небольшой кусок кода для очистки финальноговысота вершины:

float HeightAtPosition(float x, float z)
{
    //Returns an array containing information of all the adjacent biome 
    //control points(mainly their position and their biome type)
    BiomeControlPoint[] adjacentControlPoints = GetAdjacentBiomePoints(x, z);
    //Returns an array containing values between 0 and 1
    //Iputs: An array of all the adjacent biome points, a sample coordinate
    //Output: A float array containing the weight of each biome on the 
    //        coordinate(between 0 and 1)
    float[] weights = CalcWeights(adjacentControlPoints, new Vector2(x, z));
    float finalHeight = 0;
    for (int i = 0; i < adjacentControlPoints.Length; i++)
    {
        finalHeight += adjacentControlPoints[i] * weights[i];
    }
    return finalHeight;
}

Это было бы хорошим решением, если бы я мог сделать эти функции более эффективными: GetAdjacentBiomePoints (x, z) и CalcWeights (acentControlPoints, new Vector2 (x, z))

Другим методом, о котором я читал, была билинейная интерполяция, но я не совсем понял ее реализацию, поэтому я был бы рад узнать из другого источника.В этом видео обсуждается этот метод: https://www.youtube.com/watch?v=ujGW5y1x7Jg Создание Minecraft на C ++ / OpenGL - часть четвертая

Буду рад узнать от вас любую новую информацию и / или идеи :) Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Вы можете пойти другим путем:

  • сгенерировать уровни температуры и влажности для каждого пикселя
  • сгенерировать, насколько каждый биом соответствует этим значениям
    • предсчитать силукаждый биом в качестве 2-мерной таблицы поиска?
  • принять X лучших совпадений
  • нормализовать силы (сумма равна 1)
  • ваша уникальная функция шумаКомбинация представляет собой взвешенную сумму X лучших биомов

Лично я работаю с сеточными картами и интерполирую значение биома от маленькой карты с большими ячейками до большой карты с маленькими ячейками.Интерполяция там намного проще:

Извините, что этотакое Java.

0 голосов
/ 21 октября 2018

Вы можете попробовать взвешенную диаграмму Вороного.Моя реализация PHP: https://tetramatrix.github.io/awvd/.

...