2012-02-02 8 views
5

Mój aparat obraca się wokół punktu, gdy próbuję zmienić orientację. Jeśli obrócę aparat, powiedzmy, 30 stopni w osi Y, zamiast kamery patrząc 30 stopni w prawo, kamera obraca się wokół punktu, na który patrzy.Dlaczego mój aparat obraca się wokół punktu za pomocą tej matematyki?

o is the camera, A and B are 3D models. The lines show line-of-sight. 
This is what I expect: 
    A B 
    | >/
    |/
    |/
    |/ 
    o 

This is what actually happens: 
    A B 
    |\ 
    | \ 
    | \ 
    | > \ 
      o 

Teraz, z mojego zrozumienia, aby poruszyć kamerą, muszę przenieść świat przez odwrotność tej wartości. Więc jeśli chcę przesunąć +1 w osi Z, przetłumaczyć świat -1 w osi Z. Ponieważ używam kwaternionów do reprezentowania orientacji, używam odwrotności kwaternionu kamery (ponieważ orientacje są zawsze jednostkowymi kwaterunkami, optymalizuję się za pomocą sprzężenia zamiast obliczać odwrotność), aby obrócić świat o odpowiednią wielkość.

Oto jak przekonwertować kwaternion do matrycy, gdzie Q jest odwrócony quaternion:

[1 - 2 * (q.y * q.y + q.z * q.z) 2 * (q.x * q.y - q.w * q.z)  2 * (q.x * q.z + q.w * q.y)   0] 
|2 * (q.x * q.y + q.w * q.z)  1 - 2 * (q.x * q.x + q.z * q.z) 2 * (q.y * q.z - q.w * q.x)   0| 
|2 * (q.x * q.z - q.w * q.y)  2 * (q.y * q.z + q.w * q.z)  1 - 2 * (q.x * q.x + q.y * q.y)  0| 
[0         0         0         1] 

Następnie ustawić element translacji matrycy:

[... ... ... -x] 
|... ... ... -y| 
|... ... ... -z| 
[0  0  0  1] 

i wreszcie Powielam to na stos matrycy widoku modelu, a następnie renderuję wszystkie moje obiekty. Jestem prawie pewien, że ta matematyka jest poprawna, ale nie daje wyników, których oczekiwałem. Najwyraźniej problemem są naprzód i prawe wektory, więc jedyne pytanie brzmi: dlaczego się mylą i jak należy je ustawić, jeśli chcę uzyskać oczekiwane rezultaty. Dzięki.

EDYTOWANIE: Znalazłem rozwiązanie z this guy's quaternion camera class. Najpierw skonstruowałem macierz rotacyjną, tak jak robiłem to wcześniej, ale potem pobieram wektory kolumnowe macierzy z pierwszej, drugiej i trzeciej kolumny (odpowiednio xa, ya i za). Potem zestaw składowej translacyjnej matrycy, jak poniżej:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

następnie otrzymana osnowa może być pomnożona na stos ModelView matrycy i działa doskonale.

+0

Dokonaj edycji rozwiązania i zaakceptuj je. W ten sposób oznaczamy tutaj rozwiązywane pytania. Myślę też, że zasługujesz na wyjaśnienie, co się dzieje. Napiszę na to odpowiedź. – datenwolf

Odpowiedz

1

EDYCJA: Znalazłem rozwiązanie z klasy kamerowej tego faceta. Najpierw skonstruowałem matrycę obrotową , tak jak robiłem to wcześniej, ale potem biorę wektory macierzy z kolumn pierwszej, drugiej i trzeciej (odpowiednio xa, ya i za). Potem zestaw składowej translacyjnej matrycy tak:

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

następnie otrzymana osnowa może być pomnożona na matrycy ModelView stosu i działa doskonale.

Tak, to jest dokładnie to, co bym zasugerował, tylko trochę inaczej. Musisz zrozumieć, że OpenGL nie ma kamery, ale zamiast tego po prostu przesuwasz świat w przeciwnym kierunku, więc musisz znaleźć odwrotną macierz transformacji.

Kamera obraca się i porusza. To sprawia, że ​​rzeczy są bardzo proste. Tnverse translacji jest tym samym wektorem o przeciwnym znaku, a odwrotnością macierzy obrotu jest jej transpozycja (kolumny i rzędy wymieniane). Spójrzmy teraz na homogenicznej macierzy transformacji jak OpenGL ich używa:

R t 
0 1 

Górny lewy 3 x 3 jest częścią obrotową, skrajna prawa kolumna jest wektorem translacji. Sądzę, że reszta już się wymyśliła.

0

Szczerze mówiąc, próba znalezienia macierzy do pomnożenia do macierzy widoku modułu jest bardzo skomplikowana i podatna na błędy. Jest wiele nieporozumień i specjalnych przypadków. Na przykład, jeśli szukasz 90 stopni w górę, dwie z twoich osi stają się takie same. Logiczny problem polega na tym, że jeśli odwracasz głowę do tyłu, więc przechodzisz przez najwyższy punkt, twój wektor powinien być odwrócony, prawda? Ale co, jeśli przegapisz to przez 0,0001 stopnia? wtedy powinieneś obrócić głowę wokół tego punktu, aby twój wektor się nie powiódł.

Moim zdaniem najlepiej jest podejść do problemu z innej perspektywy. Załóżmy, że dwa przypadki:

  • góry nogami niemożliwe:
    • Zachowaj punkt dla lokalizacji kamery oraz długość/szerokość geograficzna dla kierunku. Dzięki prostych operacji sin/cos można uzyskać wektor kierunkowy. Twój górę wektor jest (0, 1, 0)
    • toczenia jest po prostu zmieniając długość i szerokość geograficzną
  • Upside down to możliwe:
    • Oprócz położenia kamery, zachować zarówno w górę i wektory docelowe.
    • Podczas skręcania obróć w prawo = cel x w górę, a następnie zmień cel na x * w prawo + y * w górę
    • Następnie musisz znormalizować wektor docelowy i obliczyć nowy. Wiele przypadków obsługuje jednak .

Wszakże z nich, wystarczy zadzwonić gluLookAt.

+0

"Szczerze mówiąc, próba znalezienia macierzy do pomnożenia do macierzy widoku modułu jest bardzo skomplikowana i podatna na błędy." Nie, nie jest. Matryce są najbardziej dokładnym sposobem myślenia o względnych orientacjach współrzędnych. Każda z pierwszych 3 kolumn jest jednym z podstawowych wektorów przekształconego układu współrzędnych. Czwarta kolumna to względne tłumaczenie. Znacznie łatwiej jest zapisać matrycę kamery z widoku i wektorów docelowych, a następnie z całą tą trygonometrią pomiędzy nimi. – datenwolf

+0

Wiem o tym. To, co mówię, to to, że jeśli na przykład masz 3 różne rodzaje ruchów (powiedzmy: poruszaj, skręcaj i przechylaj) do następnej klatki, to jest to o wiele łatwiejsze z pozycją/szerokością/długością i wreszcie przekształceniem jej w macierz, niż próba zastosowania każdej operacji do macierzy poprzedniej. – Shahbaz

Powiązane problemy