Noticias

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

¿Como puedo obtener el tamaño exacto de una esfera o cubo?

Iniciado por ftejada, Noviembre 05, 2018, 06:36:54 PM

Tema anterior - Siguiente tema
Hola a todos,
 
Sabemos que la escala de un gameObjet es totalmente independiente de su Tamaño real en nuestras escenas. Por ejemplo un Cubo con la malla por defecto de Unity con la escala (1,1,1) tiene un Tamaño Real en cada uno de sus EjesLocales de 1 (metro). Pero otro cubo que tenga otra malla modelada en otro programa con escala de su gameObject (1,1,1), puede tener cualquier tamaño Real en cada uno de sus EjesLocales... por ejemplo 2 (metros). Lo que nos daria un Cubo el doble de grande que el que tiene la malla por defecto de Unity
 
En la escena tengo un cubo y una esfera (con malla por defecto de Unity) y necesito darles el mismo tamaño "Real" en el mundo que un cubo y una esfera con mallas de otro programa. Pero no encuentro una manera totalmente precisa de hacerlo, ya que la escala de sus gameObjects en ambas parejas, (Cubo y Esfera con malla por defecto de Unity) y (Cubo y Esfera con mallas importadas "con tamaño indeterminado), sería de (1,1,1).
 
¿Existe alguna manera de poder saber el tamaño Real exacto dentro de nuestra escena de un objeto independientemente de la escala que tenga? mediante script, claro está!
 
 
 
Saludos y gracias de antemano.

Se me ocurre para una esfera tomar x vértice y luego calcular las distancias con todos los vértices y obtener el de mayor distancia, en una esfera funcionaria correctamente, en un cubo tendrías que limitar el valor de x & z para que se tome el vértice más lejano en line recta.
 
¿Se entiende?
 
Al final tendrás la distancia desde el primer punto al último y esa será tu escala real.

Cita de: francoe1 date=1541441179Se me ocurre para una esfera tomar x vértice y luego calcular las distancias con todos los vértices y obtener el de mayor distancia, en una esfera funcionaria correctamente, en un cubo tendrías que limitar el valor de x & z para que se tome el vértice más lejano en line recta.
   
   
      ¿Se entiende?
   
   
      Al final tendrás la distancia desde el primer punto al último y esa será tu escala real.
   


mmmm Parece buena idea... Voy a tantearla en estos días a ver que saco en claro.
 
Gracias @francoe1
 
 
 
Si a alguien se le ocurre más ideas estoy abierto a más sugerencias
 
 
 
Saludos

el componente meshFilter contine el "mesh" que contiene los vertices del modelo... cada vertice es un verctor3 con su posicion "real" respecto a su pivot o gizmo...
 
puedes pedir la "magnitude" de los verrtices para ver como de lejos estan del centro...

Lo que dice @francoe1 es lo que iba a decir, para agregar si querés podés normalizar todo a la unidad (como Unity por default) en base a la componente máxima del arreglo podés hacer, para el cubo Por ej:
 

* Cubo
Sin normalizar:
(Por ej en X)
X_min = - 2.75
X_max = 2.75
Lado = 5.5
Con |X_max|=|X_min| = 2.75

 
Si querés dejar al x max y min en 0.5 vas a terminar normalizar al vértice, osea dividir por 2 * |X_max|
 

v_n = v / ( 2 * |X_max|  )
Normalizado:
x_min_n = - 2.75 / 5.5 = - 0.5
x_max_n = 2.75 / 5.5 = 0.5

 
Con la esfera es más facil todavía.
 
: )

Has mirado ya la propiedad bounds? Creo recordar que podías sacar un cubo que envuelve la malla fácilmente...

Cita de: juanma_teso date=1541510500Has mirado ya la propiedad bounds? Creo recordar que podías sacar un cubo que envuelve la malla fácilmente...
   


eso de los bounds es buena... no se me habia ocurrido...
 
...creo que el box collider se "setupea" asi al asignarlo... creo que coje las medidas de los bounds...

Cita de: juanma_teso date=1541510500Has mirado ya la propiedad bounds? Creo recordar que podías sacar un cubo que envuelve la malla fácilmente...
   


Es buena, siempre y cuando tengas un collider asociado, no se si podés obtener algo parecido con Mesh.

Gracias a todos por las ideas!
 
Voy a probar que tal va... de todos modos me surgen algunas dudas acerca del consumo que requeriria calcular la distancia entre muchisimos vertices ( por ejemplo los de una esfera que tiene unos cuantos)... Tengo entendido que calcular la distancia es bastante costoso en terminos de rendimiento debido a la raiz cuadrada.
 
