Respostas:
Você pode decompor seu quaternion em um conjunto de ângulos de guinada / inclinação / rotação, mas geralmente é um exagero.
Em vez de compor seus quaternions assim:
cameraOrientation = cameraOrientation * framePitch * frameYaw;
Tente o seguinte:
cameraOrientation = framePitch * cameraOrientation * frameYaw;
Nunca gerará inclinação / rotação e é equivalente a armazenar guinada e inclinação separadamente
framePitch
e frameYaw
float
tipos? Também agradeceria alguns esclarecimentos sobre sua primeira frase.
cameraOrientation
, framePitch
e frameYaw
são todos quatérnions (cada Quatérnion é 4 flutuadores ou duplos).
Esse é um problema que tive por um tempo e não consegui encontrar respostas para, então pensei em publicá-lo aqui.
Na verdade é bem simples. Como você provavelmente está fazendo as rotações é assim:
currentDirection * newRotation;
Mas, fazer assim também não funciona.
newRotation * currentDirection;
O que você precisa fazer é fazê-lo na primeira ordem para as rotações para cima e para baixo e na segunda ordem para as rotações laterais.
Para mim, foi assim:
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 um motivo, a primeira maneira tem a rotação em relação à direção lateral atual, que você deseja para cima e para baixo, mas você não deseja isso para as rotações laterais, e é por isso que a segunda ordem é necessária.
Para uma câmera FPS, você geralmente não quer rolar e está limitado a +/- 90 graus de inclinação, então eu acompanharia o estado atual usando ângulos de guinada e inclinação. Todo o poder dos quaternions não é realmente útil para isso.
Você ainda pode converter os ângulos de guinada / pitch de e para quaternions, caso deseje fazer a transição entre a câmera FPS e as câmeras animadas usando a interpolação do quadro-chave de quaternion ou algo assim.
Outro truque simples é colocar a câmera em um GameObject e fazer com que a rotação de guinada controle o objeto do jogo, enquanto a câmera secundária estiver configurada com as coordenadas de afinação:
playerCameraHolder.transform.Rotate(0, rotationYaw, 0);
playerCamera.transform.Rotate(rotationPitch, 0, 0);