Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: gdl en 19 de Marzo de 2005, 11:01:46 PM

Título: Simulando Agua
Publicado por: gdl en 19 de Marzo de 2005, 11:01:46 PM
 Vamos a ver si alguien por ahí tiene más imaginación que yo porque esto me está matando. Estoy intentando hacer un simulador planetario con la orografía, la hidrosfera, etc. Hasta ahora he creado las montañas con ruido Perlin que queda muy bien. El problema lo tengo con el agua.

Supongamos que tengo un array lleno de agua ¿vale? De una dimensión para simplificar. Digamos

int agua[32];

Donde cada valor significa la altura que tiene el agua.

Ahora lo que quiero hacer es "equilibrar" el agua usando únicamente elementos adyacentes.

Por ejemplo:

for(int i=0;i<31;++i)
{
 int d=agua[i+1]-agua[i];
 agua[i]+=d/2;
 agua[i+1]-=d/2;
}


El problema es que al usar aritmética entera (desafortunadamente imprescindible) me quedan escaloncitos de uno. Si el array agua fuera

3,4,5,6,7,8,9,10

El valor d es siempre 1 y d/2=0.

Si intentamos (d+1)/2 entonces, falla cuando es descendente.

Una solución aceptable por ahora sería que la diferencia entre el mayor y menor valor sea de 1. Luego complicaremos un poco la cosa poniendo un array de tierra debajo del agua (y deberían quedarse lagunas en las zonas cóncavas de la tierra).

¿Alguna idea? :blink:  
Título: Simulando Agua
Publicado por: StraT en 19 de Marzo de 2005, 11:26:26 PM
 Y si en vez de int usas float?

Saludos
Título: Simulando Agua
Publicado por: ethernet en 19 de Marzo de 2005, 11:29:58 PM
 
Citar
El problema es que al usar aritmética entera (desafortunadamente imprescindible) me quedan escaloncitos de uno

Si usas aritmética entera como mínimo te quedarán escaloncitos de uno, no entiendo el problema.

Si quieres que no te pase eso haz que la distancia mínima entre uno y otro sean 2, o sea, multiplica por dos el array. Otra solución que se me ocurre es que si el salto es uno pues desplaces el agua un valor de 0 ó 1 (a tu gusto o quizás aleatorio).

Desde luego valores como 0.5 no vas a poder tener, por eso no entiendo lo que te pasa, quizás una imagen... y de paso así nos muestras lo que estás haciendo :)

Título: Simulando Agua
Publicado por: _Grey en 20 de Marzo de 2005, 12:00:48 AM
 Si es impresciondible usar aritmetica entera, podrias usar punto fijo.

Saludos.
Título: Simulando Agua
Publicado por: gdl en 20 de Marzo de 2005, 12:25:31 AM
 Voy a ver con punto fijo 8+8. El gran problema es el tamaño del mundo: 4096x4096 son 16Megas por byte de celda. La altura del agua es un byte, con punto fijo serán dos. Tampoco es tanto y otras soluciones que he probado usaban dos bytes también.

He de reconocer que no se me había ocurrido.

¡Te ofuscas cuando no te salen las cosas y muchas veces lo más simple es lo mejor!  (nooo)

¡Gracias!  :D  
Título: Simulando Agua
Publicado por: BeRSeRKeR en 20 de Marzo de 2005, 12:32:46 AM
 Yann L dió una gran charla hace un tiempo sobre simulación de agua. A lo mejor te sirve de algo.

Saludos.
Título: Simulando Agua
Publicado por: gdl en 20 de Marzo de 2005, 12:35:50 AM
 Para ethernet que pedía una imágen....

El mundo que genero hasta ahora sólo tiene montañas y estoy en poner los ríos.

