AGGIORNAMENTO L'errore qui è stato piuttosto semplice. Ho perso una conversione da radiante a gradi. Non c'è bisogno di leggere tutto se hai qualche altro problema.
Ho guardato diversi tutorial su questo e quando pensavo di aver capito ho cercato di implementare una fotocamera a quaternione. Il problema è che non funziona correttamente, dopo aver ruotato per ca. 10 gradi torna a -10 gradi. Non ho idea di cosa non vada. Sto usando openTK e ha già una classe quaternion. Sono un novellino di Opengl, lo sto facendo solo per divertimento e non capisco davvero i quaternioni, quindi probabilmente sto facendo qualcosa di stupido qui. Ecco un po 'di codice: (In realtà quasi tutto il codice tranne i metodi che caricano e disegnano un vbo (è preso da un campione OpenTK che dimostra vbo-s))
Carico un cubo in un vbo e inizializzo il quaternione per la videocamera
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);
}
Carico qui una proiezione prospettica. Questo viene caricato all'inizio e ogni volta che ridimensiono la finestra.
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);
}
Qui ottengo l'ultimo valore di rotazione e creo un nuovo quaternione che rappresenta solo l'ultima rotazione e lo moltiplico con il quaternione della fotocamera. Dopo questo, lo trasformo in angolo dell'asse in modo che Opengl possa usarlo. (È così che l'ho capito da diversi tutorial quaternion online)
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();
}
Qui ci sono 2 immagini per spiegare meglio: io giro un po 'e da questo:
salta in questo
Qualsiasi aiuto è apprezzato.
Update1 : aggiungo questi a uno streamwriter che scrive in un file:
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);
Il registro è disponibile qui: http://www.pasteall.org/26133/text . Alla linea 770 il cubo salta da destra a sinistra, quando camerarot.Y cambia segno. Non so se sia normale.
Update2 Ecco il progetto completo.