Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 58,34€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales
ftejada

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

Recommended Posts

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
1 hour ago, francoe1 said:

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.

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

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

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.

: )

Share this post


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

Has 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...

Share this post


Link to post
Share on other sites
9 hours ago, juanma_teso said:

Has 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.

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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...

 

Share this post


Link to post
Share on other sites
1 hour ago, Igor said:

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...

 

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.

Edited by francoe1

Share this post


Link to post
Share on other sites
6 hours ago, ftejada said:

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.

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.

Share this post


Link to post
Share on other sites

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

 

Quote

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.

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.

On 11/7/2018 at 7:14 PM, ftejada said:

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...

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.

Edited by J Montes

Share this post


Link to post
Share on other sites

no sabia que los mesh bounds eran diferentes a los renderer bounds... 

esta bien saberlo... quizas pueda ser util alguna vez...

Share this post


Link to post
Share on other sites

Hola a todos y muchas gracias por los aportes!!!

On 11/7/2018 at 9:54 PM, Igor said:

los 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

 

On 11/9/2018 at 3:31 PM, J Montes said:

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.

 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:

On 11/9/2018 at 3:31 PM, J Montes said:

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.

 

 

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

Share this post


Link to post
Share on other sites

×
×
  • Create New...