Jump to content
Sign in to follow this  
Jose134

Caras de mesh generado miran en dirección incorrecta

Recommended Posts

Hola a todos, tengo un codigo que genera varios meshes pero me ha surgido un problema y es que algunas caras miran en la direccion incorrecta y por tanto solo se ven si te situas dentro del mesh.

Creia que el problema estaba en las normales pero tras arreglarlas sigue ocurriendo, tambien he leido que puede ser por el orden en el que se definen los vertices de los triangulos pero tras varios intentos me siguen dando problemas.

Les dejo algunas imagenes y el codigo.

(Rosa = normals; Verde = edges (solo estan representados los que estan a la altura del suelo); Negro = vertices)

normals.PNG3d.PNG

 

Calculo de vertices y normales

//Generates the vertices and the normals
var vertices = new Vector3[sector.Count * 2];
var normals = new Vector3[vertices.Length];

for (int i = ; i < sector.Count; i += 2)
{
	//Calculates the vertices of a whole face
  	vertices[i * 2]     = new Vector3(sector[i].x, , sector[i].y);
    vertices[i * 2 + 1] = new Vector3(sector[i + 1].x, , sector[i + 1].y);
    vertices[i * 2 + 2] = new Vector3(sector[i].x, 10, sector[i].y);
    vertices[i * 2 + 3] = new Vector3(sector[i + 1].x, 10, sector[i + 1].y);

    //Takes calculated vertices to make an edge of the mesh's face
    var a = vertices[i * 2];
    var b = vertices[i * 2 + 1];
    var ab = b - a;

    //Calculate the two possible normals for the face
    var n1 = new Vector3(-ab.z, ab.y, ab.x);
    var n2 = new Vector3(ab.z, ab.y, -ab.x);
    n1.Normalize();
    n2.Normalize();

    //Calculates the distance from the Vertice + Normal Vector to the sector defining point
    var d1 = Vector3.Distance(a + n1, new Vector3(point.x, , point.y));
    var d2 = Vector3.Distance(a + n2, new Vector3(point.x, , point.y));

    //Chose which normal to use in function of the distances
    var n = d1 > d2 ? n1 : n2;

    //Sets the calculated normal
    normals[i * 2] =     n;
    normals[i * 2 + 1] = n;
    normals[i * 2 + 2] = n;
    normals[i * 2 + 3] = n;
}

 

Calculo de tris

//Calculates the triangles
var triangles = new int[vertices.Length / 4 * 6];

for (int i = ; i < vertices.Length; i += 4)
{
	triangles[i / 4 * 6]     = i + 3;
    triangles[i / 4 * 6 + 1] = i + 1;
    triangles[i / 4 * 6 + 2] = i;

    triangles[i / 4 * 6 + 3] = i + 3;
    triangles[i / 4 * 6 + 4] = i;
    triangles[i / 4 * 6 + 5] = i + 2;
}

 

Alguna idea de por que ocurre esto? Como lo podria arreglar?

Share this post


Link to post
Share on other sites
7 hours ago, Jose134 said:

Alguna idea de por que ocurre esto? Como lo podria arreglar?

EN teoria y de lo que recuerdo de lo que hice de ."obj" las normales son otra cosa y no depende de los vertices ni de los indices (o triangulos como llama Unity), es decir que si invertis las normales de tu codigo todo se da vuelta? hace un -n para ver que pasa.

Share this post


Link to post
Share on other sites
hace 3 minutos, lightbug said:

EN teoria y de lo que recuerdo de lo que hice de ."obj" las normales son otra cosa y no depende de los vertices ni de los indices (o triangulos como llama Unity), es decir que si invertis las normales de tu codigo todo se da vuelta? hace un -n para ver que pasa.

no puedo comprobar que las caras salgan exactamente invertidas al usar -n ya que los meshes son mas o menos aleatorios y cambian cada vez que ejecuto el programa pero he probado y creo que no influye. La mayoria de las caras se pueden ver si miras hacia el eje Z positivo y apenas se ve ninguna cuando miras desde atras y esto no cambia al usar -n por lo que supongo que no influye en la direccion de las caras.

 

Share this post


Link to post
Share on other sites
hace 8 minutos, juguefre said:

hacer los poligonos double sided, así se ven desde ambos lados.


Podrias explicar como hacerlo por favor? tiene unity algun metodo que haga esto automaticamente? y en caso de que no lo tenga, como lo podria programar yo mismo?

 

Edited by Jose134

Share this post


Link to post
Share on other sites
7 hours ago, juguefre said:

La solución rápida es hacer los poligonos double sided, así se ven desde ambos lados.

Si es una solucion, aunque tambien se renderizan de los dos lados, no se ti se sale gratis la verdad, pero si no importa esta perfecta. Lo feo de esto cuando te acostumbras a usar los poligonos "single" sided (se dice asi?) es que es mas facil de trabajar en la escena que un doble sided sobre todo si son lugares o pasillos pequeños.

7 hours ago, Jose134 said:

