UPDATE Der Fehler hier war ziemlich einfach. Ich habe eine Umrechnung von Bogenmaß in Grad verpasst. Sie müssen das Ganze nicht lesen, wenn Sie ein anderes Problem haben.
Ich habe mir mehrere Tutorials dazu angesehen und als ich dachte, ich verstehe, habe ich versucht, eine quaternionsbasierte Kamera zu implementieren. Das Problem ist, dass es nach ca. 10 Grad springt es auf -10 Grad zurück. Ich habe keine Ahnung, was los ist. Ich benutze openTK und es hat bereits eine Quaternion-Klasse. Ich bin ein Noob bei opengl, ich mache das nur zum Spaß und verstehe Quaternionen nicht wirklich, also mache ich hier wahrscheinlich etwas Dummes. Hier ist ein bisschen Code: (Eigentlich fast der gesamte Code außer den Methoden, die ein vbo laden und zeichnen (er stammt aus einem OpenTK-Beispiel, das vbo-s demonstriert).
Ich lade einen Würfel in ein VBO und initialisiere die Quaternion für die Kamera
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);
}
Ich lade hier eine perspektivische Projektion. Dies wird zu Beginn geladen und jedes Mal, wenn ich die Fenstergröße verändere.
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);
}
Hier erhalte ich den letzten Rotationswert und erstelle ein neues Quaternion, das nur die letzte Rotation darstellt, und multipliziere es mit dem Kameraquaternion. Danach wandle ich dies in Achsenwinkel um, damit opengl es benutzen kann. (So habe ich es aus mehreren Online-Quaternion-Tutorials verstanden.)
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();
}
Hier sind 2 Bilder zur besseren Erklärung: Ich drehe eine Weile und daraus:
es springt hinein
Jede Hilfe wird geschätzt.
Update1 : Ich füge diese einem Streamwriter hinzu, der in eine Datei schreibt:
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);
Das Protokoll ist hier verfügbar: http://www.pasteall.org/26133/text . In Zeile 770 springt der Würfel von rechts nach links, wenn camerarot.Y die Vorzeichen wechselt. Ich weiß nicht, ob das normal ist.
Update2 Hier ist das komplette Projekt.