Генерация барьерных островов

Автор оригинала: Scott Turner
  • Перевод
В декабрьских новостях об урагане Флоренс часто упоминались Внешние отмели — ряд барьерных островов на побережье Северной Каролины:


Барьерные острова — это плоские или глыбистые участки песка, формируемые волнами и прибоем параллельно побережью материка. Они часто имеют вид длинных цепочек, которые могут тянуться на многие десятки миль. Барьерные острова обычно разделены небольшими приливными протоками, и могут формировать лагуны между островами и материком.

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

Чтобы понять, почему это так, давайте взглянем на «ванильную» карту острова:


По сути, это круг, искажённый небольшим количеством низкочастотного шума, добавленного для разбиения круглой формы. Давайте теперь попробуем использовать шум, чтобы разбить побережье и сформировать прибрежные острова. Вот тот же остров с добавлением низкочастотного шума:


У него есть заливы и мысы. Элементы рельефа довольно большие, потому что я использовал низкочастотный шум, который меняется медленно. Однако шум недостаточно силён, чтобы создать острова. Давайте немного его усилим:


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


Это может дать нам очень изломанные береговые линии и небольшие острова вдоль побережья, но ничего, напоминающего барьерный остров.

Единственная причина этого в том, что шум не согласован по x и y, поэтому хотя в целом шум не случаен, создаваемые им формы случайны:


Для некоторых вещей это хорошо, но для создания конкретной формы, например, острова вдоль побережья, не подходит.

Как и в других случаях, когда мне нужно было сгенерировать определённую форму или область, необходимо создать маску требуемой формы, а затем использовать внутри маски шум. (Также можно использовать шум для искажения маски и придания ей более естественной формы.) Барьерные острова — это, по сути, длинные тонкие области, смещённые относительно побережья. Поэтому давайте создадим маску этой формы.

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


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

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


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


Два отрезка спроецированной линии пересекаются друг с другом и создают на полигоне устрашающую «восьмёрку». Это так называемая проблема параллельных кривых. Мы не можем просто сместить берег на какое-то расстояние, необходимо также решить проблемы, возникающие из-за острых внутренних и внешних углов.

Я поискал код на Javascript для решения этой проблемы, но единственный найденный пример (отсюда) потрясающе сбоил даже на довольно простых образцах. Поэтому я написал собственный. В целом решение заключается в том, чтобы смещать каждую точку по нормали, но затем проверять, создаёт ли новая точка отрезок, пересекающий какой-нибудь из уже существующих отрезков. Если да, то мы отсекаем петлю и вставляем новый отрезок, состоящий из точки пересечения и новой точки. В проверенных мной тестовых примеров эта система сработала для моих требований достаточно хорошо.

Итак, теперь я могу генерировать простые маски (без петель) для островов:


Это слишком равномерно, поэтому я искажу контуры:


Контуры могут в некоторых точках касаться берега, но это нормально, такое часто встречается у барьерных островов.

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


Теперь давайте попробуем добавить сушу. Для этого я подниму высоту любой локации суши (которые являются треугольниками Делоне) над уровнем моря:


Здесь стоит заметить пару аспектов. Во-первых, в левом верхнем углу есть довольно успешный барьерный остров. Однако непохоже, что остров хорошо заполняет полигон. Множество треугольников суши «включено» из-за наличия их центров внутри полигона. Это добавляет в форму острова случайность. Во-вторых, можно заметить, что два других острова были так близки к побережью, что просто слились с ним. Поскольку здесь я хочу создавать острова, то мне не нужно, чтобы такое происходило слишком часто, поэтому я настрою генерацию для получения большего водного зазора между береговой линией и островом. (Позже я добавлю проверку, чтобы этого не происходило.)


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

Если я увеличу ширину островов, оба эффекта исчезают, и я получаю более естественные острова, но без приливных проток:


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


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

В обоих этих методах есть хорошая вероятность того, что некоторые части острова будут сильно неровными:


