Después de tanta lectura sobre las transformaciones, es hora de implementar un trackball para mi aplicación. Entiendo que tengo que crear un vector desde el origen hasta donde se hace clic con el mouse y luego otro desde el origen hasta donde se suelta el mouse.
Mi pregunta es, ¿tengo que transformar las coordenadas de píxel (x, y) en coordenadas mundiales o debería hacer todo en el espacio de la imagen (considerando que el espacio de la imagen es la proyección 2D de la escena medida en píxeles)?
EDITAR
La respuesta de Richie Sams es muy buena. Sin embargo, creo que estoy siguiendo un enfoque ligeramente diferente, corrígeme si me equivoco o si no entiendo algo.
En mi aplicación tengo una SimplePerspectiveCamera
clase que recibe el position
de la cámara, la position of the target
estamos viendo, el up
vector, las fovy
, aspectRatio
, near
y far
distancias.
Con ellos construyo mis matrices de Vista y Proyección. Ahora, si quiero acercar / alejar, actualizo el campo de visión y actualizo mi matriz de proyección. Si quiero hacer una panorámica, muevo la posición de la cámara y miro por el delta que produce el mouse.
Finalmente, para las rotaciones puedo usar la transformación del eje angular o los cuaterniones. Para esto, guardo los píxeles-coords donde se presionó el mouse y luego, cuando el mouse se mueve, también guardo los píxeles-coords.
Para cada par de coordenadas puedo calcular la Z-valor dado la fórmula para una esfera, es decir, sqrt (1-x ^ 2-y ^ 2), a continuación, calcular a vectores que van desde la target
a PointMousePressed
y desde target
a PointMouseMoved
, hacer producto cruzado para obtener el eje de rotación y usar cualquier método para calcular la nueva posición de la cámara.
Sin embargo, mi mayor duda es que los valores (x, y, z) se dan en píxeles-coordenadas, y al calcular los vectores que estoy usando, target
es un punto en las coordenadas mundiales. ¿Esta mezcla de sistema de coordenadas no está afectando el resultado de la rotación que estoy tratando de hacer?
z
valor de una esfera de radior
, sin embargo, no estoy seguro de si esa esfera vive en el espacio mundial o en el espacio de la imagen y cuáles son las implicaciones. Quizás estoy pensando demasiado en el problema.Respuestas:
Suponiendo que se refiere a una cámara que gira según el movimiento del mouse:
Una forma de implementarlo es hacer un seguimiento de la posición de la cámara y su rotación en el espacio. Las coordenadas esféricas resultan convenientes para esto, ya que puede representar los ángulos directamente.
La cámara está ubicada en P, que está definida por m_theta, m_phi y m_radius. Podemos rotar y movernos libremente donde queramos cambiando esos tres valores. Sin embargo, siempre miramos y giramos alrededor de m_target. m_target es el origen local de la esfera. Sin embargo, somos libres de mover este origen a donde queramos en el espacio mundial.
Hay tres funciones principales de la cámara:
En sus formas más simples, Rotate () y Zoom () son triviales. El solo modifica m_theta, m_phi y m_radius respectivamente:
La panorámica es un poco más complicada. Una panorámica de la cámara se define como mover la cámara hacia la izquierda / derecha y / o arriba / abajo, respectivamente, a la vista de la cámara actual. La forma más fácil de lograr esto es convertir nuestra vista actual de la cámara de coordenadas esféricas a coordenadas cartesianas. Esto nos dará un vector ascendente y correcto .
Entonces, primero, convertimos nuestro sistema de coordenadas esféricas a cartesiano para obtener nuestro vector de aspecto . A continuación, se hace el producto vectorial con el mundo arriba vector, con el fin de obtener un derecho de vectores. Este es un vector que apunta directamente a la derecha de la vista de la cámara. Por último, hacemos otro producto vectorial para conseguir la cámara hasta vectorial.
Para terminar la panorámica, movemos m_target a lo largo de los vectores arriba y derecha .
Una pregunta que podría estar haciendo es: ¿Por qué convertir entre cartesiano y esférico todo el tiempo (también tendrá que convertir para crear la matriz de Vista).
Buena pregunta. Yo también tuve esta pregunta y traté de usar exclusivamente cartesian. Terminas con problemas con las rotaciones. Dado que las operaciones de coma flotante no son exactamente precisas, las rotaciones múltiples terminan acumulando errores, que correspondieron a la cámara lentamente y sin querer rodando.
Entonces, al final, me quedé con las coordenadas esféricas. Para contrarrestar los cálculos adicionales, terminé almacenando en caché la matriz de vista y solo la calculé cuando la cámara se mueve.
El último paso es usar esta clase de cámara. Simplemente llame a la función de miembro apropiada dentro de las funciones MouseDown / Up / Scroll de su aplicación:
Las variables m_camera * Factor son solo factores de escala que cambian la rapidez con la que la cámara gira / gira / desplaza
El código que tengo arriba es una versión simplificada de pseudocódigo del sistema de cámara que hice para un proyecto paralelo: camera.h y camera.cpp . La cámara intenta imitar el sistema de cámara Maya. El código es gratuito y de código abierto, así que siéntase libre de usarlo en su propio proyecto.
fuente
En caso de que desee echar un vistazo a una solución lista, tengo un puerto de controles TRES.JS TrackBall en C ++ y C #
fuente