Podrias explicar como hacerlo por favor? tiene unity algun metodo que haga esto automaticamente? y en caso de que no lo tengo, como lo podria programar yo mismo?

creo que en el meshRenderer dice la opcion doubleSided

 

7 hours ago, Jose134 said:

no puedo comprobar que las caras salgan exactamente invertidas al usar -n ya que los meshes son mas o menos aleatorios y cambian cada vez que ejecuto el programa pero he probado y creo que no influye. La mayoria de las caras se pueden ver si miras hacia el eje Z positivo y apenas se ve ninguna cuando miras desde atras y esto no cambia al usar -n por lo que supongo que no influye en la direccion de las caras.

Si invertir el "n" no influye como es que lo sabes si es todo aleatorio? (muy raro pense que esto era determinante) Si queres estar totalmente seguro hace un triangulo, version n y version -n, solo para estar seguro. Otra es invertir los triangulos, el orden con el que los formas.

Share this post


Link to post
Share on other sites
hace 39 minutos, lightbug said:

creo que en el meshRenderer dice la opcion doubleSided

No veo esa opcion pero ahora investigare un poco mas sobre lo del doubleSided

hace 40 minutos, lightbug said:

Si invertir el "n" no influye como es que lo sabes si es todo aleatorio? (muy raro pense que esto era determinante) Si queres estar totalmente seguro hace un triangulo, version n y version -n, solo para estar seguro. Otra es invertir los triangulos, el orden con el que los formas.

No es 100% aleatorio, las lineas verdes que se veian en las imagenes eran sectores achicados de un diagrama de voronoi, a partir de ahi queria hacer un mesh que formara las paredes de esos sectores. Lo que es aleatorio son los puntos que definen el diagrama de voronoi y por tanto la posicion de los vertices en los ejes X y Z (en el eje Y siempre es 0 o 10)

 

He hecho pruebas generando varios meshes de triangulos y parece que lo que afecta son los triangulos del mesh, los que hice definiendo los vertices en el sentido de las agujas del reloj se ven desde delante y los que hice en sentido contrario desde atras. En el caso de las normales afectaron a la iluminacion, los que usan Vector3.forward se ven mas oscuros que los que usan -Vector3.forward

triangles.PNG

 

Supongo que la siguiente pregunta es como determino el orden de los vertices en los triangulos para que cada cara mire hacia donde debe?

Share this post


Link to post
Share on other sites
hace 43 minutos, lightbug said:

no se ti se sale gratis la verdad

No es gratis pero es una solución rápida, y luego puede buscar una solución mas optima aunque dado la naturaleza "random" del mesh yo creo que le toca quedarse con double sided.

Share this post


Link to post
Share on other sites
11 hours ago, juguefre said:

No es gratis pero es una solución rápida, y luego puede buscar una solución mas optima aunque dado la naturaleza "random" del mesh yo creo que le toca quedarse con double sided.

SI estaba pensando lo mismo, si fuera una malla conocida podes hacerlo pero como hay cosas Random, podrias tambien pero es un quilombo. Seguramente el DoubleSided sea lo mejor.

11 hours ago, Jose134 said:

las lineas verdes que se veian en las imagenes eran sectores achicados de un diagrama de voronoi

Guat is dat?

giphy.gif

 

EDIT: Me confundi, lo de doubleSided era el castShadow del meshRenderer, si queres doubleSided vas a tener que emplear algun shader, estoy seguro de que hay miles por ahi, incluso en el assetStore o quien dice ya Built-in en Unity

Edited by lightbug

Share this post


Link to post
Share on other sites
On 30/8/2017 at 15:20, Jose134 said:


Podrias explicar como hacerlo por favor? tiene unity algun metodo que haga esto automaticamente? y en caso de que no lo tenga, como lo podria programar yo mismo?

 

Creo que seria muy útil en tu caso que generaras 2 polígonos usando tus 3 vértices, cada uno en dirección opuesta al otro.

El punto es que el double sided calcula el polígono 2 veces, básicamente cuenta cada polígono como si fuera 2 polígonos, siendo así y como tu mesh es generado automáticamente mejor usas doble polígono en lugar de double sided shader, la ventaja es que cada uno de tus polígonos usara su propia normal y la iluminación de cada polígono sera "correcta", el impacto en rendimiento es el mismo y lo puedes hacer desde tu script.
 

Share this post


Link to post
Share on other sites
8 hours ago, juguefre said:

Creo que seria muy útil en tu caso que generaras 2 polígonos usando tus 3 vértices, cada uno en dirección opuesta al otro.

El punto es que el double sided calcula el polígono 2 veces, básicamente cuenta cada polígono como si fuera 2 polígonos, siendo así y como tu mesh es generado automáticamente mejor usas doble polígono en lugar de double sided shader, la ventaja es que cada uno de tus polígonos usara su propia normal y la iluminación de cada polígono sera "correcta", el impacto en rendimiento es el mismo y lo puedes hacer desde tu script.
 

