Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Creación procedural Planetas

Iniciado por Portief, Febrero 13, 2018, 12:24:33 PM

Tema anterior - Siguiente tema
Febrero 13, 2018, 12:24:33 PM Ultima modificación: Febrero 14, 2018, 02:13:39 AM por Portief
Buenas, otra vez por aquí. Esta vez tengo un proyecto entre manos con un componente bastante grande de creación procedural. 
 
El juego tiene unas mecánicas especificas y bebe un poco de toda la corriente ahora que esta surgiendo en torno a No Man's Sky. Principalmente de momento estoy investigando un poco en la creación de superficies de planetas de forma procedural. Como lo voy a hacer con Unity y C# mi primer miedo es que no pueda administrar la gestión de memoria de forma optima ya que la carga va a ser grande. He visto por ahí proyectos que utilizan librerias en C (Planet Nomads). También observo dos formas de afrentarlo, a la hora de crear de forma procedural los mundos utilizar generadores de ruido mezclados sobre la superficie de una esfera, utilizar Height maps y bueno supongo que también se pueden utilizar implementaciones de la llamada  Superformula o derivados. Entonces planteo mis dudas y espero recomendaciones:
 
Como gestionar la memoria, alguna complementación mejor que otra, información respecto al tema... Estoy abierto a escuchar cualquier tipo de ayuda, gracias de antemano. 
 
Un saludo.

lo ideal es q tengas una funcion q te devuelva la forma del planeta con sus montañas, cañones y todo eso... luego generas la geometria del terreno obteniendo la altura de cada punto segun la distancia de vision q quieras... pintas las texturas x altura
como es una funcion de ruido nada se guarda en memoria, solo la geometria q vas creando y destruyendo en el camino x eso es muy eficiente

hola, no se lo estas implementandobtodo tu, o usas algun asset o libreria....
 
yo he dedicado un tiempo a la generacion procedural... he hecho varios metodos... pero siempre en superficies planas... terrenos... (como los terrain de unity...)
 
creando mis propios planos, y modificando los vertex via perlin noise (varias capas para crear las "octaves")... luego a raiz del resultado tambien genero la textura y la aplico... y dependiendo de ciertos datos de esa textura coloco vegetacion, arboles, rocas... 
 
con heightMaps agilizas el calculo pero requiere crear/guardar/almazenar las "texturas" y tambien habria luego que cargarlas cuando fuese necesario.... osea que no se si es mejor....
 
ah, pero ten en cuenta que los calculos se complican al querer hacerlo en mundos esfericos...  ya no son planos... ni pueden ser "cortados" en zonas cuadradas como ocurre con los planos.... que los vas montando en forma de cuadricula... y tambien se complica el calculo de las zonas vecinas (neigbour) para ajustar el sombreado y no se note el "corte"...
 
yo lo deje por imposible (de momento) y me resigne a crear mundos planos..., no esfericos, con relieves y montañas y lagos y rios y caminos y bosques.... pero "planos"....
 
...y los planetas no son asi....
 
ya le metere otro intento mas adelante a la generacion procedural en esferas...
 
si quieres puedes ver una demo de uno de mis sistemas procedurales en un post de un jueguillo que comence hace meses, aunque ahora lo tengo avandonado.... esta en proyectos/spaceship proyect... creo que se llamaba.... mira que nombre mas original le puse:)
 
graficamente no es una pasada... pero mi PC es muy viejuno y no tira mas...
 
saludos

Buenas de nuevo, lo primero gracias a los dos por el aporte y lo segundo voy a postear mis avances por aquí. Respecto a la creación de la superficie e visto tres tutoriales. En uno se creaba una esfera (Problema el pico de la esfera, terreno mallado de forma variada en geometría), en otra mediante un octaedro y por ultimo http://catlikecoding.com/unity/tutorials/cube-sphere/ redondeando un cubo. Este ultimo es el mejor. 
 
Despues de estos surgen varios problemas como el terreno cercano a ti es el que debes renderizar con mayor densidad de vertices y el resto con menor y otro tramo sin nada. 
 
