Rotación de cámara 3D

9

Por favor, perdónenme, pero necesito ayuda y he estado atrapado en esto por algunas semanas, no estoy progresando y en todos lados donde voy y veo una respuesta diferente, todo lo que intento no funciona. He tenido suficientes consejos y sugerencias, ahora realmente necesito que alguien me dé la respuesta para que pueda trabajar hacia atrás porque no puedo entender esto.

Lo que ha hecho que este tema sea más confuso es la forma en que todos usan un conjunto diferente de convenciones o reglas, y sus respuestas se basan en sus propias convenciones sin definir cuáles son.

Así que aquí está el conjunto de convenciones que he formado en base a lo que parece ser más común y lógico:

  1. Regla de la mano derecha para eje.
  2. Positivo Y está arriba, Positivo Z está hacia el espectador, Positivo X está a la derecha.
  3. Fila Matrices principales, transpuestas cuando se envían a sombreadores.
    • Paso: rotación sobre el eje X
    • Guiñada: rotación sobre el eje y
    • Rollo: rotación sobre el eje z
  4. Orden de rotación: Roll, Pitch, Yaw (¿es correcto? ¿Alguien puede revisarme sobre esto?)
  5. Los valores de rotación positivos, mirando hacia abajo desde el extremo positivo de un eje, dan como resultado una rotación en el sentido de las agujas del reloj.
  6. La dirección predeterminada para la rotación 0 en todos los ejes es un vector que apunta hacia abajo a Y negativo.

.. dadas esas convenciones (¡por supuesto corrígeme si están equivocadas!), ¿cómo se puede:

  • ¿Escribir una función LookAt? (lookAt (posición del vector, enfoque ocular del vector, arriba del vector))
  • Calcular una matriz de rotación. (rotación (x, y, z))

Intenté responder estas dos preguntas por mí mismo al menos durante las últimas 3 semanas, reescribí mi función LookAt & Rotation Matrix al menos 30 veces, probé docenas de métodos y leí material que he visto en cientos de sitios web y leí muchas preguntas respondidas, copié el código de otras personas, y nada de lo que he hecho hasta ahora ha funcionado, todo ha producido un resultado incorrecto. Algunos de los cuales han producido algunos resultados extrañamente divertidos que ni siquiera se acercan a la rotación correcta.

He estado trabajando en esto todas las noches con la excepción de anoche porque me estaba frustrando tanto con el fracaso repetido que tuve que parar y tomar un descanso.

Por favor, solo muéstrame cuál es el método correcto para que pueda trabajar hacia atrás a partir de eso y averiguar cómo funciona, ¡simplemente no estoy obteniendo la respuesta correcta y esto me está volviendo un poco loco!

Estoy escribiendo en Java, pero tomaré el código escrito en cualquier idioma, la mayor parte de mi código de renderizado 3D en realidad funciona de manera bastante brillante, son solo las matemáticas que no puedo entender.

ACTUALIZACIÓN: RESUELTA

¡Gracias por tu ayuda! Ahora tengo una función LookAt en funcionamiento que realmente entiendo y no podría estar más feliz (si alguien quisiera verla, pregunte).

Intenté nuevamente crear una matriz de rotación basada en las variables de cabeceo / guiñada / balanceo y nuevamente pareció fallar, pero decidí volcar intentando usar los ángulos de Euler para la cámara libre, ya que parece no ser adecuada para el El rol, en su lugar voy a crear una clase de cuaternión, podría tener mejor suerte al seguir ese camino, de lo contrario, recurriré al uso del tono / guiñada como coordenadas esféricas y confiaré en la nueva función LookAt de trabajo para la rotación.

Si alguien más se enfrenta a un problema similar y quiere hacerme preguntas, siéntase libre de hacerlo.

Al menos ya no estoy atrapado, ¡gracias por la ayuda!

Grady
fuente

Respuestas:

15

Lo que está buscando se puede encontrar en esta muy buena explicación: http://www.songho.ca/opengl/gl_transform.html

Pero como lo encontré un poco confuso sin sostener la mano, intentaré explicarlo aquí.

En este punto, debe considerar 5 sistemas de coordenadas y cómo se relacionan entre sí. Estas son las coordenadas de la ventana, las coordenadas del dispositivo normalizadas, las coordenadas del ojo, las coordenadas del mundo y las coordenadas del objeto.

Las coordenadas de la ventana pueden verse como los píxeles "físicos" en su pantalla. Son las coordenadas a las que se refiere el sistema de ventanas y, si opera en la resolución nativa de su monitor, en realidad son píxeles individuales. El sistema de coordenadas de la ventana son enteros 2D y es relativo a su ventana. Aquí se deja x + e y + está abajo con el origen en la esquina superior izquierda. Los encuentra cuando, por ejemplo, llamaglViewport .