Por Bound he estado haciendo unas pequeñas pruebas y parece que en cuanto rotas un objeto los valores cambian ya que la caja delimitadora nunca gira con los ejes y la Api de Unity no provee de unas variables con la posicion exacta de cada Bound para poder calcular todo manualmente ayudandonos con el centro...
 
Parece que la mejor via de conseguirlo es mediante lo que dijo francoe1... voy a seguir tanteando...
 
 
 
Saludos
 
 

los vertex de un mesh son directamente Vector3... si les pides la "magnitude" es la distancia...
 

//la distancia es directamente:
vertices[numeroDeVertice].magnitude;
//haces un bucle for...
Vector3 vertices = mesh.vertices;
float maxDistance = 0;
for (int i=0; i<vertices.Lentgth; i++) {
    if (vertices[i].magnitude > maxDistance) {
        maxDistance = vertices[i].magnitude;
    }
}
Debug.Log("distancia"+maxDistance);//mostrar en consola
  
//con eso encontrarias la distancia del vertice mas lejano del centro del objeto...

 
 

Noviembre 07, 2018, 11:30:25 PM #10 Ultima modificación: Noviembre 07, 2018, 11:30:53 PM por francoe1
Cita de: Igor date=1541624092los vertex de un mesh son directamente Vector3... si les pides la "magnitude" es la distancia...
   
   

//la distancia es directamente:
vertices[numeroDeVertice].magnitude;
//haces un bucle for...
Vector3 vertices = mesh.vertices;
float maxDistance = 0;
for (int i=0; i<vertices.Lentgth; i++) {
    if (vertices[i].magnitude > maxDistance) {
        maxDistance = vertices[i].magnitude;
    }
}
Debug.Log("distancia"+maxDistance);//mostrar en consola
  
//con eso encontrarias la distancia del vertice mas lejano del centro del objeto...

   
       
   


En una esfera esto funciona, el problema se presenta en 1 cubo o formas irregulares donde la distancia perpendicular es mayor que la distancia recta.

Cita de: ftejada date=1541614453Voy a probar que tal va... de todos modos me surgen algunas dudas acerca del consumo que requeriria calcular la distancia entre muchisimos vertices ( por ejemplo los de una esfera que tiene unos cuantos)... Tengo entendido que calcular la distancia es bastante costoso en terminos de rendimiento debido a la raiz cuadrada.
   


No para nada, es una relativamente una papita por sí solo, dependerá del número de vértices y de la arquitectura del CPU (ya hablando más hardcore) que calcule esas distancias, pero no es preocupante ...además lo vas a hacer una sola vez (supongo). Y como todo, lo mejor es probar y sacarte la duda.
 
Igual no es necesario calcular las distancias de todos los puntos, tenés que encontrar el valor más alto del arreglo de vértices, una vez tengas eso y sepas que el objeto originalmente está (y va) centrado lo que te resta es hacer un escalamiento manual o modificar su localScale si quisieras.

Noviembre 09, 2018, 03:31:19 PM #12 Ultima modificación: Noviembre 09, 2018, 03:34:17 PM por J Montes
Explorar todos los vértices puede ser un poco excesivo. Si lo vas a usar a menudo yo creo que deberías precalcular el tamaño en tu MonoBehavior. Por ejemplo implementando la medida de tamaño como una Editor Tool.
 
De todas formas, Unity ya hace ese trabajo.  Yo intentaría usar los bounds como dijo @juanma_teso. De la documentación de Mesh.bounds: 
 
 
 



   
      This is the axis-aligned bounding box of the mesh in its local space (that is, not affected by the transform). Note that the 
Renderer.bounds property is similar but returns the bounds in world space.
   

[/quote]
 
Y si sabes que se trata de un cubo o una esfera, puedes obtener el tamaño de la propiedad mesh.bounds.size. Como la matriz de transformación no está aplicada a los bounds (esto lo hace el Renderer en cada ciclo), tendrás que multiplicar ese vector por transform.lossyScale para tener las dimensiones en world coordinates.
 
Cita de: ftejada date=1541614453Por Bound he estado haciendo unas pequeñas pruebas y parece que en cuanto rotas un objeto los valores cambian ya que la caja delimitadora nunca gira con los ejes y la Api de Unity no provee de unas variables con la posicion exacta de cada Bound para poder calcular todo manualmente ayudandonos con el centro...
   