Despues la formula del perling Noise esta dificil debido a que de momento no se aplicarla de forma guay sobre la superficie. Me genera cosas bastante mediocres. Cuidado con el borde de la maya que si habeis aplicado triangulos abiertos hay que juntarlos por codigo. No se como generare cosas como montañas y planicies que queden bien. Creo que para poder guardarme el ruido especifico sobre el planeta utilizare una semilla generada de forma aleatoria para posteriormente poder reproducir con los generadores siguiendo siempre la misma semilla en cada planeta. 
 
Otro tema es como conseguir las estructuras de superficies no continuas que conseguían en No mans sky, tipo puentes o cuevas aunque esto si que son continuas y tiene más sentido que se puedan conseguir mediante ruido aunque no tengo muy claro como.
 
Y otro tema es como corregir la escala porque evidentemente no me permite unity crear planeta del radio de la tierra 6371km. Lo he intentado pero el editor cuesta mover la cámara y bueno que tampoco creo que se deba hacer así. Aquí explican lo que han hecho pero no lo entiendo demasiado bien si me conviene esto: https://forum.unity.com/threads/how-can-i-zoom-scene-view-camera-further.440774/

Buenas de nuevo, vuelvo con una duda seria. Como comente he escogido el modo de generación de una malla cerrada sin costuras a partir de un cubo que acoplamos a una esfera mediante las normales http://catlikecoding.com/unity/tutorials/cube-sphere/. El primer problema serio que intento arreglar es la bajada de resolución de triángulos agrupándolos en triángulos más grandes. Estoy teniendo problemas con la cara de arriba ya que al tener que encontrar un bucle que consiga cerrarlas es difícil. De hecho no se si será viable de la forma planteada. 
 

 
Mi segunda duda y más importante es que a la hora de crear la malla  mesh.vertices = vertices; la asignación que intento efectuar con una resolución para mi decente es de una malla de más de 65000 vértices. Pero es un mundo y es que sino las montañas me quedan super cutres. Alguna idea para la solución?
 

Febrero 21, 2018, 03:32:13 PM #5 Ultima modificación: Febrero 21, 2018, 03:35:03 PM por Igor
no entiendo muy bien lo del cubo.... quieres hacer el planeta en una sola pieza? bueno, mis consejos son para terrenos planos (no esfericos).... no me he puesto nunca con los esfericos... 
 
bueno, lo terrenos se suelen hacer con varias mallas cuadradas colocadas en cuadricula... o al menos yo lo hago asi, luego tendras que calcular los "vecinos" para calcular bien las normales en las "uniones" entre las diferentes mallas... para que no se note la union...  si el player avanza recolo "adelante" las mallas que se quedan "atras"... y recalculos las elevaciones (relieve) de la malla... asi como su textura, arboles, etc... , y los vecinos y normales otra vez...
 
solo reposiciono/recalculo una malla cada vez... si usas mallas grandes igual es combeniente usar corrutinas... y dividir el "trabajo" a lo largo de varios frames...
 
hice uno usando mallas custom... y otro usando los "terrain" de unity, lo bueno de los terrain de unity es que la geometria se subdibide si esta cerca, o se reduce si esta lejos... y tambien que casi casi te ahorra tener que calcular las normales de la union, tan solo tienes que decirle quienes son los vecinos.... pero los terrenos de unity, a mi parecer, no son del todo buenos, te dejan realizar pocas alteraciones, y añadir funcionalidades extra es una tarea muy dificil.... (porejemplo cortar arboles o que la hierva arda y prenda los arboles cercanos y se expanda, puede resultar complejo con los "terrain")... ademas adaptarlo a una forma esferica puede tener vastantes complicaciones...
 
para las "alturas" yo uso tres "capas" de perlin noise (para generar como "octavas") y luego paso el valor por una curva animationcurve para poder variar el tipo de relieve... puedes hacer picos picudos, campos suaves, cañones, o incluso "terrazas" tipo "campos de arroz" tan solo cambiando la curva... luego cojiendo el valor de altura que te ha resultado puedes poner texturas diferentes dependiendo la altura a la que esta... arriba del todo nieve, luego roca, luego prados, y luego arena (suponiendo que hay agua/mar) .... y si corresponde colocar textura de prado igual toca poner un arbol, o "hierva" o arbustos.... y si toca texrura de roca igual poner pequeñas rocas, o grandes... etc....
 