(http://www.arrakis.es/~gdl/MiniMundo.png)

Esta es una miniversión de 256x256, el mundo total tiene 256 bloques como este.

Cuando le paso el ciclo del agua (evaporar de los océanos y lluvia uniforme) el agua de los océanos sufre del efecto escalón mencionado.

(http://www.arrakis.es/~gdl/MiniMundo2.png)

Eso sí, se empiezan a ver lagos y ríos anchos (supongo que se estrecharán cuando programe la erosión).
Título: Simulando Agua
Publicado por: gdl en 20 de Marzo de 2005, 12:46:18 AM
 
Cita de: "BeRSeRKeR"Yann L dió una gran charla hace un tiempo sobre simulación de agua. A lo mejor te sirve de algo.

Saludos.
Esta charla está enfocada en simulación en tiempo real de la ecuación de onda que conforman las ecuaciones de Navier-Stokes. En mi caso no me interesa la ecuación de onda, sólo la asintótica de dispersión (parecida a la de transmisión de calor). Mientras la ecuación de onda es hiperbólica e inestable, la de dispersión no lo es ¡¡si fuera en aritmética real!! Desafortunadamente en aritmética entera no hay unicidad en la solución y se me estabiliza con los escalones arriba mencionados.

En cualquier caso, la charla es realmente interesante. :D

Gracias por el link.
Título: Simulando Agua
Publicado por: ethernet en 20 de Marzo de 2005, 09:54:24 AM
  (ole) muy interesante, unas preguntillas... :)

El proyecto es para el PFC ?
Qué algoritmo usas para generar los mapas?

saludos
Título: Simulando Agua
Publicado por: gdl en 20 de Marzo de 2005, 12:03:23 PM
 
CitarEl proyecto es para el PFC ?

La idea es tener un generador automático de mundos para un jueguecillo (como no podía ser de otra manera en estos foros).

CitarQué algoritmo usas para generar los mapas?

Una especie de ruido Perling. El código es muy corto, te lo pongo:

int Noise(int x, int y, int a, int o)
{
   int n = x + y * 57 + o*37;
   n = (n<<13) ^ n;
   return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)%a-a/2;
}

int SNoise(int x, int y, int a, int o, int n)
{
   int m=SIDE/n;
   int xi=x/n;
   int yi=y/n;
   int xf=x%n;
   int yf=y%n;

   int v1=Noise(xi%m,yi%m,a,o);
   int v2=Noise((xi+1)%m,yi%m,a,o);
   int v3=Noise(xi%m,(yi+1)%m,a,o);
   int v4=Noise((xi+1)%m,(yi+1)%m,a,o);

   return (v1*(n-xf)*(n-yf)+v2*xf*(n-yf)+v3*(n-xf)*yf+v4*xf*yf)/n/n;
}

void PerlinPass(Map<char> &r, int a, int n)
{
   int o=rand();
   int x=rand();
   int y=rand();
   for(int i=0;i<SIDE;++i)
    for(int j=0;j<SIDE;++j)
     r(i,j)+=SNoise(i+x,j+y,a,o,n);
}


La idea es la siguiente:

Noise() te da un valor aleatorio para cada posición x,y. De amplitud a, con una semilla o y de media cero.
SNoise() te interpola entre cuatro valores (x/n,y/n), (x/n+1,y/n), (x/n,y/n+1) y (x/n+1,y/n+1). Se puede ver n como la resolución.
PerlinPass() te suma a cada punto del mapa un ruido suavizado (SNoise()) con una resolución n y amplitud a. Los rand() son para que no haya coincidencia de vértices a distintas resoluciones (que queda muy feo).

El ruido Perlin se obtendría con algo así como

   PerlinPass(R,128,64);
   PerlinPass(R,64,16);
   PerlinPass(R,32,8);
   PerlinPass(R,16,4);
   PerlinPass(R,8,2);


Donde tanto n como a son proporcionales (en el caso de usar frecuencias a=k/f).

Luego ponemos el agua. Si la roca está por encima del agua pinto de verde y si el agua está por encima de la roca de azul.

¡Y ya'stá! :D
Título: Simulando Agua
Publicado por: ethernet en 20 de Marzo de 2005, 12:28:57 PM
 Aja, interesante, quizás te interese un libro que trata sobre estas cosas: "texturing and modeling: a procedural aproach"