El segundo conjunto son las coordenadas del dispositivo normalizadas. Estos se refieren a la configuración del espacio por el puerto de vista activa. El área visible del puerto de vista va de -1 a +1 y, por lo tanto, tiene el origen en el centro. Se deja x + y se levanta y +. También tienes el z + está "fuera" de la escena. Esto es lo que describe en 1.

No tiene control sobre cómo pasar de las coordenadas del dispositivo normalizadas a las coordenadas de la ventana, esto se hace implícitamente por usted. El único control que tienes es a través glViewporto similar.

Cuando trabaje con openGL, su resultado final siempre estará en coordenadas de dispositivo normalizadas. Como resultado, debe preocuparse por cómo representar su escena en estos. Si configura la matriz de proyección y vista de modelo a la matriz de identidad, puede dibujar directamente en estas coordenadas. Esto se hace, por ejemplo, al aplicar efectos de pantalla completa.

Lo siguiente son las coordenadas del ojo. Este es el mundo visto desde la cámara. Como resultado, el origen está en la cámara y se aplican los mismos alimentos del eje, como las coordenadas del dispositivo.

Para llegar desde las coordenadas del ojo a las coordenadas del dispositivo, construye la matriz de proyección. La más simple es la proyección ortográfica que simplemente escala los valores adecuadamente. La proyección en perspectiva es más complicada e implica una perspectiva de simulación.

Finalmente tienes el sistema mundial de coordenadas. Este es el sistema de coordenadas en el que se define su mundo y su cámara es parte de este mundo. Aquí es importante tener en cuenta que las orientaciones de los ejes son tal como las define . Si prefiere z + como arriba, está totalmente bien.

Para ir de las coordenadas mundiales a las coordenadas oculares, defina la matriz de vista. Esto se puede hacer con algo como lookAt. Lo que hace esta matriz es "mover" el mundo para que la cámara esté en el origen y mirando hacia el eje z.

Para calcular la matriz de vista es sorprendentemente simple, necesita para la transformación de la cámara. Básicamente, necesita formular la siguiente matriz:

METRO=X[1]y[1]z[1]-pags[1]X[2]y[2]z[2]-pags[2]X[3]y[3]z[3]-pags[3]0 00 00 01

Los vectores x, y y z pueden tomarse directamente de la cámara. En el caso de mirarlos, los derivaría de los valores objetivo, ojo (centro) y arriba. Al igual que:

z=norteormetrounalyozmi(miymi-tunarsolmit)X=norteormetrounalyozmi(tupags×z)y=zX

Pero si tiene estos valores por ahí, puede tomarlos tal como están.

Obtener p es un poco más complicado. No es la posición en coordenadas mundiales sino la posición en coordenadas de cámara. Una solución simple aquí es inicializar dos matrices, una con solo x, y y z y una segunda con -eye y multiplicarlas. El resultado es la matriz de vista.

Para ver cómo se ve esto en el código:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

código completo

Y finalmente, en aras de la exhaustividad, también tiene el sistema de coordenadas de objeto. Este es el sistema de coordenadas en el que se almacenan las mallas. Con la ayuda de la matriz modelo, las coordenadas de malla se convierten en el sistema de coordenadas mundial. En la práctica, las matrices de modelo y vista se combinan en la denominada matriz de vista de modelo.

rioki
fuente
1
Si pudiera votar esta respuesta cien veces, lo haría. ¡Gracias por una respuesta completa y completa que aborda todo lo que me confundió y proporciona el código y el enlace también! He pasado todo el día leyendo libros de matemáticas sobre este tema y con su respuesta y el código de ejemplo y la página vinculada, si esto no es suficiente para resolverlo, entonces debería dejarlo ahora. Si pudiera pedir solo una aclaración, en esa última muestra de código, ¿estaría en lo cierto al decir que esas matrices están en orden de columna mayor y la de arriba está en fila mayor?
Grady
Esto es un poco confuso, las matrices son columnas principales, pero la columna está en la fila. Entonces, para asignar las matemáticas reales al código, debe transponer la matriz. Ver github.com/rioki/glm/blob/master/src/matrix.h#l72 Esto se asigna exactamente a openGL y cómo sería si se usara float[16].
rioki
Ah, sí lo creo, pero solo quería estar seguro, ¡gracias de nuevo! Has sido de gran ayuda, realmente lo aprecio.
Grady