Después de multiplicar por la matriz de proyección en perspectiva (también conocida como matriz de clip) se termina con un vector homogéneo de 4 vectores [x, y, z, w]. Esto se llama npc (coordenadas de proyección normalizadas) y también se llama coordenadas de clip. Para obtener coordenadas 2D en la pantalla se suele usar algo así como
xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width
Para los puntos en frente de la cámara esto le da lo que quiere. Pero los puntos detrás de la cámara tendrán w < 0 y obtendrá valores que se correlacionan con coordenadas de pantalla válidas aunque el punto esté detrás de la cámara. Para evitar esto, necesitas cortar. Cualquier vértice que tenga un w < 0 debe recortarse.
Una cosa rápida para intentar es simplemente no dibujar ninguna línea si cualquiera de los vértices tiene w < 0. Esto debería corregir los extraños polígonos que aparecen en su escena. Pero también eliminará algunas líneas que deberían ser visibles.
Para solucionar por completo el problema que necesita para recortar todas las líneas que tienen un vértice en frente de la cámara y un vértice detrás de la cámara. Recortar significa cortar la línea por la mitad y tirar la mitad que está detrás de la cámara. La línea es "recortada" por un plano que atraviesa la cámara y es paralelo a la pantalla de visualización. El problema es encontrar el punto en la línea que corresponde a este plano (es decir, donde la línea se cruza con el plano). Esto ocurrirá en el punto en la línea donde w == 0.Puede encontrar este punto, pero luego, cuando se intenta encontrar la pantalla coordina
xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width
se termina dividiendo por 0 (w == 0). Esta es la razón del "plano de recorte cercano". El plano de recorte cercano también es paralelo a la pantalla de visualización pero está en frente de la cámara (entre la cámara y la escena). La distancia entre la cámara y el plano de delimitación cercano es el parámetro de "cerca" de la matriz de proyección:
[ near/width ][ 0 ][ 0 ][ 0 ]
[ 0 ][ near/height ][ 0 ][ 0 ]
[ 0 ][ 0 ][(far+near)/(far-near) ][ 1 ]
[ 0 ][ 0 ][-(2*near*far)/(far-near)][ 0 ]
para recortar al plano cerca de usted tiene que encontrar el punto de la línea que corta el plano de delimitación cercano. Este es el punto donde w == cerca. Así que si usted tiene una línea con vértices v1, v2, donde
v1 = [x1, y1, z1, w1]
v2 = [x2, y2, z2, w2]
es necesario comprobar si cada vértice está por delante o por detrás del plano de recorte cercano. V1 está al frente si w1> = cerca y detrás si w1 < cerca. Si v1 y v2 están ambos al frente, dibuja la línea. Si v1 y v2 están detrás, no dibuje la línea. Si v1 es delante y detrás v2 es entonces usted necesita para encontrar vc donde la línea se cruza con el plano de recorte cerca de:
n = (w1 - near)/(w1 - w2)
xc = (n * x1) + ((1-n) * x2)
yc = (n * y1) + ((1-n) * y2)
zc = (n * z1) + ((1-n) * z2)
vc = [xc, yc, zc, wc]
Ahora trazar la línea entre v1 y VC.
No puedo agradecerle lo suficiente por la respuesta bien escrita. Esto me ha ayudado tremendamente ... no puedo votar lo suficiente tampoco. – shbi
Esta es una gran respuesta, pero hay algunas cosas que no tengo claras. Primero, ¿te falta la línea 'wc = (n * w1) + ((1 - n) * w2)'? Además, ¿su matriz de proyección P se multiplica a la derecha, es decir, v_e * P? Lo que es más importante, ningún renderizador que haya utilizado me obliga a especificar el plano cercano en el momento del sorteo. ¿Cómo se puede realizar este recorte cuando se desconoce el valor cercano? – Qualia
Probablemente haya encontrado una respuesta. Claramente, recorte z, constriñe w, ya que son linealmente dependientes. El problema que tuve es que si está interpolando w, está interpolando el valor del clip con el que prueba z. De hecho, las ecuaciones no son tan difíciles como pensaba. Para un vértice v_3 dado por v_1 y v_2, cuya línea interseca el plano del clip, 'w_3 = w_1 + r * (w_2-w_1)' y 'a_3 = a_1 + r * (a_2-a_3)', donde 'a_n = dot (avión, v_n) '. Pero a_3 es igual al valor del clip, w_3, entonces 'a_1 + r * (a_2-a_1) = w_1 + r * (w_2-w_1)'. Resuelve para r, y listo. (Espero). – Qualia