MISE À JOUR L'erreur ici était assez simple. J'ai raté une conversion de radian en degrés. Pas besoin de lire le tout si vous avez un autre problème.
J'ai regardé plusieurs tutoriels à ce sujet et quand j'ai cru comprendre, j'ai essayé d'implémenter une caméra basée sur quaternion. Le problème est qu'il ne fonctionne pas correctement, après avoir tourné pendant env. 10 degrés, il revient à -10 degrés. Je n'ai aucune idée de ce qui ne va pas. J'utilise openTK et il a déjà une classe quaternion. Je suis un noob chez opengl, je fais ça juste pour le plaisir, et je ne comprends pas vraiment les quaternions, donc je fais probablement quelque chose de stupide ici. Voici du code: (En fait, presque tout le code, sauf les méthodes qui chargent et dessinent un vbo (il est tiré d'un exemple OpenTK qui illustre les vbo-s))
Je charge un cube dans un vbo et initialise le quaternion pour la caméra
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
cameraPos = new Vector3(0, 0, 7);
cameraRot = Quaternion.FromAxisAngle(new Vector3(0,0,-1), 0);
GL.ClearColor(System.Drawing.Color.MidnightBlue);
GL.Enable(EnableCap.DepthTest);
vbo = LoadVBO(CubeVertices, CubeElements);
}
Je charge ici une projection en perspective. Ceci est chargé au début et chaque fois que je redimensionne la fenêtre.
protected override void OnResize(EventArgs e) {
base.OnResize(e);
GL.Viewport(0, 0, Width, Height);
float aspect_ratio = Width / (float)Height;
Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 64);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref perpective);
}
Ici, j'obtiens la dernière valeur de rotation et crée un nouveau quaternion qui ne représente que la dernière rotation et le multiplie avec le quaternion de la caméra. Après cela, je le transforme en axe-angle afin que opengl puisse l'utiliser. (Voici comment je l'ai compris à partir de plusieurs tutoriels quaternion en ligne)
protected override void OnRenderFrame(FrameEventArgs e) {
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
double speed = 1;
double rx = 0, ry = 0;
if (Keyboard[Key.A]) {
ry = -speed * e.Time;
}
if (Keyboard[Key.D]) {
ry = +speed * e.Time;
}
if (Keyboard[Key.W]) {
rx = +speed * e.Time;
}
if (Keyboard[Key.S]) {
rx = -speed * e.Time;
}
Quaternion tmpQuat = Quaternion.FromAxisAngle(new Vector3(0,1,0), (float)ry);
cameraRot = tmpQuat * cameraRot;
cameraRot.Normalize();
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
Vector3 axis;
float angle;
cameraRot.ToAxisAngle(out axis, out angle);
//////////////////////////////////////////////////////////////////////
// THIS IS WHAT I DID WRONG: I NEED TO CONVERT FROM RADIANS TO DEGREES
//////////////////////////////////////////////////////////////////////
//BEFORE
//GL.Rotate(angle, axis);
//AFTER
GL.Rotate(angle * (float)180.0/(float)Math.PI, axis);
GL.Translate(-cameraPos);
Draw(vbo);
SwapBuffers();
}
Voici 2 images pour mieux expliquer: je tourne un moment et à partir de là:
ça saute dedans
Toute aide est appréciée.
Update1 : je les ajoute à un streamwriter qui écrit dans un fichier:
sw.WriteLine("camerarot: X:{0} Y:{1} Z:{2} W:{3} L:{4}", cameraRot.X, cameraRot.Y, cameraRot.Z, cameraRot.W, cameraRot.Length);
sw.WriteLine("ry: {0}", ry);
Le journal est disponible ici: http://www.pasteall.org/26133/text . À la ligne 770, le cube saute de droite à gauche lorsque camerarot.Y change de signe. Je ne sais pas si c'est normal.
Update2 Voici le projet complet.
Réponses:
Bien que vous n'ayez pas montré le code nécessaire pour vérifier mon hypothèse ici, je peux presque garantir que votre problème est en fait que cette ligne:
renvoie une valeur d' angle exprimée en radians , tandis que
veut que l' angle soit fourni en degrés .
Pour le corriger, vous devez convertir la valeur d' angle lors du passage à GL.Rotate (), comme ceci:
la source
Math.Pi
constante disponible, qui doit être utilisée de préférence à la valeur littérale de 3,141593 que j'ai utilisée dans ce calcul final.Non. Il peut sembler que ce serait moins de travail d'avoir une caméra qui peut être manipulée comme d'autres objets de scène, mais à long terme, il est préférable d'avoir une caméra où vous pouvez définir une position, une direction des yeux et un vecteur vers le haut. Surtout lorsque vous commencez à programmer des modèles de mouvement, c'est vraiment pénible de travailler avec des quaternions.
la source
Je ne sais pas grand chose sur les internes d'OpenTK. D'après mon expérience, je n'ai pas vu de bibliothèque mathématique avec une implémentation correcte de quat qui conserve la précision nécessaire (machine), car toutes affectent les erreurs e ^ 2-e ^ 3. Donc l'effet que vous voyez: la précision (et la valeur epsilon) est d'environ 10 ^ -5, et elle "saute" près de zéro. C'est ma conjecture :)
la source