2011-04-07 15 views
10

Estoy trabajando con Perlin Noise para un algoritmo de generación de mapas de altura, me gustaría envolverlo alrededor de los bordes para que se pueda ver como continuo ... ¿hay una manera simple o un truco para hacerlo? ? Supongo que necesito algo así como un ruido esférico para que se enrolle horizontal y verticalmente. También sería feliz con solo 1 eje de ajuste, pero dos serían mejores.Envolviendo 2D perlin noise

Por ahora estoy usando el algoritmo clásico en el que puede configurar cuántas octavas quiere agregar y cuáles son los multiplicadores utilizados para cambiar la amplitud y la frecuencia de las ondas entre cada octava sucesiva.

¡Gracias de antemano!

+0

Usted no está tratando de construir mundos de Minecraft periódicos, ¿verdad? : D – Cephron

+0

Por supuesto que no estoy tratando de hacerlo, aunque sabía que alguien lo habría dicho :) (entonces también es 2D, no en 3D) – Jack

Respuesta

7

El ruido de Perlin se obtiene como la suma de las formas de onda. Las formas de onda se obtienen interpolando valores aleatorios, y las formas de onda de octava más alta tienen factores de escala más pequeños mientras que los valores aleatorios interpolados están más cerca el uno del otro. Para que se ajuste, solo necesita interpolar correctamente alrededor de los ejes yy de la forma toroidal habitual, es decir, si su eje X se extiende de x_min a x_max, y el punto aleatorio más a la izquierda (que se está interpolando) es en x0 y la derecha en x1 (x_min < x0 < x1 < x_max), el valor de los píxeles interpolados derecho a x1 y a la izquierda de x0 se obtiene interpolando de x1 a x0 (envolviendo los bordes).

Aquí pseudocódigo para una de las octavas que utiliza interpolación lineal. Esto supone una matriz de 256 x 256 donde el tamaño de la rejilla de ruido Perlin es una potencia de dos píxeles ... solo para que sea legible. Imagine, por ejemplo, tamaño == 16:

wrappable_perlin_octave(grid, size): 
    for (x=0;x<256;x+=size): 
    for (y=0;y<256;y+=size): 
     grid[x][y] = random() 
    for (x=0;x<256;x+=size): 
    for (y=0;y<256;y+=size): 
     if (x % size != 0 || y % size != 0): # interpolate 
     ax = x - x % size 
     bx = (ax + size) % 256 # wrap-around 
     ay = y - y % size 
     by = (ay + size) % 256 # wrap-around 
     h = (x % size)/size # horizontal balance, floating-point calculation 
     v = (y % size)/size # vertical balance, floating-point calculation 
     grid[x][y] = grid[ax][ay] * (1-h) * (1-v) + 
         grid[bx][ay] * h * (1-v) + 
         grid[ax][by] * (1-h) * v + 
         grid[bx][by] * h * v 
+1

Encontré que esta información era igualmente útil: http: //webstaff.itn. liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#toc-tile –

+0

Creo que esto sufre de artefactos "confusos" en el medio de cada celda de rejilla Perlin como se describe aquí: http: //www.gamedev.net/blog/33/entry-2138456-seamless-noise/ y aquí: http://staffwww.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/. (El primer enlace también describe una mejor solución.) – Leftium

+0

La respuesta anterior no tiene sentido, porque el segundo ciclo va en pasos de 'tamaño', y luego el cálculo del módulo debe ser cero en cada paso. ¡Así que nunca se ha llamado al cálculo principal! – Alex