Asi lo hace sketchup por ej, cuando le das que exporte double sided lo que hace te duplica todo. Igual cuando tenes un shader soble sided no tenes ese problema con la iluminacion, el resultado final es identico, mira (luz celeste ilumina las caras que salen con cualquier shader, luz roja las caras a duplicar):

doblesided.png

-> Se ven diferentes iluminados (sobretodo el del shader) porque olvide de setear los mismos parametros de los dos :3_grin:, pero al final son iguales (o pueden serlo mejor dicho).

La razon por la que seguiria usando el mesh doble vs el shader es porque podes tener el shader que quieras, cuando haces el doble de la maya lo seguis teniendo, con el shader (en este caso descargué uno por free del asset store ,identico al standard de Unity) estas limitado al tipo que sea (si es que tenes algunos nada mas version two-sided), en el asset store no estaban todos version two-sided, aunque si sabes de shaders los podes copiar y hacerlos doble sided, pero ya no tiene sentido hacerlos todos asi.

La desventaja que se me ocurre de duplicar el mesh es que tenes el doble de indices, no tanto por el tema de memoria hoy en dia no es mucho drama, pero si un arreglo mas grande que pasar de CPU a GPU (si no fuera estico el mesh), mientras que el shader lo calcula todo (los nuevos indices duplicados) en el mismo GPU, esto habria que medirlo bien pero estoy seguro que para grandes mesh de millones de triangulos se nota una diferencia y muy notable, no diria que "el impacto en el rendimiento es el mismo". Aunque si la mesh es estatica no hay ningun problema de rendimiento, quizas de memoria. (hablando de un caso exagerado)

Es decir que ambos tienen lo suyo, igual por practicidad me quedo con el mesh doble toda la vida, pero esta clarisimo que lo mejor es setear bien las normales/triangulos y olvidarse de todo lo doble Sided, pero bueno si no queda otra... hasta yo por vago exporto todo dobleSided, ni da para setear en sketchup las normales :6_smile:

Share this post


Link to post
Share on other sites

@lightbug

La diferencia entre doble sided shader y doble mesh es la iluminación.

Imagina una pared creada con un solo polígono que usa double sided shader, la pared separa una habitación y un pasillo, en el pasillo hay una luz tenue pero en la habitación no hay ninguna luz, ahora dependiendo de hacia donde este orientada la normal del polígono sera la iluminación.

Si la normal esta hacia la habitación el polígono sera oscuro (no hay luz en el cuarto).

Si la normal esta hacia el pasillo el polígono estará iluminado.

Hasta aquí todo perfecto PERO la iluminación sera la misma para ambos lados. Resultando en esto:

Si la normal esta hacia la habitación los DOS lados del polígono serán oscuros sin importar que haya una luz en el pasillo.

Si la normal esta hacia el pasillo los DOS lados del polígono estarán iluminados sin importar que en la habitación no haya luz.

Esto es por que el shader usa una sola normal para calcular la luz en ambos lados del polígono.

Con doble mesh tienes 1 normal cada polígono y el calculo de la luz es mas preciso resultando en el lado de la habitación siendo oscuro mientras el lado del pasillo es iluminado (como se supone que debería ser).

Es obvio que la misma solución no se puede aplicar a múltiples casos diferentes. Se pueden presentar casos donde double shaded es la solución apropiada en lugar de double mesh.

 

 

 

Share this post


Link to post
Share on other sites
8 hours ago, juguefre said:

Hasta aquí todo perfecto PERO la iluminación sera la misma para ambos lados.

Justamente eso lo probe, puse una sola luz de un lado y mire ambos y responden correctamente, no pasa lo que decis, tambien para la luz en el otro lado, ya que el shader (este en particular) usa otras normales(invertidas quizas) y no comparte la misma.

Si tenes dudas probalo vos mismo:

https://www.assetstore.unity3d.com/en/#!/content/23087

8 hours ago, juguefre said:

Esto es por que el shader usa una sola normal para calcular la luz en ambos lados del polígono.

Con doble mesh tienes 1 normal cada polígono y el calculo de la luz es mas preciso resultando en el lado de la habitación siendo oscuro mientras el lado del pasillo es iluminado (como se supone que debería ser).

Eso dependera sola y exclusivamente de como esté hecho el shader double-sided, yo he hecho manualmente con glsl un doble-sided y es totalmente posible y amigable con las luces, podes hacerlo de la manera que decis, compartiendo normales, o invertirlas para el "lado doble" (como deberia ser), dependerá solo del shader, no de si es single sided o double sided.

 

8 hours ago, juguefre said:

Es obvio que la misma solución no se puede aplicar a múltiples casos diferentes. Se pueden presentar casos donde double shaded es la solución apropiada en lugar de double mesh.

Si por supuesto, toda comparacion tiene un punto de inflexión.

 

EDIT: Si lo probas fijate que hay algo raro con las normales, como el normal map las modifica cuando le das mucho "Normal Intensity" del otro lado parece que pasa algo de luz, pero en si no debería (no pasa si no tenes normal map) ...  un punto mas a favor de doble mesh.

Edited by lightbug

Share this post


Link to post
Share on other sites
Sign in to follow this  

UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...