volumen una tiene que para hallar esfera diametro cual con circulo cilindro calcular balon 5cm math opengl geometry projection

math - una - volumen de un cilindro



Radio de Esfera proyectada (4)

El FOV no se almacena directamente en la matriz de proyección, sino que se usa cuando llamas a gluPerspective para construir la matriz resultante.

El mejor enfoque sería simplemente mantener todas las variables de su cámara en su propia clase, como una clase trunco, cuyas variables de miembro se usan cuando llama a gluPerspective o similar.

Es posible que el FOVy vuelva a salir de la matriz, pero las matemáticas requeridas me eluden.

quiero refinar una pregunta anterior :

¿Cómo proyecto una esfera en la pantalla?

(2) da una solución simple:

approximate radius on screen[CLIP SPACE] = world radius * cot(fov / 2) / Z with: fov = field of view angle Z = z distance from camera to sphere result is in clipspace, multiply by viewport size to get size in pixels

Ahora mi problema es que no tengo el campo de visión. Solo las matrices de vista y proyección son conocidas. (Y el tamaño de la ventana gráfica si eso ayuda)

¿Alguien sabe cómo extraer el campo de visión de la matriz de proyección?

Actualizar:

Esta aproximación funciona mejor en mi caso:

float radius = glm::atan(radius/distance); radius *= glm::max(viewPort.width, viewPort.height) / glm::radians(fov);


Actualización: ver a continuación.

Como tiene las matrices de visualización y proyección, esta es una forma de hacerlo, aunque probablemente no sea la más corta:

  • Transforme el centro de la esfera en el espacio visual usando la matriz de vista: llame al punto de resultado C
  • transformar un punto en la superficie de la esfera, por ejemplo, C + (r, 0, 0) en coordenadas mundiales donde r es el radio mundial de la esfera, en el espacio de visión; llamar al punto de resultado S
  • calcular rv = distancia de C a S (en el espacio de visualización)
  • dejar que el punto S1 en coordenadas de vista sea C + (rv, 0, 0) - es decir, otro punto en la superficie de la esfera en el espacio de visión, para el cual la línea C -> S1 es perpendicular al vector "mirar"
  • proyecto C y S1 en coords de pantalla usando la matriz de proyección como Cs y S1s
  • radio de pantalla de la pantalla = distancia entre Cs y S1s

Pero sí, como dijo Brandorf, si puedes preservar las variables de la cámara, como FOVy, sería mucho más fácil. :-)

Actualización: Aquí hay una variante más eficiente sobre lo anterior: hacer una inversión de la matriz de proyección. Úselo para transformar los bordes de la ventana gráfica en espacio de visualización. Entonces no tendrá que proyectar cada cuadro en coordenadas de pantalla.

Mejor aún, haz lo mismo con la matriz de visualización y transforma la cámara triturada de nuevo en el espacio mundial. Eso sería más eficiente para comparar muchas cajas contra; pero es más difícil descifrar las matemáticas.


Llego un poco tarde a esta fiesta. Pero encontré este hilo cuando estaba investigando el mismo problema. Pasé un día investigando esto y trabajé en algunos excelentes artículos que encontré aquí: http://www.antongerdelan.net/opengl/virtualcamera.html

Terminé empezando con la matriz de proyección y trabajando hacia atrás. Obtuve la misma fórmula que mencionas en tu publicación anterior. (donde cot (x) = 1 / tan (x))

radius_pixels = (radius_worldspace / {tan(fovy/2) * D}) * (screen_height_pixels / 2)

(donde D es la distancia de la cámara a la esfera delimitadora del objetivo)

Estoy usando este enfoque para determinar el radio de una rueda de desplazamiento imaginaria que utilizo para rotar mi objeto.

Por cierto, Florian, puedes extraer el fovy de la matriz de proyección de la siguiente manera:

Si toma el componente Sy de la matriz de proyección como se muestra aquí:

Sx 0 0 0 0 Sy 0 0 0 0 Sz Pz 0 0 -1 0 where Sy = near / range and where range = tan(fovy/2) x near

(puede encontrar estas definiciones en la página que he vinculado anteriormente)

Si sustituye el rango en la ecuación de Sy arriba, obtiene:

Sy = 1 / tan(fovy/2) = cot(fovy/2)

reordenando:

tan(fovy/2) = 1 / Sy

tomando arctan (el inverso de tan) de ambos lados obtenemos:

fovy/2 = arctan(1/Sy)

asi que,

fovy = 2 x arctan(1/Sy)

No estoy seguro si todavía te importa, ¡ha pasado un tiempo! - pero tal vez esto ayudará a alguien más.


La respuesta publicada en su enlace radiusClipSpace = radius * cot(fov / 2) / Z , donde fov es el ángulo del campo de visión, y Z es la distancia z a la esfera, definitivamente funciona. Sin embargo, tenga en cuenta que radiusClipSpace debe multiplicar por el ancho de la ventana radiusClipSpace para obtener una medida de píxeles. El valor medido en radiusClipSpace será un valor entre 0 y 1 si el objeto se ajusta a la pantalla.

Una solución alternativa puede ser usar el ángulo sólido de la esfera. El ángulo sólido subtendido por una esfera en el cielo es básicamente el área que cubre cuando se proyecta a la esfera de la unidad.

Las fórmulas se dan en este enlace, pero aproximadamente lo que estoy haciendo es:

if( (!radius && !distance) || fabsf(radius) > fabsf(distance) ) ; // NAN conditions. do something special. theta=arcsin( radius/distance ) sphereSolidAngle = ( 1 - cosf( theta ) ) ; // not multiplying by 2PI since below ratio used only frustumSolidAngle = ( 1 - cosf( fovy / 2 ) ) / M_PI ; // I cheated here. I assumed // the solid angle of a frustum is (conical), then divided by PI // to turn it into a square (area unit square=area unit circle/PI) numPxCovered = 768.f*768.f * sphereSolidAngle / frustumSolidAngle ; // 768x768 screen radiusEstimate = sqrtf( numPxCovered/M_PI ) ; // area=pi*r*r

Esto funciona aproximadamente en los mismos números que radius * cot(fov / 2) / Z Si solo desea una estimación del área cubierta por la proyección de la esfera en px, esta puede ser una manera fácil de hacerlo.

No estoy seguro de si se puede encontrar fácilmente una mejor estimación del ángulo sólido del tronco. Este método implica más comps que radius * cot(fov / 2) / Z