ah, eso, lo del cubo... yo no usaria un cubo... usaria (al menos) 6 planos indibiduales con capacidad de reducir/apliar poligonos (como estas haciendo) digo al menos seis pero igual en cada "cara" del cubo ponia 3*3 o 5*5 planos.... aunque dependeria de la "resolucion" que desees en la malla...
 
pero claro, mis consejos son sin conocimiento sobre planetas procedurales (esfericos)... osea que igual en vez de ayudar te estoy liando mas....
 
 
 
oye muy chulo el enlace
 
Cita de: Portief date=1519216466...generación de una malla cerrada sin costuras a partir de un cubo que acoplamos a una esfera mediante las normales http://catlikecoding.com/unity/tutorials/cube-sphere/. 
   


esta muy bien.... me lo apunto

creo que lo q quieres hacer esta explicado aqui con codigo fuente en C:
 
http://paulbourke.net/geometry/circlesphere/
 
mira la seccion "Sphere Generation"
 

 
 
 
 
 
segun dice la esfera se vuelve mas uniforme si usas un octahedro como figura base:
 

ademas si ves todas las caras son triangulos q son mas naturales para el motor 3d, debe ser "facil" hacerle el LOD y mapear el perlin en esa bola xD
Cita de: Portief date=1519216466Mi segunda duda y más importante es que a la hora de crear la malla  mesh.vertices = vertices; la asignación que intento efectuar con una resolución para mi decente es de una malla de más de 65000 vértices. Pero es un mundo y es que sino las montañas me quedan super cutres. Alguna idea para la solución?
   


por eso te decia q mejor solo generas la geometria a una distancia del observador, de esa manera reduces los recursos

Hola, actualizo un poco mis dudas sobre el tema. Termine ya de hacer el LOD y más o menos esta bien a falta de optimizar un poco, aplique ruido Perlin de la biblioteca mathf, pero me hacia uno cosa muy rara en torno a un eje de la esfera, como una interferencia. Así que he optado por cogerlo de una librería LibNoise y aplico ruido Perlin y RidgeMultifractal pero no consigo acabados bonitos de montañas. Estoy probando en un plano primero para poder controlarlo pero nada. Haber si me podéis tirar un cable. 
 
Creo los parámetros y después aplico a mano también un bucle para suavizar el ruido:
 

 public Libnoise(float _lacunarity=2.0f, int _octaves=8,float _mult=0.8f,float _warp=0.25f)
    {
        //frq = _frq;
        warp = _warp;
        mult = _mult;
        //persistance = _persistence;
        lacunarity = _lacunarity;
        /*
                planes = new LibNoise.Generator.Perlin(0.03, 2.7, 0.5, 6, 1337, LibNoise.QualityMode.Low);
        mountains = new LibNoise.Generator.RidgedMultifractal(50, 4.5, 2, 137, LibNoise.QualityMode.Medium);
        */
        planes = new LibNoise.Generator.Perlin(30, 2.4, 3.5, 2, 1, LibNoise.QualityMode.Low);
        mountains = new LibNoise.Generator.RidgedMultifractal(50, 4.5, 2, 137, LibNoise.QualityMode.Medium);
    }
    public float SumNoise(Vector3 v)
    {
        float sum = 0.0f,freq=1.0f,amp=1.0f;
        for (int o = 0; o < octaves; o++)
        {
            sum += amp * (float)planes.GetValue(v);
            freq *= lacunarity;
            amp *= mult;
        }
        sum *= (float)mountains.GetValue(v * freq) * warp * octaves;
        return sum;
    }

 
Y creo el mesh plano y le aplico el ruido
 

Vector3[] vertices = new Vector3[(resolution + 1) * (resolution + 1)];
        Vector3[] normals = new Vector3[vertices.Length];
        Vector2[] uv = new Vector2[vertices.Length];
        float stepSize = 1f / resolution;
        for (int v = 0, y = 0; y <= resolution; y++)
        {
            for (int x = 0; x <= resolution; x++, v++)
            {
                vertices[v] = new Vector3(x * stepSize - 0.5f, 1, y * stepSize - 0.5f);
                float h = noise.SumNoise(vertices[v]);
                vertices[v] = vertices[v]*h;
                normals[v] = Vector3.back;
                uv[v] = new Vector2(x * stepSize, y * stepSize);
            }
        }
        mesh.vertices = vertices;
        mesh.normals = normals;
        mesh.uv = uv;

 