Los bounds de un Mesh nunca cambian, porque son los bounds axis-aligned, esto es, siempre ortogonales, en sus coordenadas locales. Estos bounds se usan para calcular en "grueso" las colisiones, el clipping... pero se transforman a través de la matriz de transformación del objeto para realizar estos cálculos. Después, la GPU usa esa misma transformación para proyectar cada vértice del objeto a sus coordenadas en word space. 
 
Y esto debería servirte si lo que necesitas es la escala del objeto, que para una esfera o cubo se puede deducir de su AABB (axis-aligned bounding box).
 
Pero las esferas son un caso un poco especial. Al estar trianguladas, el tamaño de su AABB varía levemente en función de su orientación. Y en función de cómo esté modelada, la medida de su Mesh.bounds podría ser menor que su radio real. Si no puedes predecir este efecto, tendrías efectivamente que evaluar cada vértice para saber cuál es el más alejado.
 
Dependiendo de tu caso de uso, podría interesarte usar Renderer.bounds en lugar de Mesh.bounds, pero Renderer.bounds sí irá cambiando de tamaño a medida que el objeto rota, sea un cubo o una esfera triangulada (de hecho sólo una esfera perfecta no cambiaría su Renderer.bounds al rotar, y no hay esferas perfectas en un rasterizador de triángulos). De nuevo, depende de tu caso de uso, pero si se trata de escalarlos para que tengan el mismo tamaño, yo creo que podrías usar los bounds.

no sabia que los mesh bounds eran diferentes a los renderer bounds... 
 
esta bien saberlo... quizas pueda ser util alguna vez...

Hola a todos y muchas gracias por los aportes!!!
 
Cita de: Igor date=1541624092los vertex de un mesh son directamente Vector3... si les pides la "magnitude" es la distancia...
   


respecto a lo que dijo Igor, concuerdo con francoe1, la magnitud de la posición de cada vertice, solo serviría para esferas "totalmente redondas". En cuanto la esfera tuviese una escala distinta en alguno de sus ejes o en otras figuras irregulares... no parece ser una solución
 
 
 
Cita de: J Montes date=1541773879Y si sabes que se trata de un cubo o una esfera, puedes obtener el tamaño de la propiedad mesh.bounds.size. Como la matriz de transformación no está aplicada a los bounds (esto lo hace el Renderer en cada ciclo), tendrás que multiplicar ese vector por transform.lossyScale para tener las dimensiones en world coordinates.
   


 J Montes he estado probando lo que dijiste y va perfecto para los cubos... no tenia ni idea de que multiplicandolo por su lossyScale podría conseguirlo, por eso cuando estuve probando no me servia esta solución ya que no lo estaba haciendo bien. Siguiendo tu información he hecho algo así.
 
 


targetMeshBounds = gameObjectTarget.GetComponent<MeshFilter>().mesh;
 
//....
 
Vector3 sizeBoundsTarget = targetMeshBound.bounds.size;
Vector3 nSize;
nSize.x = Target.transform.lossyScale.x * size.x;
nSize.y = Target.transform.lossyScale.y * size.y;
nSize.z = Target.transform.lossyScale.z * size.z;
 
transform.localScale = nSize;

 
También lo he estado probando con esferas y parece ir perfecto también aunque la esferaTarget tenga escalas diferentes en cada eje X, Y, Z... Es cierto que he notado que la escala no es totalmente exacta, pero es más que suficiente para lo que necesito, ya que la perdida de precisión es como de 0.000001 o algo asi... supongo que es a esto a lo que te referias con si no dimelo pq con las prubas que he hecho parece bastante preciso y no representaría un problema para mi:
 
Cita de: J Montes date=1541773879Pero las esferas son un caso un poco especial. Al estar trianguladas, el tamaño de su AABB varía levemente en función de su orientación. Y en función de cómo esté modelada, la medida de su Mesh.bounds podría ser menor que su radio real. Si no puedes predecir este efecto, tendrías efectivamente que evaluar cada vértice para saber cuál es el más alejado.
   


 
 
 
 
Otro cantar parece ser con figuras como los cilindros, en los que la altura de este siempre se incrementa al doble ya que al final le estamos pasando el tamaño del bound.y a la escala del otro objeto... por lo que si es un cilindro conviene dividir el bound.y/2
 
¿Existe alguna manera de poder modificar el mesh.bounds.size de una malla para que cambie su tamaño en vez de andar tocando la escala de su transform?
 
Saludos

Etiquetas: