Kuaterniyon tabanlı bir kamerayı nasıl uygularım?


14

GÜNCELLEME Buradaki hata oldukça basitti. Derece dönüşümü için bir radyanı kaçırdım. Başka bir sorununuz varsa her şeyi okumaya gerek yok.

Bununla ilgili birkaç öğreticiye baktım ve anladığımı düşündüğümde kuaterniyon tabanlı bir kamera uygulamaya çalıştım. Sorun yakl. 10 derece geri -10 dereceye atlar. Neyin yanlış olduğu hakkında hiçbir fikrim yok. OpenTK kullanıyorum ve zaten bir quaternion sınıfı var. Ben opengl'de bir çaylağım, bunu sadece eğlence için yapıyorum ve kuaterniyonları gerçekten anlamıyorum, bu yüzden muhtemelen burada aptalca bir şey yapıyorum. İşte bazı kod: (Aslında bir vbo yükleyen ve çizen yöntemler dışında neredeyse tüm kod (vbo-s gösteren bir OpenTK örneğinden alınır)

Bir vbo'ya bir küp yüklerim ve kamera için kuaterniyonu başlatırım

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

Buraya bir perspektif projeksiyonu yüklüyorum. Bu başlangıçta yüklenir ve pencereyi her yeniden boyutlandırdığımda.

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

Burada son dönüş değerini alıyorum ve sadece son dönüşü temsil eden yeni bir kuaterniyon oluşturuyorum ve kamera kuaterniyonu ile çarpıyorum. Bundan sonra bunu eksen açısına dönüştürüyorum ki opengl bunu kullanabilsin. (Bunu birkaç çevrimiçi quaternion dersinden anladım)

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

İşte daha iyi açıklamak için 2 resim: Bir süre döndürüyorum ve bundan:

bu

buna atlar

resim açıklamasını buraya girin

Herhangi bir yardım takdir.

Update1 : Bunları bir dosyaya yazan bir streamwriter'a ekliyorum:

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

Günlüğü şu adreste bulabilirsiniz: http://www.pasteall.org/26133/text . 770 satırında, camerarot.Y işaretleri değiştiğinde küp sağdan sola atlar. Bunun normal olup olmadığını bilmiyorum.

Güncelleme2 İşte tam proje.


2
Sorunu anlamıyorum. Oluşturmak için kullandığınız kuaterniyonları yazdırmayı denediniz mi?
Nicol Bolas

1
Kabul edildi, rx, ry ve Quaternion değerlerinizde hata ayıklama.
deceleratedcaviar

Neden tüm projenizi rapidshare olarak bir yere yüklemiyorsun? Daha kolay olurdu.
bobobobo

Tamam eve geldiğimde yükleyeceğim.
gyozo kudor

Yanıtlar:


9

Varsayımı burada doğrulamak için gerekli kodu göstermeseniz de, neredeyse sorunun aslında bu satır olduğunu garanti edebilirim:

cameraRot.ToAxisAngle(out axis, out angle);

Bir dönen açısı olarak ifade değeri radyan ise,

GL.Rotate(angle, axis);

ister açılı sağlanacak derece .

Düzeltmek için, açı değerini GL.Rotate () öğesine aktarırken aşağıdaki gibi dönüştürmeniz gerekir :

GL.Rotate(angle * 180.0/3.141593, axis);

Evet, sorun buydu. :) Çok teşekkürler. Opengl'in derece beklediğini biliyordum, ToAxisAngle'ın derece döndürdüğünü varsaydım. Sadece opentk koduna baktım ve bu radyan. BTW Sonunda tam kaynak kodu verdim.
gyozo kudor

@NickCaplinger, doğru bir şekilde C # 'da, Math.Pio son hesaplamada kullandığım 3.141593 değişmez değerine göre kullanılması gereken bir sabit olduğunu gösterir.
Trevor Powell

1

Yapma. Diğer sahne nesneleri gibi manipüle edilebilen bir kameraya sahip olmak daha az iş gibi görünebilir, ancak uzun vadede bir konum, göz yönü ve yukarı vektör tanımlayabileceğiniz bir kameraya sahip olmak daha iyidir. Özellikle hareket modellerini programlamaya başladığınızda, kuaterniyonlarla çalışmak gerçekten bir acıdır.


1
Kabul. Ben de benim uygulamaları tasarımı "daha iyi olmalı telaffuz zor" yöntemi hayranıyım değilim =)
Patrick Hughes

Quaternion'un telaffuzu zor mu?
notlesh

1
Biraz mizah uzun bir yol kat ediyor = D Çıkarımla, sorunun neden bir quaternion kamera istediğini bilmeyen birinden geldiğini ima ediyorum, sadece düzgün bir terim ve OMG Ben şimdi sooo kötü istiyorum! Yukarıdaki bozuk kodda radyanları ve derece parametrelerini düzgün bir şekilde işlemek gibi bir şey düzgün bir şekilde ele alınmadığında kesinlikle mücadele etmek bir konu değildir.
Patrick Hughes

3
Bu soru gerçekten kameralarla ilgili değil; oyun kodundaki rotasyonların nasıl temsil edileceği ve bu oyun temsillerinin OpenGL'nin bunları kullanabileceği bir forma nasıl dönüştürüleceği ile ilgilidir. Bu tamamen meşru bir soru ve OP'nin etki alanı deneyimi eksikliğiyle alay etmenin herhangi bir şekilde yararlı olduğunu düşünmüyorum. OP'nin aptalca bir hata yaptığı gibi değil; OpenGL'nin açıları ifade ederken dereceleri kullanma ısrarı düpedüz tuhaftır. Herkes bu hatayı ilk kez OpenGL kullanarak yapar. Yani yüksek atlarından inin, insanlar. Tanrım.
Trevor Powell

Kuaterniyon tabanlı bir kameranın nasıl çalıştığını anlamak istedim ve bu projeyi yapacak başka bir şeyim olmadığı bir günde yaptım. Bununla ilgili gerçek bir planım yok.
gyozo kudor

0

OpenTK iç bileşenleri hakkında fazla bir şey bilmiyorum. Deneyimlerime göre, matematik kütüphanesini gerekli hassasiyet (makine) tutan düzgün bir quat uygulaması ile görmedim, çünkü hepsi e ^ 2-e ^ 3 hatalarını etkiliyor. Gördüğünüz etki: hassasiyet (ve epsilon değeri) yaklaşık 10 ^ -5'tir ve sıfıra 'atlar'. Bu benim tahminim :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.