saludos
Título: Simulando Agua
Publicado por: StraT en 20 de Marzo de 2005, 05:11:24 PM
 Y si pones el azul oscuro más claro y sobretodo, muchisima más tierra?

Saludos
Título: Simulando Agua
Publicado por: gdl en 20 de Marzo de 2005, 09:37:04 PM
 
Cita de: "StraT"Y si pones el azul oscuro más claro y sobretodo, muchisima más tierra?

Saludos

Pues queda una cosa así (aunque no con mucha más tierra):

(http://www.arrakis.es/~gdl/MiniMundo3.png)

También he puesto el perfil de la mitad del mapa para que se vea lo que hay debajo de la tierra:

Gris -> Roca madre
Celeste -> Tierra con aguas subterráneas
Verde -> Tierra seca
Azul -> Aguas superficiales
Título: Simulando Agua
Publicado por: StraT en 20 de Marzo de 2005, 09:43:42 PM
 Y has pasado el ciclo del agua con los cambios que te dije?

Por cierto, en la foto de perfil veo zonas de agua por encima del mar.

Saludos
Título: Simulando Agua
Publicado por: gdl en 21 de Marzo de 2005, 09:43:27 AM
 
CitarY has pasado el ciclo del agua con los cambios que te dije?

Sí, está cambiado. Ahora hay mucha más precisión, pero sigue habiendo desniveles en el agua. Muchos menos, eso sí.

CitarPor cierto, en la foto de perfil veo zonas de agua por encima del mar.

Son aguas subterráneas que se mueven mucho más lentamente y casi siempre se quedan por encima del nivel del mar. Cuando salen al exterior (manantiales) van más rápidas y forman ríos.
Título: Simulando Agua
Publicado por: tamat en 21 de Marzo de 2005, 11:07:14 AM
 El tema generacion de terrenos siempre me ha gustado mucho.
Conoces esta libreria? libnoise, va muuuy bien.

Y de paso te recomiendo que le eches una ojeada al World Machine, ideal si te va el tema erosion
Título: Simulando Agua
Publicado por: ethernet en 21 de Marzo de 2005, 03:26:12 PM
 tamat: muy buenos los enlaces :)
Título: Simulando Agua
Publicado por: gdl en 21 de Marzo de 2005, 05:01:52 PM
 Están magníficos los screenshots del World Machine.  (uoh)

¡¡Gracias por millones, tamat!!
Título: Simulando Agua
Publicado por: StraT en 21 de Marzo de 2005, 05:30:48 PM
 Puedes enseñarnos una imagen del resultado en perspectiva?  (genial)

Saludos
Título: Simulando Agua
Publicado por: gdl en 21 de Marzo de 2005, 06:32:58 PM
 
CitarPuedes enseñarnos una imagen del resultado en perspectiva?

La verdad es que tendría que hacer un renderizador y eso es difícil.  (asco)

¿No hay por ahí ningún programa al que le pases los heightmaps y te haga el rendering?
Título: Simulando Agua
Publicado por: gdl en 21 de Marzo de 2005, 08:02:33 PM
 He encontrado una animación que muestra algo parecido a lo que quiero hacer.

El código fuente está aquí.

Título: Simulando Agua
Publicado por: ethernet en 21 de Marzo de 2005, 09:36:35 PM
Cita de: "gdl"
CitarPuedes enseñarnos una imagen del resultado en perspectiva?

La verdad es que tendría que hacer un renderizador y eso es difícil.  (asco)

¿No hay por ahí ningún programa al que le pases los heightmaps y te haga el rendering?
blender :^P
Título: Simulando Agua
Publicado por: Sacrifai en 21 de Marzo de 2005, 09:56:04 PM
Cita de: "gdl"
CitarPuedes enseñarnos una imagen del resultado en perspectiva?

La verdad es que tendría que hacer un renderizador y eso es difícil.  (asco)

¿No hay por ahí ningún programa al que le pases los heightmaps y te haga el rendering?
Y el terragen creo que tambien  :D .