Farenin hareketine göre dönen bir kamera anlamına geldiğinizi varsayarsak:
Uygulamanın bir yolu, kamera konumunu ve uzayda dönüşünü takip etmektir. Küresel koordinatlar bunun için uygun olur, çünkü açıları doğrudan temsil edebilirsiniz.
float m_theta;
float m_phi;
float m_radius;
float3 m_target;
Kamera bulunmaktadır P m_theta, m_phi ve m_radius ile tanımlanır. Bu üç değeri değiştirerek istediğimiz yerde serbestçe dönebilir ve hareket edebiliriz. Ancak, her zaman m_target'a bakar ve döneriz. m_target kürenin yerel kaynağıdır. Bununla birlikte, bu kökeni dünya uzayında istediğimiz yere hareket ettirmekte özgürüz.
Üç ana kamera işlevi vardır:
void Rotate(float dTheta, float dPhi);
void Zoom(float distance);
void Pan(float dx, float dy);
En basit formlarında, Rotate () ve Zoom () önemsizdir. Sadece m_theta, m_phi ve m_radius değişikliklerini yapın:
void Camera::Rotate(float dTheta, float dPhi) {
m_theta += dTheta;
m_phi += dPhi;
}
void Camera::Zoom(float distance) {
m_radius -= distance;
}
Kaydırma biraz daha karmaşıktır. Kamera yatay kaydırma, kamerayı geçerli kamera görünümüne göre sola / sağa ve / veya yukarı / aşağı hareket ettirmek olarak tanımlanır. Bunu yapmanın en kolay yolu, mevcut kamera görünümümüzü küresel koordinatlardan kartezyen koordinatlara dönüştürmektir. Bu bize yukarı ve doğru vektörler verecektir .
void Camera::Pan(float dx, float dy) {
float3 look = normalize(ToCartesian());
float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);
float3 right = cross(look, worldUp);
float3 up = cross(look, right);
m_target = m_target + (right * dx) + (up * dy);
}
inline float3 ToCartesian() {
float x = m_radius * sinf(m_phi) * sinf(m_theta);
float y = m_radius * cosf(m_phi);
float z = m_radius * sinf(m_phi) * cosf(m_theta);
float w = 1.0f;
return float3(x, y, z, w);
}
İlk olarak, küresel vektör koordinat sistemimizi görünüm vektörümüzü elde etmek için kartezyen'e dönüştürdük . Sonra, dünya ile vektör çarpımı yapmak kadar bir almak için, vektör sağ vektör. Bu, doğrudan kamera görünümünün sağını gösteren bir vektördür. Son olarak, kamerayı almak için başka vektör çarpımı yapmak kadar vektörü.
Tavayı bitirmek için m_target'ı yukarı ve sağ vektörler boyunca hareket ettiririz .
Sormanız gereken bir soru şudur: Neden her zaman kartezyen ve küresel arasında dönüştürme (Görünüm matrisini oluşturmak için de dönüştürmeniz gerekir).
İyi soru. Ben de bu soruyu sordum ve sadece kartezyen kullanmaya çalıştım. Sonunda rotasyon sorunları var. Kayan nokta işlemleri tam olarak kesin olmadığından, birden fazla rotasyon kameraya yavaşça karşılık gelen ve istemeden yuvarlanan hataları biriktirir.
Sonunda, küresel koordinatlarla takıldım. Ekstra hesaplamalara karşı koymak için, görünüm matrisini önbelleğe aldım ve sadece kamera hareket ettiğinde hesapladım.
Son adım, bu Camera sınıfını kullanmaktır . Uygulamanızın MouseDown / Yukarı / Kaydırma işlevlerinin içindeki uygun üye işlevini aramanız yeterlidir:
void MouseDown(WPARAM buttonState, int x, int y) {
m_mouseLastPos.x = x;
m_mouseLastPos.y = y;
SetCapture(m_hwnd);
}
void MouseUp(WPARAM buttonState, int x, int y) {
ReleaseCapture();
}
void MouseMove(WPARAM buttonState, int x, int y) {
if ((buttonState & MK_LBUTTON) != 0) {
if (GetKeyState(VK_MENU) & 0x8000) {
// Calculate the new phi and theta based on mouse position relative to where the user clicked
float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
float dTheta = ((float)(m_mouseLastPos.x - x) / 300);
m_camera.Rotate(-dTheta, dPhi);
}
} else if ((buttonState & MK_MBUTTON) != 0) {
if (GetKeyState(VK_MENU) & 0x8000) {
float dx = ((float)(m_mouseLastPos.x - x));
float dy = ((float)(m_mouseLastPos.y - y));
m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);
}
}
m_mouseLastPos.x = x;
m_mouseLastPos.y = y;
}
void MouseWheel(int zDelta) {
// Make each wheel dedent correspond to a size based on the scene
m_camera.Zoom((float)zDelta * m_cameraScrollFactor);
}
M_camera * Faktör değişkenleri sadece kameranızın dönme / tava / kaydırma hızını değiştiren ölçek faktörleridir
Yukarıdaki kod, bir yan proje için yaptığım kamera sisteminin basitleştirilmiş bir sahte kod sürümüdür: camera.h ve camera.cpp . Kamera Maya kamera sistemini taklit etmeye çalışıyor. Kod ücretsiz ve açık kaynaklıdır, bu yüzden kendi projenizde kullanmaktan çekinmeyin.