Это происходит, потому что контур пересекает две стороны (а иногда и все три стороны) лежащих в основе треугольников Делоне. Это неотъемлемая проблема использования триангуляции Делоне в генерации карт, но обсуждают её почему-то редко! Такое происходит на береговых линиях в моей игре не очень часто, потому что для уменьшения количества таких случаев я намеренно добавил этап сглаживания, но этот этап имеет тенденцию к уничтожению узких островов. Потенциальное решение заключается в создании чуть более широких островов и в использовании сглаживания — при правильной настройке так можно получить более тонкие острова без множества артефактов треугольников:


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

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


Единственное, что остаётся — дать островам названия и нанести их на карту. Единственный тонкий аспект здесь в том, что я не хочу давать названия всем островам в цепи барьерных островов. В реальных цепях барьерных островов у отдельных островов часто бывают названия, что приводит к хаосу на карте:


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


Обычно барьерные острова называют «отмелями» (Banks) или «валами» (Bars), поэтому эти слова встречаются в вариантах названий.

На этом примере показана потенциальная проблема с барьерными островами:


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

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 12

    +1
    Ради интереса попробовал сделать просто шум с отступом. Т.е. граница берега — это, допустим, 0.5, а барьер — градиент 0.5-0.51-0.52 помноженный на другой шум. Ну в принципе тоже работает, хотя качество никакое надо очень аккуратно подходить к настройкам шума и что-то может получиться. Зато сильно проще.
      +1
      Поигрался немного. Получилось не идеально, но немного похоже. Думаю, можно и лучше, но голова сейчас хреново соображает.
      image
      0
      А где можно опробовать-то этот генератор?
      +3
      Если посмотреть на карту реальных островов в начале статьи, то можно заметить что:
      1) со стороны океана очень гладкая линия
      2) со стороны материка есть пики, похожие на волнорезы-наоборот
      3) линия островов не повторяет линию берега
      4) линия острова похожа на вязку тугую веревку, которую проложили по контуру.
      5) Она не заходит в бухты, не делает изгибов на дельты и заливы, она это все усредняет при чем очень грубо.
      6) Расстояние от берега не фиксировано, на внешних углах, они почти вплотную к берегу, на внутренних углах и заливах они очень далеко.
      7) Соотношение толщины острова с толщиной дельт рек и самих рек иное. Или реки должны быть толще, или острова тоньше.
        0
        Если натренировать нейросеть на реальных картах, то она и не такие особенности заметит, правда нам не расскажет.
        Интересно, будет ли она рисовать красивые и реалистичные карты.
        0
        Барьерные острова — это плоские или глыбистые участки песка, формируемые волнами и прибоем параллельно побережью материка

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

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

            0
            остров в бухте

            А они как формируются и возникают?
            То что на фото — похоже на скалу, а не на отмель торчащую из воды как коса-переросток.
              +1
              ага, а есть еще намывные острова, которые создают люди
              есть коралловые рифы, у которых свой генезис
              есть вулканические острова, которые могут появиться за одну ночь
              в геологии очень много причин — нам придется симулировать весь земной шар с океаном, атмосферами и внутренним строением — заодно решим проблему прогнозирования погоды, цунами и землетрясений. Шутка.

              А про остров на фото — да, это скорее скалы. Я не знаю точной причины их возникновния, так как в 8 классе, простудившись в походе и болея на природе, окончательно решил идти в компьютерщики, а не геологи. Но в юго-восточной Азии их очень много. Многие выглядят еще круче — между Пхукетом и Пхи-Пхи в океане можно увидеть острова, похожие на ошибку генератора в Майнкрафте, или на башни с верхушками, заросшими лесом. Мне они, когда я их увидел, напомнили скалу зеленых драконов из замка лесных эльфов в третьих Героях

              В целом надо спрашивать — что мы хотим симулировать алгоритмом? Если отмели, то данный остров-скала не годится как сэмпл. Если реальную береговую линию с заливами — то вообще причин появления островов несколько больше. Поэтому Земля такая и красивая местами.
                +1
                А где можно про всё это кратко почитать?
                  0
                  Начните с вузовского учебника по общей геологии.
                  Сейчас проще всего ищется Короновский: я его не читал, слишком новый (ничего ужасного, просто я слишком рано родился. А так более новые учебники обычно полезнее, поскольку учитывают современные им достижения науки) — но на очень беглый взгляд вроде бы вполне себе ничего.
                  Например, вот PDF.

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

        Самое читаемое