Bir kamerayı hedef noktası hakkında nasıl yörüngeye alabilirim?


18

Kameranın evrende özgürce hareket ettiği bir sahne çiziyorum. Kamera sınıfı görünüm (veya bakma ) noktasını, kameranın konumunu ve yukarı vektörünü izler . Bu vektörler / noktalar daha sonra gluLookAt'a geçirilir.

Kaydırma ve yakınlaştırma uygulamak neredeyse önemsizdir. Ancak, konuya bakışta daha fazla sorun olması için rotasyon buluyorum . Ben 2 açıları, birini alan bir fonksiyon Camera.rotate yazmak istiyorum o döner yukarı / aşağı ve döner bıraktı kimse bu / sağ merkezde yer alır hayali bir küre boyunca bakmak noktası.

Bunu yapmanın kolay bir yolu var mı?

Kuaterniyonları (kısaca) okudum, ancak sahnemin nispeten basit yapısı göz önüne alındığında daha kolay bir çözüm olup olmadığını görmek istedim.


Bir eksen ve bir açı verildiğinde, araç kutunuzda başlangıç ​​noktasını döndürmek için herhangi bir şey var mı?
sam hocevar

Gevşek Kuaterniyon anlayışım dışında hiçbir şey yok. Buna daha çok baktığımda, Kuaterniyonların cevap olabileceğini düşünüyorum. Ancak, Quaternion formüllerinde kullanılacak x, y ve z eksen değerlerinin nasıl hesaplanacağından emin değilim .
Luke

Size kuaterniyonların gidilecek yol olmadığını söylemeyeceğim. Sorununuza çok iyi bir çözümdür. Ancak bir kuaterniyon sınıfına ve GL ve GLU ile etkileşime girme yollarına ihtiyacınız olacak ve önce dönüşüm matrislerine aşina olmaya çalışmanız gerektiğini düşünüyorum. Diğerleri buna katılmayabilir.
sam hocevar

rotasyonları hangi sırayla yaptığınızı düşünün. dünya boşluğuna gitmek veya kamera boşluğuna gitmek için rotasyon uygulamak farklıdır
Charlie

Yanıtlar:


25

İstediğinize Arcball dönüşü denir. Kuaterniyonlar ancak nasıl çalıştıklarını anlarsanız kolay çözümdür. Ancak aynısını quaternions olmadan da yapabilirsiniz.

Ön koşul

Genel olarak nesnelerin nasıl döndürüleceğini biliyor musunuz? Diyelim ki başlangıç ​​noktasında bir nesneniz var. Nasıl döndürdüğünüzü biliyor musunuz (ipucu: bazı döndürme matrisi ile çarpın)? Evet ise, önce nesneyi çevirir ve sonra döndürürseniz ne olacağını bildiğinizi varsayıyorum?

Bir açı matrisini açı ekseninden nasıl hesaplayacağınızı bilmelisiniz (pasta gibi kolay, sayısız denkleme çevrimiçi bakın, birçoğu size kodu verir)

Çözüm

  • Kameranın yukarı ve sağ vektörlerini alın. Normalleştirilmesi gerektiğini unutmayın.
  • Vektörü netleme noktasından kameraya alın (camPosition - Focus). Bu, döndüreceğiniz vektördür. Bu camFocusVector diyelim .
  • Kameraya göre yaw / pitch'de ne kadar döndürmek istediğinize karar verin
  • İki dönme matrisi oluşturun. 1. dönüş matrisi, karar verdiğiniz eksen ve sapma açısı olarak kameranın üst kısmını kullanır . 2 rotasyon matrisi kullanacak hakkı ekseni gibi kameranın Saha sen karar açısı.
  • Şimdi yeni dönme matrisleriyle camFocusVector öğesini döndürün . Bu, artık kameranın başlangıç ​​noktasına göre yeni konumunuzdur. Tabii ki, odak noktasına göre olmasını istiyoruz ...
  • Netleme noktası konumunu camFocusVector öğesine ekleyin . Bu şimdi kameranızın yeni pozisyonu. Kameranızı uygun şekilde çevirin.
  • Son olarak, lookAt () işlevinizi çağırarak kameradan odak noktasına odaklanmasını isteyin

Uyarılar

Kameranızın çalışmayı durduracağı belirli durumlara veya tekilliklere dikkat etmeniz gerekir. Örneğin düz aşağı / yukarı bakıyorum. Bunlarla nasıl başa çıkacağınızı anlamanıza izin vereceğim.

EDIT1: Kameranın ortonormal vektörleri nasıl yeniden hesaplanır

Kameranın yönünü zaten biliyorsunuz ((cameraPos - focusPoint) .normalize ()). Şimdi kameranızın yukarı + Y (veya dünyanızın mevcut yukarı ekseni ... yani size kalmış) olduğunu varsayın. Şimdi sadece çapraz yön ile yukarı almak için hakkı . Bitti? Hayır! Yukarı vektörünüz artık diğer ikisine dik değil. O, çapraz düzeltmek için hakkı ile yön ve yeni olsun yukarı .

