2012-02-02 21 views
5

Mi cámara gira alrededor de un punto cuando trato de cambiar la orientación. Si giro la cámara, por ejemplo, 30 grados en el eje Y, en lugar de que la cámara mire 30 grados hacia la derecha, la cámara gira alrededor del punto que estaba mirando.¿Por qué mi cámara gira alrededor de un punto con esta matemática?

o is the camera, A and B are 3D models. The lines show line-of-sight. 
This is what I expect: 
    A B 
    | >/
    |/
    |/
    |/ 
    o 

This is what actually happens: 
    A B 
    |\ 
    | \ 
    | \ 
    | > \ 
      o 

Ahora, desde mi entender, para mover la cámara, tengo que mover el mundo por el inverso de esa cantidad. Entonces, si quiero mover +1 en el eje Z, traduzco el mundo -1 en el eje Z. Dado que estoy usando cuaterniones para representar orientaciones, utilizo la cámara inversa del cuaternión (ya que las orientaciones son siempre unidades de cuaterniones, optimizo usando el conjugado en lugar de calcular el inverso) para rotar el mundo en la cantidad correcta.

Aquí es cómo puedo convertir un cuaternión a una matriz, donde q es el cuaternión invertida:

[1 - 2 * (q.y * q.y + q.z * q.z) 2 * (q.x * q.y - q.w * q.z)  2 * (q.x * q.z + q.w * q.y)   0] 
|2 * (q.x * q.y + q.w * q.z)  1 - 2 * (q.x * q.x + q.z * q.z) 2 * (q.y * q.z - q.w * q.x)   0| 
|2 * (q.x * q.z - q.w * q.y)  2 * (q.y * q.z + q.w * q.z)  1 - 2 * (q.x * q.x + q.y * q.y)  0| 
[0         0         0         1] 

Después de eso, me puse el componente de traducción de la matriz:

[... ... ... -x] 
|... ... ... -y| 
|... ... ... -z| 
[0  0  0  1] 

Y, por último Multiplico eso en la pila de matriz de vista de modelo, luego renderizo todos mis objetos. Estoy bastante seguro de que esta matemática es correcta, pero no produce los resultados que esperaba. Claramente, los vectores hacia adelante y hacia la derecha son el problema, entonces mi única pregunta es por qué están equivocados y cómo deberían establecerse si quiero obtener los resultados que estoy esperando. Gracias.

EDIT: He encontrado la solución desde this guy's quaternion camera class. Primero construyo una matriz de rotación como lo estaba haciendo antes, pero luego tomo los vectores de columna de la matriz de la primera, segunda y tercera columnas (xa, ya y za respectivamente). Entonces me puse el componente de traslación de la matriz de la siguiente manera:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

entonces la matriz resultante puede multiplicarse en la pila matriz modelview, y funciona perfectamente.

+0

Haga de su edición una solución y acéptelo. Así es como marcamos las preguntas resueltas por aquí. También creo que mereces una explicación de lo que está pasando. Escribiré una respuesta para esto. – datenwolf

Respuesta

1

EDIT: He encontrado la solución de la clase de cámara quaternion de este tipo. Primero construyo una matriz de rotación como lo estaba haciendo antes, pero luego tomo los vectores columna de la matriz de la primera, segunda y tercera columna (xa, ya, y za respectivamente). Entonces me puse el componente de traslación de la matriz de la siguiente manera:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

entonces la matriz resultante puede multiplicarse sobre la matriz modelview pila, y funciona perfectamente.

Sí, esto es exactamente lo que habría sugerido, solo que un poco diferente. Debe comprender que OpenGL no tiene una cámara, sino que simplemente mueve el mundo en la dirección opuesta, por lo que necesita encontrar la matriz de transformación inversa.

Una cámara solo gira y se mueve. Esto hace las cosas muy simples. El tnverse de la traducción es exactamente el mismo vector con signo opuesto, y el inverso de una matriz de rotación es su transposición (columna e hileras intercambiadas). Ahora mira a una matriz de transformación homogénea como OpenGL los utiliza:

R t 
0 1 

La parte superior izquierda de 3 × 3 es la parte de rotación, la columna más a la derecha es el vector de traslación. Creo que el resto ya te imaginaste a ti mismo.

0

Para ser honesto, tratar de encontrar una matriz para multiplicar a la matriz de vista de módulo es realmente complicado y muy propenso a errores. Hay mucha confusión y casos especiales. Por ejemplo, si miras 90 grados hacia arriba, dos de tus ejes se vuelven iguales. Un problema lógico es este: si vuelves la cabeza hacia atrás, para que pases por el punto superior, tu vector ascendente debería invertirse, ¿no? ¿Pero qué pasa si te lo pierdes por un grado de 0.0001? entonces deberías girar la cabeza alrededor de ese punto para que tu vector ascendente aún esté arriba.

En mi opinión, la mejor manera es abordar el problema desde otra perspectiva. Supongamos dos casos:

  • Al revés imposible:
    • Mantener un punto para su ubicación de la cámara y latitud/longitud de la dirección. Con simples operaciones sin/cos se puede obtener un vector de dirección. Su vector hacia arriba es (0, 1, 0)
    • Pasando simplemente cambiando la latitud y longitud
  • Al revés posible:
    • Además de la ubicación de la cámara, mantenga tanto hacia arriba como vectores blanco.
    • Al girar, calcular right = target x up y luego cambiar el destino a x * right + y * up
    • Luego necesita normalizar el vector de destino y calcular el nuevo. Lote de casos para manejar sin embargo.

Después de todo esto, sólo tiene que llamar gluLookAt.

+0

"Para ser sincero, tratar de encontrar una matriz para multiplicar a la matriz de vista de módulo es realmente complicado y muy propenso a errores". No, no es. Las matrices son la forma más directa de pensar acerca de las orientaciones de coordenadas relativas. Cada una de las primeras 3 columnas es uno de los vectores base del sistema de coordenadas transformadas. La cuarta columna es la traducción relativa. Es mucho más fácil escribir una matricula de cámara desde la vista y los vectores de destino, luego con toda esa trigonometría entremedio. – datenwolf

+0

Lo sé. Lo que estoy diciendo es que, si, por ejemplo, tienes 3 tipos diferentes de movimientos (por ejemplo, mover, girar y girar) hasta el siguiente cuadro, es mucho más fácil hacerlo con posición/latitud/longitud y finalmente convertirlo en una matriz, que tratar de aplicar cada operación a la matriz de la anterior. – Shahbaz

Cuestiones relacionadas