¿Cómo evitar que mi cámara FPS con Quaternion se incline y se estropee?

17

Estoy usando una cámara tipo FPS, y usa cuaterniones. Pero, cada vez que trato de mirar hacia arriba y hacia los lados, se inclina y, a veces, puede volcarse. ¿Cómo puedo arreglar esto?

Aeodyn
fuente
3
(Contestará a sí mismo en 7 horas) ...
Aeodyn

Respuestas:

16

Podrías descomponer tu cuaternión en un conjunto de ángulos de guiñada / inclinación / balanceo, pero eso suele ser excesivo.

En lugar de componer tus cuaterniones de esta manera:

cameraOrientation = cameraOrientation * framePitch * frameYaw;

Prueba esto:

cameraOrientation = framePitch * cameraOrientation * frameYaw;

Entonces nunca generará inclinación / balanceo y es equivalente a almacenar guiñada y cabeceo por separado

ltjax
fuente
3
Esta. Esto es exactamente lo que estaba buscando. Resolvió mi problema de una sola vez. ¡Agradable!
aardvarkk
1
¿Son framePitchy frameYaw floattipos? Además, agradecería algunas aclaraciones sobre su primera oración.
sirdank
1
@sirdank cameraOrientation, framePitchy frameYawson todos los cuaterniones (cada uno de cuaternión es de 4 flotadores o dobles).
Dan
8

Este es un problema que tuve durante un tiempo y no pude encontrar ninguna respuesta, así que pensé en publicarlo aquí.

En realidad es bastante simple. La forma más probable de hacer las rotaciones es la siguiente:

currentDirection * newRotation;

Pero, hacerlo así tampoco funciona.

newRotation * currentDirection;

Lo que tiene que hacer es hacerlo en el primer orden para las rotaciones hacia arriba y hacia abajo, y en el segundo orden para las rotaciones laterales.

Para mí fue así:

        if (keyboard.IsKeyDown(Keys.Up))
            Direction = Direction * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Down))
            Direction = Direction * Quaternion.CreateFromAxisAngle(new Vector3(-1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Left))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), TurnSpeed) * Direction;
        if (keyboard.IsKeyDown(Keys.Right))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, -1), TurnSpeed) * Direction;

Por una razón, la primera forma tiene la rotación relativa a la dirección lateral actual, que desea para arriba y abajo, pero no para las rotaciones laterales, por lo que se necesita el segundo orden.

Aeodyn
fuente
Tuve que esperar 7 horas para contestar las mías ...
Aeodyn
lo siento, ¿puedes explicar esto con algunas capturas de pantalla? "primer orden" y "segundo orden" son un poco confusos, ¡gracias!
Atav32
Cuando se trabaja con Quaternions, el orden es importante, como siempre lo hace con las rotaciones 3D. En mi ejemplo, "Direction * = newRotation" es lo mismo que "Direction = Direction * newRotation". Pero, con rotaciones izquierda y derecha, lo queremos al revés. Esto hace que no dependa de la inclinación hacia arriba y hacia abajo, lo que provoca un balanceo.
Aeodyn
Oh, pensé que el objetivo de los cuartones era que evitaba el bloqueo del cardán y que las rotaciones eran todas independientes, pero es posible que haya leído mal el libro de texto. Entonces, para aclarar, ¿está diciendo que si invierte el orden de las transformaciones de rotación, puede evitar que la cámara se incline? ¿O está configurando manualmente las transformaciones de balanceo y cabeceo a 0 cuando gira el guiñada?
Atav32
5

Para una cámara FPS, generalmente no desea rodar y está limitado a +/- 90 grados de inclinación, por lo que solo debería seguir el estado actual utilizando los ángulos de guiñada y inclinación. El pleno poder de los cuaterniones no es realmente útil para esto.

Todavía puede convertir los ángulos de guiñada / inclinación hacia y desde los cuaterniones en caso de que desee realizar la transición entre la cámara FPS y las cámaras animadas utilizando la interpolación de fotogramas clave de cuaternión, o algo así.

Nathan Reed
fuente
0

Otro truco simple es colocar la cámara en un GameObject y hacer que la rotación Yaw controle el objeto del juego, mientras que la cámara secundaria está configurada con las coordenadas Pitch:

playerCameraHolder.transform.Rotate(0, rotationYaw, 0);
playerCamera.transform.Rotate(rotationPitch, 0, 0);
Victor S
fuente