Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Simulando Agua

Iniciado por gdl, 19 de Marzo de 2005, 11:01:46 PM

« anterior - próximo »

gdl

 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:  

StraT

 Y si en vez de int usas float?

Saludos
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

ethernet

 
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 :)


_Grey

 Si es impresciondible usar aritmetica entera, podrias usar punto fijo.

Saludos.

gdl

 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  

BeRSeRKeR

 Yann L dió una gran charla hace un tiempo sobre simulación de agua. A lo mejor te sirve de algo.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

gdl

 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.



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.



Eso sí, se empiezan a ver lagos y ríos anchos (supongo que se estrecharán cuando programe la erosión).

gdl

 
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.

ethernet

  (ole) muy interesante, unas preguntillas... :)

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

saludos

gdl

 
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

ethernet

 Aja, interesante, quizás te interese un libro que trata sobre estas cosas: "texturing and modeling: a procedural aproach"

saludos

StraT

 Y si pones el azul oscuro más claro y sobretodo, muchisima más tierra?

Saludos
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

gdl

 
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):



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

StraT

 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
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

gdl

 
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.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.