¿Cómo encuentras la esfera más grande que puedes dibujar en perspectiva?
Visto desde arriba, sería esto:
Agregado: en el centro de la derecha, he marcado cuatro puntos, creo que sabemos algo. Podemos desproyectar las ocho esquinas del frusum y los centros de los extremos cercano y lejano. Entonces sabemos los puntos 1, 3 y 4. También sabemos que el punto 2 es la misma distancia de 3 que 4 es de 3. Entonces podemos calcular el punto más cercano en la línea 1 a 4 al punto 2 para obtener el ¿centrar? Pero las matemáticas y el código real se me escapan.
Quiero dibujar modelos (que son aproximadamente esféricos y para los que tengo una esfera delimitadora de miniball) lo más grandes posible.
Actualización: He intentado implementar el enfoque de incircle-on-two-planes como lo sugieren bobobobo y Nathan Reed :
function getFrustumsInsphere(viewport,invMvpMatrix) {
var midX = viewport[0]+viewport[2]/2,
midY = viewport[1]+viewport[3]/2,
centre = unproject(midX,midY,null,null,viewport,invMvpMatrix),
incircle = function(a,b) {
var c = ray_ray_closest_point_3(a,b);
a = a[1]; // far clip plane
b = b[1]; // far clip plane
c = c[1]; // camera
var A = vec3_length(vec3_sub(b,c)),
B = vec3_length(vec3_sub(a,c)),
C = vec3_length(vec3_sub(a,b)),
P = 1/(A+B+C),
x = ((A*a[0])+(B*a[1])+(C*a[2]))*P,
y = ((A*b[0])+(B*b[1])+(C*b[2]))*P,
z = ((A*c[0])+(B*c[1])+(C*c[2]))*P;
c = [x,y,z]; // now the centre of the incircle
c.push(vec3_length(vec3_sub(centre[1],c))); // add its radius
return c;
},
left = unproject(viewport[0],midY,null,null,viewport,invMvpMatrix),
right = unproject(viewport[2],midY,null,null,viewport,invMvpMatrix),
horiz = incircle(left,right),
top = unproject(midX,viewport[1],null,null,viewport,invMvpMatrix),
bottom = unproject(midX,viewport[3],null,null,viewport,invMvpMatrix),
vert = incircle(top,bottom);
return horiz[3]<vert[3]? horiz: vert;
}
Admito que estoy volando; Estoy tratando de adaptar el código 2D extendiéndolo en 3 dimensiones. No calcula la insfera correctamente; El punto central de la esfera parece estar en la línea entre la cámara y la esquina superior izquierda cada vez, y es demasiado grande (o demasiado cerca). ¿Hay algún error obvio en mi código? ¿El enfoque, si es fijo, funciona?
Respuestas:
Asumiré que su frustum es simétrico, ya que su dibujo parece sugerirlo. Hay tres restricciones (dos si su tronco es 2D):
A. la esfera no puede ser mayor que la distancia entre los planos cercano y lejano
Si
D
es la distancia casi lejana, la primera restricción es simplemente:B. la esfera no puede ensancharse más que los planos laterales
Ahora para la otra restricción, digamos que
α
es el medio ángulo del tronco yL
es el ancho medio del plano lejano, como se muestra en este dibujo:La primera fórmula está dada por trigonometría en el triángulo. El segundo proviene de la suma de los ángulos de un triángulo. Lo que nos da la segunda restricción:
Si su frustum es 3D, tendrá una tercera restricción con nuevos
L
yα
valores.Resultado final
El
R
valor que está buscando es elmin
de los tres límites.Cómo obtener los parámetros
Si puede desproyectar el tronco de visión o el espacio mundial, puede calcular L, D y α de la siguiente manera, donde los
P
puntos son del plano cercano y losQ
puntos son del plano lejano:Las flechas significan vectores, "." es el producto escalar y || indica la longitud de un vector. Reemplace
Q2
conQ3
yP2
conP3
para obtener L y α en la dimensión vertical.fuente
En 2D: considere el tronco como un triángulo (2D)
Luego quieres encontrar el círculo del triángulo.
Como un problema 3D, necesitas encontrar la esfera de una pirámide de base cuadrada.
Si tuviera la fórmula, la imprimiría aquí, pero, por desgracia, no sé la fórmula.
fuente
La Esfera más grande posible debería tocar el plano lejano (usando los términos para ver frustrums aquí) justo en el centro. También tocaría los planos superior / inferior o izquierdo / derecho, según el ángulo de FoV que sea más pequeño. Tengo que decir que no tengo una prueba matemática real para esos supuestos, pero deberían estar en lo cierto. Tal vez alguien tenga una idea sobre cómo probar esto.
Una esfera se puede definir por su punto central y un radio. Cx y Cy es lo mismo que el centro del plano lejano.
Cz y el radio pueden obtenerse resolviendo un sistema de ecuaciones basado en los supuestos enumerados anteriormente.
T es uno de los planos inferior / superior o izquierdo / derecho (ver arriba) con t1, t2 y t3 como vector normal normalizado y t4 como distancia desde el origen. f es el centro del plano lejano.
t1 * cx + t2 * cy + t3 * cz - t4 = r
-fz + cz = r
t1 * cx + t2 * cy + t3 * cz - t4 = -fz + cz
t1 * cx + t2 * cy + fz - t2 = + cz - t3 * cz
t1 * cx + t2 * cy - fz - t2 = cz * (1 - t3)
cz = (t1 * cx + t2 * cy - fz - t2) / (1 - t3)
r entonces se calcula insertando cz en esto: -fz + cz = r
Puede obtener todos los planos de la Matriz de proyección que está utilizando. (No ViewProjection en este caso)
luego debe mover la esfera al espacio correcto: C '= inverso (Ver) * C
fuente
Estoy tratando de hacer algo similar, y en mi caso, la velocidad es más crucial que la precisión, siempre y cuando la esfera no exista fuera de los límites del tronco.
Si calcula la distancia más corta entre linesegs (o caras en 3d), la distancia más corta encontrada podría usarse como el diámetro de un círculo / insfera que se encuentra completamente dentro del tronco. El origen del incircle / insphere podría simplemente el promedio de todos los vértices (suma y división). Sería bastante rápido y también funcionaría para todo tipo de poliedros convexos.
El único inconveniente es que el círculo o la esfera no serán necesariamente el mayor círculo o insfera posible. Para un tronco con mucho volumen y un borde muy corto, el círculo / esfera compartiría mucho menos espacio del tronco que sea posible.
Otra idea
Si desea la insfera de un frustum de vista 3D y tiene la matriz de perspectiva utilizada para construir este frustum, entonces simplemente podría usar esa matriz en la insfera de un cubo unitario, y esa debería ser una insfera perfecta para el frustum. (El diámetro de la esfera de un cubo es la longitud de uno de los bordes del cubo, el centro es el centro del cubo, que es el promedio de los vértices del cubo)
fuente