Создание точек из двумерного фрактального шума

Я использую многослойный шум Перлина для создания 2D-точек, используя метод из https://www.redblobgames.com/maps/terrain-from-noise/#trees. Однако я бы хотел, чтобы координаты точки были не ints, а floats. Для этого я реализовал переменную resolution:

List<Vector2> points = new List<Vector2> ();
int res = 10;
int R = 2;
for (int yc = 0; yc < height*res; yc++) {
    for (int xc = 0; xc < width*res; xc++) {
        float max = 0;
        for (int yn = yc - R; yn <= yc + R; yn++) {
            for (int xn = xc - R; xn <= xc + R; xn++) {
                float e = pointsMap.GetClampedValue((float)xn/res, (float)yn/res);
                if (e > max) { max = e; }
            }
        }
        if (pointsMap.GetClampedValue((float)xc/res, (float)yc/res) == max) {
            points.Add (new Vector2((float)xc/res, (float)yc/res));
        }
    }
}

pointsMap.GetClampedValue() возвращает float от 0 до 1.

При ширине и высоте 100, разрешении 10 и R = 2 выполняется 25 миллионов циклов for. Хотя код внутри циклов далек от оптимизации, код выполняется в разумные сроки с указанными выше настройками. Однако по мере увеличения разрешения, ширины, высоты и R время выполнения становится слишком большим.

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


person Jonan    schedule 26.04.2018    source источник
comment
Это может быть актуально: stackoverflow.com/questions/10159318/, не уверен, но взгляните.   -  person Doh09    schedule 26.04.2018
comment
Ваш код имеет разрешение^2 больше работы, поэтому он будет работать на несколько порядков медленнее даже при небольшом увеличении разрешения или размера. Было бы полезно узнать, для чего вы используете баллы - я могу придумать простую альтернативу, но она не подходит для определенных приложений.   -  person Pikalek    schedule 27.04.2018
comment
@Pikalek Я использую точки для размещения объектов в генераторе процедурного ландшафта. Я пытался использовать выборку диска Пуассона, но мне нужен алгоритм, чтобы возвращать одни и те же точки каждый раз, когда осуществляется доступ к определенной области, если это имеет смысл - поэтому я использую карту шума.   -  person Jonan    schedule 28.04.2018
comment
@ Джонан, нет, для меня это не имеет смысла. Как и в случае с шумом Перлина, если вы используете одно и то же начальное число выкупа для области, вы получите ту же дискретную выборку Пуассона для этой области. Немного, если вы все еще хотите придерживаться шума Перлина, я перечислю модификации, которые могут работать.   -  person Pikalek    schedule 28.04.2018


Ответы (1)


Если вы хотите придерживаться чего-то, что близко к учебнику, на который вы ссылаетесь, но вам нужны координаты с плавающей запятой, а не десятичные координаты, самое простое решение — просто добавить случайное значение в диапазоне [0,1):

Random rng = new Random(regionSeed);
List<Vector2> points = new List<Vector2> ();
for (int yc = 0; yc < height; yc++) {
  for (int xc = 0; xc < width; xc++) {
    double max = 0;
    // there are more efficient algorithms than this
    for (int yn = yc - R; yn <= yc + R; yn++) {
      for (int xn = xc - R; xn <= xc + R; xn++) {
        double e = value[yn][xn];
        if (e > max) { max = e; }
      }
    }
    if (value[yc][xc] == max) {
      list.add( new Vector2(xc+rng.NextDouble(),yc+rng.NextDouble()) );
    }
  }
}
person Pikalek    schedule 28.04.2018