2008-09-20 11 views
13

Tengo un objeto en 3D que deseo rotar en 3D. La manera más fácil es traducir directamente el movimiento del mouse X e Y a la rotación sobre los ejes Y y X, pero si hay rotación en ambos ejes, la forma en que gira el modelo se torna altamente contraintuitiva (es decir, si volteas el objeto 180 grados sobre uno eje, su movimiento a lo largo del otro eje se invierte).La mejor forma de traducir el movimiento de arrastre del mouse a la rotación en 3D de un objeto

Podría simplemente hacer el método anterior, pero en lugar de almacenar la cantidad para girar sobre los dos ejes, podría almacenar la matriz de rotación completa y simplemente rotarla en los mismos ejes para cada arrastre del mouse, pero estoy preocupado de que eso tenga problemas de precisión rápidamente.

Respuesta

4

Crea una matriz de acumuladores e inicialízalo con la identidad.

Cada cuadro, aplíquelo a su vista de modelo/estado de matriz mundial antes de dibujar el objeto.

Con el movimiento del mouse, construya una matriz de rotación sobre el eje X con alguna sensitivity_constant * delta_x. Construya otra matriz de rotación sobre el eje Y para el otro componente. Multiplica uno, luego el otro en el acumulador.

El acumulador cambiará a medida que mueva el mouse. Al dibujar, orientará el objeto como esperabas.

Además, la persona que habla de cuaterniones tiene razón; esto se verá bien solo para pequeños cambios incrementales. Si lo arrastra rápidamente en diagonal, no girará del modo que espera.

+0

sobreestimé el efecto de la imprecisión de punto flotante. Simplemente acumulando las rotaciones funciona bien. Examinaré los cuaterniones, pero como solo estoy girando alrededor de 2 ejes, todo se ve bien. –

3

Puede hacer frente a la pérdida de precisión al renormalizar su matriz de rotación para que cada una de las 3 filas sea perpendicular nuevamente. O puede regenerar la matriz de rotación que va a modificar en función de la información existente sobre el objeto, y esto elimina la necesidad de renormalización.

Como alternativa, puede usar quaternions, que es una alternativa a los ángulos de Euler para hacer frente a las rotaciones.

Aprendí mucho de esto en mis primeros días desde this faq, que trata este problema (aunque para otra aplicación) en Euler's are Evil.

6

Probablemente sea más intuitivo rotar el objeto alrededor del eje perpendicular a la dirección de arrastre actual, ya sea incrementalmente con cada movimiento del mouse, o relativo a la posición de inicio del arrastre. Las dos opciones ofrecen interacciones de usuario ligeramente diferentes, cada una de las cuales tiene sus ventajas y desventajas.

Hay una forma relatively straightforward para convertir un ángulo y un vector 3d que representa el eje que se está girando en una matriz de rotación.

Tiene razón en que la actualización de una matriz de rotación sin procesar a través de rotaciones incrementales dará como resultado que la matriz ya no sea una matriz de rotación pura. Esto se debe a que una matriz de rotación 3x3 tiene tres veces más datos de los necesarios para representar una rotación.

Una forma más compacta de representar rotaciones es con Euler Angles, teniendo un mínimo de 3 vectores de valor. Puede tomar la rotación actual como un vector de ángulo de Euler, convertirla en una matriz, aplicar la rotación (incremental o no) y convertir la matriz de nuevo en un vector de ángulo de Euler. Ese último paso eliminaría naturalmente cualquier componente no rotacional de su matriz, de modo que una vez más terminaría con una matriz de rotación pura para el siguiente estado.

Los ángulos de Euler son conceptualmente agradables, sin embargo, es mucho trabajo realizar las conversiones de ida y vuelta.

Una opción más práctica es Quaternions (also), que son cuatro vectores de elementos. Los cuatro elementos especifican rotación y escala uniforme, y sucede que si ingresas y normalizas el vector a la longitud de la unidad, obtendrás un factor de escala de 1.0. Resulta que un valor de ángulo de eje también puede ser convertido a un valor de cuaternión muy fácilmente por

q.x = sin(0.5*angle) * axis.x; 
q.y = sin(0.5*angle) * axis.y; 
q.z = sin(0.5*angle) * axis.z; 
q.w = cos(0.5*angle); 

A continuación, puede tomar el producto de cuaternión (que utiliza la multiplicación sólo es simple y adición) del cuaternión de rotación actual e incremental rotación quaternion para obtener un nuevo cuaternión que representa la realización de ambas rotaciones. En ese punto, puede normalizar la longitud para garantizar una rotación pura, pero de lo contrario continuará combinando rotaciones iterativamente.

La conversión del cuaternión a una matriz de rotación es muy sencilla (solo usa multiplicación y adición) cuando se desea mostrar el modelo en su estado girado utilizando las API de gráficos tradicionales.

5

En mi curso de Gráficos por computadora, nos dieron el siguiente código que nos permitió no reinventar la rueda.

trackball.h

trackball.c

Cuestiones relacionadas