O Not Gram-Schmidt orthonormalize vektörlere kullanılması gerektiğini gerçekten ne olduğunu.

Yine, bazı durumlarda işe yaramayacağı için uyarıları not edin ( örneğin , yön yukarıya paraleldir ).


Doğru vektörün normalize(up ^ camFocusVector)(veya solaksa tersinin) kullanılarak elde edilebileceğini unutmayın .
sam hocevar

Şimdiye kadar iyi görünüyordu, sol / sağ rotasyon için güzel çalıştı (bu kadar kolay vektör kadar var). @SamHocevar yorumunuzdaki '^' ne anlama geliyor? Bu çapraz ürün mü? Ayrıca, çevirileri yaptıktan sonra up vektörünü nasıl yeniden hesaplayabilirim?
Luke

@ Luke: EDIT1'imi kontrol et
Samaursa

1
@Samaursa Çok teşekkür ederim. Çözümünüz mükemmel çalışıyor ve bu süreçte çok şey öğrendim!
Luke

2
Bu MÜKEMMEL bir cevap, açıklamanız için çok teşekkür ederim. Benim durumumda, kameranın sadece XY düzlemindeki hedef nokta etrafında dönmesini istedim ve bu yüzden tüm hesaplamaları yaptıktan sonra, cameraRight.z öğesini her zaman 0'a ayarladım ve sonra cameraUp vektörünü hesapladım. Bu istenen etkiyi verdi. Sadece paylaşmayı düşündüm
Codemonkey

1

İhtiyacınız olan şey, temel olarak bir hedef konumu tutan ve kamerayı bu hedefin etrafında "küresel" bir şekilde taşımanıza izin veren tipik bir ArcBall kameradır.

XNA'da ama IIRC Daha önce bu uygulamayı kullandım ve oldukça iyi çalıştı:

http://roy-t.nl/index.php/2010/02/21/xna-simple-arcballcamera/


Bu uygulama sadece doğrudan doğru vektör boyunca hareket ediyor gibi görünüyor, bu da küçük miktar değerleri için bir arcball'a yaklaşıyor . Ayrıca kamerayı hareket ettirmek istediğim yerde LookAt noktasını da hareket ettiriyor (yakın ama zarif bir şekilde farklı). Samaursa'nın bunu başarmanın en basit yolunu sağladığına inanıyorum.
Luke

Geri bildiriminiz için teşekkür ederiz. Bu uygulamayı biraz "blackbox" olarak kullandığımı itiraf etmeliyim ama herhangi bir sorun fark etmedim. Açıklığa kavuşturmak için belki de MoveCameraRight / MoveCameraForward yöntemlerinden mi bahsediyordunuz? Bu yöntemler kamerayı kaydırmak için eklenmiştir, ancak Arcball arayüzünün bir parçası değildir. Kamerayı hedefin etrafında döndürmek istiyorsanız Yaw veya Pitch özelliklerini değiştirmeniz yeterlidir.
David Gouveia

Üzgünüm, haklısın, bunlar kaydırma yöntemleri. Sapma ve zift değiştiğinde matris için nasıl kirli bir bayrak koyduğunu fark etmedim.
Luke

0

İşte bir nokta etrafında dönen kodum, kendimi çok tekrar kullandım.

float distance;      // Straight line distance between the camera and look at point

// Calculate the camera position using the distance and angles
float camX = distance * -sinf(camAngleX*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));
float camY = distance * -sinf((camAngleY)*(M_PI/180));
float camZ = -distance * cosf((camAngleX)*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));

// Set the camera position and lookat point
gluLookAt(camX,camY,camZ,   // Camera position
          0.0, 0.0, 0.0,    // Look at point
          0.0, 1.0, 0.0);   // Up vector

1
Temelde başlangıçta böyle yaptım. Bu şekilde yapmanın birçok sorunu var (en azından benim için). Temel olarak bu uygulama sadece yaklaşık 2 sabit ekseni döndürür. Let Diyelim ki döndürmek demek kadar neredeyse hiç kuzey kutbu . Sonra sağa döndürün . Kameranın doğru vektörünü dünyanın dört bir yanına kadar takip etmek yerine kendinizi küçük bir daire içinde döndüğünü göreceksiniz .
Luke

Şimdi bundan bahsettiğinize göre, sanırım soruna bakmanın iki farklı yolu var. Uygulamamda ArcBall kamerayı denizdeki bir hedef ada etrafında döndürmek için kullandım ve 3 eksen eksenini kullansaydım düz yanlış görünüyordu (adanın baş aşağı veya yan tarafını görmek gibi).
David Gouveia

Kamera açılarını buraya nasıl getirebilirim?
rafvasq

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.