Bagaimana cara menerapkan kamera berbasis angka empat?

14

UPDATE Kesalahan di sini sangat sederhana. Saya telah melewatkan konversi radian ke derajat. Tidak perlu membaca semuanya jika Anda memiliki masalah lain.

Saya melihat beberapa tutorial tentang ini dan ketika saya pikir saya mengerti saya mencoba menerapkan kamera berbasis angka empat. Masalahnya adalah itu tidak berfungsi dengan benar, setelah berputar kira-kira. 10 derajat melompat kembali ke -10 derajat. Saya tidak tahu apa yang salah. Saya menggunakan openTK dan sudah memiliki kelas angka empat. Saya seorang noob di OpenGL, saya melakukan ini hanya untuk bersenang-senang, dan tidak benar-benar mengerti angka empat, jadi mungkin saya melakukan sesuatu yang bodoh di sini. Berikut ini beberapa kode: (Sebenarnya hampir semua kode kecuali metode yang memuat dan menggambar vbo (diambil dari sampel OpenTK yang menunjukkan vbo-s))

Saya memuat kubus ke vbo dan menginisialisasi angka empat untuk 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);
}

Saya memuat proyeksi perspektif di sini. Ini dimuat di awal dan setiap kali saya mengubah ukuran jendela.

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);
}

Di sini saya mendapatkan nilai rotasi terakhir dan membuat angka empat baru yang hanya mewakili rotasi terakhir dan melipatgandakannya dengan angka empat kamera. Setelah ini saya mengubah ini menjadi sumbu-sudut sehingga opengl dapat menggunakannya. (Ini adalah bagaimana saya memahaminya dari beberapa tutorial angka empat 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();
}

Berikut adalah 2 gambar untuk menjelaskan lebih baik: Saya memutar beberapa saat dan dari ini:

ini

itu melompat ke ini

masukkan deskripsi gambar di sini

Bantuan apa pun dihargai.

Update1 : Saya menambahkan ini ke penulis aliran yang menulis ke 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);

Log tersedia di sini: http://www.pasteall.org/26133/text . Pada baris 770 kubus melompat dari kanan ke kiri, ketika camerarot.Y mengubah tanda. Saya tidak tahu apakah ini normal.

Update2 Ini adalah proyek lengkap.

gyozo kudor
sumber
2
Saya tidak mengerti masalahnya. Sudahkah Anda mencoba mencetak angka empat yang Anda gunakan untuk menyajikan?
Nicol Bolas
1
Setuju, debug nilai rx, ry, dan Quaternion Anda.
decaviatedcaviar
Mengapa Anda tidak mengunggah seluruh proyek Anda di suatu tempat ke rapidshare? Akan lebih mudah.
bobobobo
OK saya akan mengunggahnya begitu sampai di rumah.
gyozo kudor

Jawaban:

9

Meskipun Anda belum menunjukkan kode yang diperlukan untuk memverifikasi asumsi saya di sini, saya hampir dapat menjamin bahwa masalah Anda sebenarnya adalah baris ini:

cameraRot.ToAxisAngle(out axis, out angle);

mengembalikan sudut nilai dinyatakan dalam radian , sementara

GL.Rotate(angle, axis);

inginkan sudut disediakan dalam derajat .

Untuk memperbaikinya, Anda perlu mengonversi nilai sudut saat meneruskannya ke GL.Rotate (), seperti ini:

GL.Rotate(angle * 180.0/3.141593, axis);
Trevor Powell
sumber
Ya, itu masalahnya. :) Terima kasih banyak. Saya tahu OpenGL mengharapkan derajat, saya berasumsi bahwa ToAxisAngle mengembalikan derajat. Saya baru saja melihat kode opentk dan itu adalah radian. BTW saya telah memberikan kode sumber lengkap di akhir.
gyozo kudor
@NickCaplinger dengan benar menunjukkan bahwa dalam C #, ada Math.Pikonstanta yang tersedia, yang harus digunakan sebagai preferensi terhadap nilai 3.141593 literal yang saya gunakan dalam perhitungan akhir itu.
Trevor Powell
1

Jangan. Mungkin kelihatannya lebih sulit memiliki kamera yang dapat dimanipulasi seperti objek pemandangan lainnya, tetapi dalam jangka panjang lebih baik memiliki kamera di mana Anda dapat menentukan posisi, arah mata, dan vektor ke atas. Terutama ketika Anda mulai pemrograman model gerak itu benar-benar menyebalkan untuk bekerja dengan angka empat.

wooyay
sumber
1
Sepakat. Saya bukan penggemar metode "jika sulit untuk mengatakannya pasti lebih baik" dalam mendesain aplikasi saya juga =)
Patrick Hughes
Quaternion sulit diucapkan?
notlesh
1
Sedikit humor berjalan jauh = D Dengan kesimpulan saya menyiratkan bahwa pertanyaan itu datang dari seseorang yang tidak tahu MENGAPA dia ingin kamera angka empat, hanya saja itu kata kunci yang rapi dan OMG saya ingin itu sangat buruk sekarang! Ini tentu bukan masalah untuk ditangani ketika sesuatu seperti menangani radian dan parameter derajat dengan benar dalam kode yang rusak di atas tidak ditangani dengan benar.
Patrick Hughes
3
Pertanyaan ini sebenarnya bukan tentang kamera; ini tentang bagaimana merepresentasikan rotasi dalam kode gim, dan bagaimana mengubah representasi gim tersebut menjadi bentuk yang dapat digunakan OpenGL. Ini pertanyaan yang sangat sah, dan saya pikir mengejek kurangnya pengalaman domain OP sangat membantu. Bukannya OP melakukan kesalahan bodoh; Desakan OpenGL untuk menggunakan derajat ketika mengekspresikan sudut benar-benar aneh. Semua orang membuat kesalahan ini pertama kali menggunakan OpenGL. Jadi, turunkan kuda tinggi Anda, teman-teman. Ya ampun.
Trevor Powell
Saya hanya ingin memahami bagaimana kamera berbasis angka empat bekerja dan saya membuat proyek ini di hari ketika saya tidak memiliki hal lain untuk dilakukan. Saya tidak punya rencana nyata dengan ini.
gyozo kudor
0

Tidak tahu banyak tentang internal OpenTK. Dalam pengalaman saya, saya tidak melihat perpustakaan matematika dengan implementasi quat yang tepat yang menjaga presisi (mesin) yang dibutuhkan, karena semuanya mempengaruhi kesalahan e ^ 2-e ^ 3. Jadi efek yang Anda lihat: presisi (dan nilai epsilon) adalah sekitar 10 ^ -5, dan 'melompat' mendekati nol. Ini tebakan saya :)

infra
sumber