Po tak wielu lekturach dotyczących transformacji nadszedł czas, aby zaimplementować trackball dla mojej aplikacji. Rozumiem, że muszę utworzyć wektor od początku do miejsca kliknięcia myszy, a następnie inny od początku do miejsca zwolnienia myszy.
Moje pytanie brzmi: czy muszę przekształcić współrzędne pikseli (x, y) na współrzędne świata, czy powinienem po prostu zrobić wszystko w przestrzeni obrazu (biorąc pod uwagę, że przestrzeń obrazu to projekcja 2D sceny mierzona w pikselach)?
EDYTOWAĆ
Odpowiedź Richiego Samsa jest bardzo dobra. Myślę jednak, że stosuję nieco inne podejście, proszę mnie poprawić, jeśli się mylę lub coś źle rozumiem.
W mojej aplikacji mam SimplePerspectiveCamera
klasy, która odbiera position
od aparatu, position of the target
patrzymy, w up
wektorze fovy
, aspectRatio
, near
i far
odległościach.
Za pomocą tych tworzę moje matryce Widok i Projekcja. Teraz, jeśli chcę powiększyć / pomniejszyć, aktualizuję pole widzenia i aktualizuję matrycę projekcji. Jeśli chcę przesuwać, przesuwam pozycję kamery i patrzę na deltę, którą wytwarza mysz.
Wreszcie, do rotacji mogę użyć transformacji kąt-oś lub czwartorzędów. W tym celu zapisuję współrzędne pikseli w miejscu naciśnięcia myszy, a następnie, gdy mysz się porusza, zapisuję również współrzędne pikseli.
Dla każdej pary coords można obliczyć Z wartość podana formuła kuli, czyli sqrt (1-x ^ 2-y ^ 2), a następnie obliczyć z wektorami, które go od target
do PointMousePressed
i od target
celu PointMouseMoved
, do iloczynu aby uzyskać oś obrotu i użyć dowolnej metody do obliczenia nowej pozycji kamery.
Jednak moje największe wątpliwości to to, że wartości (x, y, z) podane są w współrzędnych pikselowych, a przy obliczaniu wektorów używam tego, target
co jest punktem w światowych współrzędnych. Czy to mieszanie układu współrzędnych nie wpływa na wynik obrotu, który próbuję wykonać?
z
wartości kuli o promieniur
, jednak nie jestem pewien, czy ta kula żyje w przestrzeni świata czy przestrzeni obrazu i jakie są tego konsekwencje. Być może przesadzam z problemem.Odpowiedzi:
Zakładając, że masz na myśli kamerę obracającą się w oparciu o ruch myszy:
Jednym ze sposobów jego realizacji jest śledzenie położenia kamery i jej obrotu w przestrzeni. Współrzędne sferyczne są do tego wygodne, ponieważ można bezpośrednio przedstawić kąty.
Kamera znajduje się w punkcie P zdefiniowanym przez m_theta, m_phi i m_radius. Możemy obracać i swobodnie poruszać się, gdziekolwiek chcemy, zmieniając te trzy wartości. Zawsze jednak patrzymy na m_target i obracamy się wokół niego. m_target to lokalne pochodzenie kuli. Możemy jednak swobodnie przenosić to pochodzenie w dowolne miejsce na świecie.
Istnieją trzy główne funkcje aparatu:
W najprostszych postaciach Rotate () i Zoom () są trywialne. Wystarczy zmodyfikować odpowiednio m_theta, m_phi i m_radius:
Panoramowanie jest nieco bardziej skomplikowane. Panoramowanie kamery definiuje się jako przesuwanie kamery w lewo / prawo i / lub góra / dół odpowiednio do bieżącego widoku kamery. Najłatwiejszym sposobem na to jest konwersja naszego obecnego widoku kamery ze współrzędnych sferycznych na współrzędne kartezjańskie. To daje nam do góry i odpowiednie wektory.
Najpierw przekształcamy nasz sferyczny układ współrzędnych na kartezjański, aby uzyskać wektor wyglądu . Następnie wykonujemy iloczyn wektorowy z wektorem świat do góry , aby uzyskać właściwy wektor. Jest to wektor wskazujący bezpośrednio na prawo od widoku z kamery. Na koniec robimy kolejny krzyżowy produkt wektorowy, aby ustawić kamerę w górę .
Aby zakończyć przesuwanie, przesuwamy m_target wzdłuż wektorów w górę i w prawo .
Jedno z pytań, które możesz zadać, brzmi: po co cały czas konwertować między kartezjańskim i sferycznym (musisz także przekonwertować, aby utworzyć macierz Widoku).
Dobre pytanie. Ja też miałem to pytanie i starałem się używać wyłącznie kartezjańskich. Masz problemy z obrotami. Ponieważ operacje zmiennoprzecinkowe nie są dokładnie precyzyjne, wielokrotne obroty powodują kumulowanie się błędów, które odpowiadały kamerze powoli i niezamierzenie toczyły się.
W końcu utknąłem ze współrzędnymi sferycznymi. Aby przeciwdziałać dodatkowym obliczeniom, skończyłem buforowanie macierzy widoku i obliczam ją tylko wtedy, gdy kamera się porusza.
Ostatnim krokiem jest użycie tej klasy aparatu. Wystarczy wywołać odpowiednią funkcję członka w funkcjach MouseDown / Up / Scroll aplikacji:
Zmienne m_camera * Factor są tylko czynnikami skalującymi, które zmieniają szybkość, z jaką kamera obraca się / przesuwa / przewija
Kod, który mam powyżej, jest uproszczoną pseudokodową wersją systemu kamer, który stworzyłem dla pobocznego projektu: camera.h i camera.cpp . Aparat próbuje naśladować system kamer Maya. Kod jest darmowy i open source, więc możesz go używać we własnym projekcie.
źródło
Jeśli chcesz zajrzeć do gotowego rozwiązania, mam port z odpowiednio steruje Three.js trackball w C ++ i C #
źródło