ACTUALIZACIÓN El error aquí fue bastante simple. He perdido una conversión de radianes a grados. No es necesario leer todo si tienes algún otro problema.
Miré varios tutoriales sobre esto y cuando pensé que entendía, intenté implementar una cámara basada en el cuaternión. El problema es que no funciona correctamente, después de girar durante aprox. 10 grados salta de nuevo a -10 grados. No tengo idea de lo que está mal. Estoy usando openTK y ya tiene una clase quaternion. Soy un novato en opengl, estoy haciendo esto solo por diversión, y realmente no entiendo cuaterniones, así que probablemente estoy haciendo algo estúpido aquí. Aquí hay algo de código: (En realidad, casi todo el código, excepto los métodos que cargan y dibujan un vbo (se toma de una muestra de OpenTK que demuestra vbo-s))
Cargo un cubo en un vbo e inicializo el cuaternión para la cámara
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);
}
Cargo una proyección en perspectiva aquí. Esto se carga al principio y cada vez que cambio el tamaño de la ventana.
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);
}
Aquí obtengo el último valor de rotación y creo un nuevo cuaternión que representa solo la última rotación y lo multiplico con el cuaternión de la cámara. Después de esto, lo transformo en ángulo de eje para que opengl pueda usarlo. (Así es como lo entendí de varios tutoriales en línea de quaternion)
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();
}
Aquí hay 2 imágenes para explicar mejor: giro un rato y de esto:
salta a esto
Cualquier ayuda es apreciada.
Actualización 1 : los agrego a una máquina de escribir que escribe en un archivo:
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);
El registro está disponible aquí: http://www.pasteall.org/26133/text . En la línea 770, el cubo salta de derecha a izquierda, cuando camerarot.Y cambia de signo. No sé si esto es normal.
Update2 Aquí está el proyecto completo.
Respuestas:
Si bien no ha mostrado el código necesario para verificar mi suposición aquí, casi puedo garantizarle que su problema es en realidad esta línea:
está devolviendo un valor de ángulo expresado en radianes , mientras
quiere que el ángulo se proporcione en grados .
Para solucionarlo, debe convertir el valor del ángulo al pasarlo a GL.Rotate (), así:
fuente
Math.Pi
constante disponible, que debe usarse con preferencia al valor literal 3.141593 que utilicé en ese cálculo final.No lo hagas Puede parecer que sería menos trabajo tener una cámara que se pueda manipular como otros objetos de escena, pero a la larga es mejor tener una cámara donde se pueda definir una posición, la dirección del ojo y el vector hacia arriba. Especialmente cuando comienzas a programar modelos de movimiento, es realmente un trabajo trabajar con cuaterniones.
fuente
No sé mucho sobre los componentes internos de OpenTK. En mi experiencia, no vi la biblioteca matemática con la implementación adecuada de quat que mantiene la precisión (máquina) necesaria, porque todos afectan los errores e ^ 2-e ^ 3. Entonces, el efecto que ves: la precisión (y el valor de épsilon) es de aproximadamente 10 ^ -5, y 'salta' cerca de cero. Esta es mi suposición :)
fuente