ОНОВЛЕННЯ Помилка тут була досить простою. Я пропустив перетворення радіану в градуси. Не потрібно читати всю справу, якщо у вас є якісь інші проблеми.
Я переглянув кілька навчальних посібників з цього приводу, і коли я подумав, що зрозумів, я намагався реалізувати камеру на основі кватерніона. Проблема в тому, що вона не працює належним чином, після обертання протягом прибл. 10 градусів він стрибає назад до -10 градусів. Я поняття не маю, що не так. Я використовую openTK, і він вже має клас кватерніона. Я нобій в opengl, я роблю це просто для розваги, і не дуже розумію кватерніонів, тому, напевно, тут роблю щось дурне. Ось такий код: (Насправді майже весь код, за винятком методів, що завантажують та малюють vbo (він взято із зразка OpenTK, який демонструє vbo-s))
Я завантажую куб у vbo і ініціалізую четвертинку для камери
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);
}
Я завантажую сюди перспективну проекцію. Це завантажується на початку і кожен раз, коли я змінюю розмір вікна.
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);
}
Тут я отримую останнє значення обертання і створюю новий кватерніон, який представляє лише останнє обертання, і помножую його на кватерніон камери. Після цього я перетворюю це на кут осі, щоб opengl міг ним користуватися. (Ось як я зрозумів це з кількох підручників онлайн-кватерніона)
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();
}
Ось 2 зображення, щоб пояснити краще: я обертаюсь деякий час і з цього:
вона стрибає в це
Будь-яка допомога вдячна.
Update1 : я додаю їх до сценарію, який записує у файл:
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);
Журнал доступний тут: http://www.pasteall.org/26133/text . На лінії 770 куб стрибає справа наліво, коли camerarot.Y змінює знаки. Я не знаю, чи нормально це.
Update2 Ось повний проект.