Sale una cosa rara que no tiene sentido. Agradezco cualquier ayuda. Saludos

Marzo 12, 2018, 05:39:31 PM #8 Ultima modificación: Marzo 12, 2018, 05:39:56 PM por lightbug
Cita de: Portief date=1520869372Así que he optado por cogerlo de una librería LibNoise y aplico ruido Perlin y RidgeMultifractal pero no consigo acabados bonitos de montañas
   


Que sería un acabado bonito? podrías subir algunas imágenes de como te quedó el resultado para entenderlo mejor.
 
Una pregunta, no podrías generar perlin para el resto y tener algunos patrones tuyos de montañas?, cosa de samplearlas y mezclarlas con el perlin, así te aseguras de que mantengan el acabado/forma que quieras, si le sumás n patrones de estos y si querés le metés aleatoriedad a cada uno te va a quedar algo bastante bueno. El perlin de por sí es algo mmmm... fijate que en una gdc aparece el creador de No man sky (si, no lo rajaron a balazos jajaj) y explica como pasó de "Full Perlin" a otro método que bien no recuerdo ahora (porque los resultados no le gustaban),  quizás podrías darle un vista si te interesa.
 
 

Marzo 15, 2018, 03:12:01 AM #9 Ultima modificación: Marzo 16, 2018, 03:45:49 AM por Portief
Gracias Lightbug he estado echando un vistazo a la conferencia que me dijiste y me esta ayudando bastante a perfeccionar todo. Creo que empiezo a conseguir a controlar el ruido y como tratarlo.
 
Ellos utilizan voxeles y después les dan forma, me he quedado un poco roto. Bueno iré poco a poco mejorando la cosa.
 
Segundo como comente conseguí juntar los chunks con mayor poligonaje con los de menor, interpolando los vértices para que quede junto. Sin embargo hace un extraño en la maya debido yo diría a las normales. Me podéis decir entre cual y cual vértice debería interpolar o hacer el dot para conseguir la normal correcta en la zona en la que ambos trozos se juntan. Adjunto imagen:
 



yo con el perlinNoise (Mathf), y unas animationCurves de esas, conseguia muchos resultados diferentes, dependiendo como construyas la curvas y las escalas de los perlin noises
 
utilizaba tres "capas" de perlin noise para simular "octabas" con diferente escala... cada una con su curva que alteraba el resultado del perlin noise...
 
ah, sobre las "normals" creo que "mesh" tiene una funcion calculateNormals, y otra para los "bounds" (que tambien hay que recalcularlos al cambiar el "relieve" de al pieza)... que te lo hacen automatico.... 
 
...este "post" me resulta muy interesante... pero ahora mismo estoy terminando otro proyecto y no quiero despistame demasiado...
 
pero retomare este tema en cuanto pueda, quiero poder hacer planetas procedurales (spheres)... y no solo limitarme a "terrenos" (plains)...
 
la idea de hacer una esfera basada en un cubo me parece genial, no se me ocurrio cuando inicie mis andares en este tema de lo procedural... pero ahora que la se, intentare hacer algo yo tambien... 
 
y probare tu codigo a ver que tal...
 
...cuando acabe con lo otro...

Vale ya he actualizado las imágenes. Creo que no me he explicado del todo bien. Sabría como realizar las normales el problema es que la unión son dos objetos. Uno no sabe que es vecino del otro. Desde uno no puedo acceder a los vértices del otro. Las normales las calculo automáticamente, pero la unión como veis es rara. Creo que es un problema de normales como he dicho pero parece que también es de sombras.

ah vale.... tendrias que acceder alos verticess del otro....
 
o hacer trampa... y hacer el mesh una fila mas largo (por cada lado) para calcular la normal.... y luego, una vez calculado, borrar esa linea de mas.... (supuestamente esa fila de mas se "sobrepondria" (pondria encima) del mesh vecino...  entinces podrias calcular las normals de esa "junta" o "union" ... despues borrando esos triangulos extra, que estan "repes" y superpuestos.... 
 
 

otra posible solucion "trampa" seria hacerlo todo "flat shading" y entonces no se notaria la union... 

Etiquetas: