3D Kamera Döndürme


9

Lütfen, affet beni, ama yardıma ihtiyacım var ve birkaç haftadır buna bağlı kaldım, ilerleme kaydedemiyorum ve gittiğim her yerde ve farklı bir cevap görüyorum, denediğim her şey çalışmıyor. Yeteri kadar tavsiyem ve tavsiyem oldu, şimdi sadece geriye doğru çalışmam için bana cevap verecek birine ihtiyacım var çünkü bunu anlayamıyorum.

Bu konuyu en karmaşık hale getiren şey, herkesin farklı bir dizi sözleşme veya kural kullanma biçimidir ve yanıtları, ne olduklarını tanımlamaksızın kendi sözleşmelerine dayanır.

İşte en yaygın ve mantıklı görünen şeylere dayanarak oluşturduğum bir dizi sözleşme:

  1. Eksen için Sağ El Kuralı.
  2. Pozitif Y yukarıda, Pozitif Z izleyiciye, Pozitif X sağda.
  3. Row Gölgelendiricilere gönderildiğinde aktarılan büyük matrisler.
    • Pitch: X ekseni etrafında dönüş
    • Sapma: y ekseni etrafında dönüş
    • Rulo: z ekseni etrafında dönüş
  4. Döndürme sırası: Roll, Pitch, Yaw (bu doğru mu? Birisi beni bu konuda kontrol edebilir mi?)
  5. Eksenin pozitif ucundan aşağıya bakıldığında pozitif dönüş değerleri saat yönünde dönüş ile sonuçlanır.
  6. Tüm eksen boyunca 0 dönüş için varsayılan yön, negatif Y'yi gösteren bir vektördür.

.. bu sözleşmeler göz önüne alındığında (yanlışsa beni düzeltin!), nasıl olur:

  • LookAt işlevi yazılsın mı? (lookAt (vektör konumu, vektör göz odak, vektör yukarı))
  • Bir dönme matrisi hesaplayın. (döndürme (x, y, z))

Bu iki soruyu en az son 3 hafta boyunca kendim cevaplamaya çalıştım, LookAt & Rotation Matrix işlevimi en az 30 kez yeniden yazdım, düzinelerce yöntemi test ettim ve üzerinde gördüğüm materyalleri okudum yüzlerce web sitesi ve birçok soru cevaplandı, diğer insanların kodlarını kopyaladı ve şimdiye kadar yaptığım hiçbir şey işe yaramadı, her şey yanlış sonuç verdi. Bazıları doğru rotasyona bile yakın olmayan bazı tuhaf çıktılar üretti.

Dün gece hariç her gece bu konuda çalışıyorum çünkü tekrar tekrar başarısızlıkla o kadar sinirli oluyordum ki durup bir mola vermek zorunda kaldım.

Lütfen, bana doğru yöntemin ne olduğunu gösterin, böylece geriye doğru çalışabilir ve nasıl çalıştığını anlayabilirim, sadece doğru cevabı alamıyorum ve bu beni biraz deli ediyor!

Java ile yazıyorum ama herhangi bir dilde yazılmış kodu alacağım, 3D render kodumun çoğu aslında oldukça parlak çalışıyor, sadece anlayamadığım matematik.

GÜNCELLEME: ÇÖZÜLDÜ

Yardımın için teşekkürler! Şimdi gerçekten anladığım çalışan bir LookAt işlevi var ve daha mutlu olamazdım (eğer herkes elbette görmek istiyorsa sor).

Saha / yaw / roll değişkenlerine dayanan bir döndürme matrisi oluşturmayı tekrar denedim ve yine başarısız gibi görünüyordu, ancak serbest görüş kamerası için euler açılarını kullanmaya çalışırken denemeye karar verdim. rol, bunun yerine bir quaternion sınıfı oluşturacağım, bu yolda gidiş daha iyi şans olabilir, aksi takdirde pitch / yaw küresel koordinatlar olarak kullanmak için başvurur ve rotasyon için yeni çalışan LookAt işlevine güvenirim.

Başka biri benzer bir sorunla karşı karşıya kalırsa ve bana soru sormak istiyorsa, çekinmeyin.

En azından artık sıkışıp kalmadım, yardım için teşekkürler!


Sorununuzu çözdünüz mü, benzer bir sorunla da karşılaştım, lütfen nasıl çözeceğinizi sorabilir misiniz? Teşekkür ederim!
xiao xiao

Yanıtlar:


15

Aradığınızı şu çok iyi açıklamada bulabilirsiniz: http://www.songho.ca/opengl/gl_transform.html

Ama el tutmadan kafa karıştırıcı bulduğum için burada açıklamaya çalışacağım.

Bu noktada 5 koordinat sistemini ve bunların birbirleriyle nasıl ilişkilendiğini göz önünde bulundurmanız gerekir. Bunlar pencere koordinatları, normalleştirilmiş cihaz koordinatları, göz koordinatları, dünya koordinatları ve nesne koordinatlarıdır.

Pencere koordinatları, ekranınızdaki "fiziksel" pikseller olarak görülebilir. Bunlar, pencereleme sisteminin başvurduğu koordinatlardır ve monitörlerinizin doğal çözünürlüğünde çalışırsanız, bunlar aslında tek tek piksellerdir. Pencere koordinat sistemi 2B tamsayılardır ve pencerenize göredir. Burada x + sola, y + ise başlangıç ​​sol üst köşeye gelecek şekilde aşağıdadır. Örneğin aradığınızda bunlarla karşılaşırsınız glViewport.

İkinci küme normalize edilmiş cihaz koordinatlarıdır. Bunlar, aktif görünüm bağlantı noktasının alan kurulumuyla ilgilidir. Görünüm bağlantı noktasının görünür alanı -1'den +1'ye gider ve bu nedenle başlangıç ​​noktası merkezdedir. X + kaldı ve y + yukarı kaldı. Ayrıca z + sahne dışında "var". Bu, 1.

Normalleştirilmiş cihaz koordinatlarından pencere koordinatlarına nasıl gideceğiniz konusunda hiçbir kontrole sahip değilsiniz, bu sizin için örtük olarak yapılır. Sahip olduğunuz tek kontrol glViewportya da benzeri.

OpenGL ile çalışırken, nihai sonucunuz daima normal cihaz koordinatlarında olacaktır. Sonuç olarak, sahnenizi bunlarda nasıl oluşturacağınız konusunda endişelenmeniz gerekir. Yansıtma ve model görünümü matrisini kimlik matrisine ayarlarsanız, doğrudan bu koordinatlarda çizim yapabilirsiniz. Bu, örneğin tam ekran efektleri uygulanırken yapılır.

Bir sonraki göz koordinatlarıdır. Bu kameradan görüldüğü gibi dünya. Sonuç olarak başlangıç ​​noktası kameradadır ve cihaz koordinatları gibi aynı eksen ittifakları uygulanır.

Göz koordinatlarından cihaz koordinatlarına ulaşmak için projeksiyon matrisini oluşturursunuz. En basit olanı, değerleri uygun şekilde ölçekleyen ortografik izdüşümdür. Perspektif projeksiyonu daha karmaşıktır ve simülasyon perspektifini içerir.

Sonunda dünya koordinat sistemine sahipsiniz. Bu, dünyanızın tanımlandığı ve kameranızın bu dünyanın bir parçası olduğu koordinat sistemidir. Burada eksen yönlerinin tam da sizin tanımladığınız gibi olduğuna dikkat etmek önemlidir . Eğer z + 'yı yukarı olarak tercih ederseniz, bu tamamen iyi.

Dünya koordinatlarından göz koordinatlarına ulaşmak için görünüm matrisini tanımlarsınız. Bu gibi bir şeyle yapılabilir lookAt. Bu matrisin yaptığı şey, dünyayı "hareket ettirmektir", böylece kamera başlangıç ​​noktasında ve z eksenine bakar.

Görünüm matrisini hesaplamak şaşırtıcı derecede basittir, kameranın dönüşümüne kadar yapmanız gerekir. Temel olarak aşağıdaki matrisi formüle etmeniz gerekir:

M=x[1]y[1]z[1]p[1]x[2]y[2]z[2]p[2]x[3]y[3]z[3]p[3]0001

X, y ve z vektörleri doğrudan kameradan alınabilir. Bakmak durumunda, onları hedef, göz (merkez) ve yukarı değerlerden elde edersiniz. Şöyle ki:

z=normalize(eyetarget)x=normalize(up×z)y=zx

Ama eğer bu değerlerin etrafta yattığını düşünüyorsanız, onları oldukları gibi alabilirsin.

P elde etmek biraz daha zordur. Dünya koordinatlarındaki pozisyon değil, kamera koordinatlarındaki pozisyon. Buradaki basit bir çözüm, biri yalnızca x, y ve z ile diğeri -eye sahip iki matrisi başlatmak ve bunları birlikte çarpmaktır. Sonuç görünüm matrisidir.

Bunun kodda nasıl görünebileceği hakkında:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

tam kod

Ve son olarak bütünlük uğruna, nesne koordinat sistemine de sahipsiniz. Bu, kafeslerin depolandığı koordinat sistemidir. Model matrisinin yardımıyla ağ koordinatları dünya koordinat sistemine dönüştürülür. Uygulamada, model ve görünüm matrisleri, model görünümü matrisinde birleştirilir.


1
Bu cevabı yüzlerce kez oylayabilseydim yapardım. Şaşkın olduğum her şeyi ele alan ve kod ve bağlantıyı da sağlayan eksiksiz ve eksiksiz bir cevap için teşekkür ederim! Bütün gün bu konuda matematik kitaplarını okudum ve cevabınız ve örnek kod ve bağlantılı sayfa ile, bu anlamaya yetmiyorsa, şimdi bırakmalıyım. Sadece bir açıklama isteyebilirsem, kodun son örneğinde, bu matrislerin sütun büyük düzeninde olduğunu ve yukarıdaki satırın büyük satır olduğunu söyleyebilir miyim?
Grady

Bu biraz karışıklık, matrisler sütun büyük, ancak sütun satırda. Bu yüzden gerçek matematiği kodla eşleştirmek için matrisi sıraya almanız gerekir. Bkz. Github.com/rioki/glm/blob/master/src/matrix.h#l72 Bu, tam olarak openGL ve bunun nasıl kullanılacağı ile eşleşirfloat[16] .
rioki

Ah öyle düşündüm ama sadece emin olmak istedim, tekrar teşekkürler! Çok yardımcı oldun, gerçekten minnettarım.
Grady
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.