Comment empêcher mon appareil photo FPS utilisant Quaternion de s'incliner et de gâcher?

17

J'utilise un appareil photo de type FPS et il utilise des quaternions. Mais, chaque fois que j'essaie de regarder vers le haut puis de côté, cela s'incline et parfois cela peut se retourner. Comment puis-je réparer cela?

Aeodyn
la source
3
(Répondra automatiquement dans 7 heures) ...
Aeodyn

Réponses:

16

Vous pouvez décomposer votre quaternion en un ensemble d'angles de lacet / tangage / roulis, mais c'est généralement exagéré.

Au lieu de composer vos quaternions comme ceci:

cameraOrientation = cameraOrientation * framePitch * frameYaw;

Essaye ça:

cameraOrientation = framePitch * cameraOrientation * frameYaw;

Il ne générera alors jamais d'inclinaison / roulis et équivaut à stocker le lacet et le tangage séparément

ltjax
la source
3
Cette. Ceci est exactement ce que je cherchais. Résolu mon problème dans un one-liner. Agréable!
aardvarkk
1
Sont framePitchet frameYaw floattypes? Je vous serais également reconnaissant de bien vouloir clarifier votre première phrase.
sirdank
1
@sirdank cameraOrientation, framePitchet frameYawsont tous des quaternions (chaque quaternion est composé de 4 flotteurs ou doubles).
Dan
8

C'est un problème que j'ai eu pendant un certain temps, et je n'ai trouvé aucune réponse, j'ai donc pensé le poster ici.

C'est en fait assez simple. Voici comment vous effectuez le plus probablement les rotations:

currentDirection * newRotation;

Mais le faire comme ça ne marche pas non plus.

newRotation * currentDirection;

Ce que vous devez faire, c'est le faire dans le premier ordre pour les rotations vers le haut et vers le bas, et dans le second ordre pour les rotations latérales.

Pour moi, c'était comme ça:

        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;

Pour une raison, la première façon a la rotation par rapport à la direction latérale actuelle, que vous voulez pour le haut et le bas, mais vous ne voulez pas cela pour les rotations latérales, c'est pourquoi le deuxième ordre est nécessaire.

Aeodyn
la source
J'ai dû attendre 7 heures pour répondre au mien ...
Aeodyn
désolé, pouvez-vous expliquer cela avec quelques captures d'écran? "premier ordre" et "deuxième ordre" est un peu déroutant - merci!
Atav32
Lorsque vous travaillez avec des Quaternions, l'ordre est important, comme c'est toujours le cas avec les rotations 3D. Dans mon exemple, "Direction * = newRotation" est identique à "Direction = Direction * newRotation". Mais, avec des rotations à gauche et à droite, nous voulons que ce soit l'inverse. Cela ne le rend pas dépendant de l'inclinaison vers le haut et vers le bas, ce qui provoque le roulis.
Aeodyn
Oh, je pensais que le point des quarternions était qu'il évitait le blocage du cardan et que les rotations étaient toutes indépendantes, mais j'ai peut-être mal lu le manuel. Donc, juste pour clarifier, dites-vous que si vous inversez l'ordre des transformations de rotation, vous pouvez empêcher la caméra de s'incliner? Ou définissez-vous manuellement les transformations de roulis et de tangage sur 0 lorsque vous tournez le lacet?
Atav32
5

Pour une caméra FPS, vous ne voulez généralement pas de roulis et vous êtes limité à +/- 90 degrés, donc je garderais simplement trace de l'état actuel en utilisant les angles de lacet et de tangage. La pleine puissance des quaternions n'est pas vraiment utile pour cela.

Vous pouvez toujours convertir les angles de lacet / tangage vers et depuis les quaternions au cas où vous souhaiteriez faire la transition entre la caméra FPS et les caméras animées en utilisant l'interpolation d'images clés quaternion, ou quelque chose comme ça.

Nathan Reed
la source
0

Une autre astuce simple consiste à placer la caméra dans un GameObject et à faire en sorte que la rotation de lacet contrôle l'objet de jeu, tandis que la caméra enfant est configurée avec les coordonnées de hauteur:

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