Mam Vector3, który ma kąt eulera dla każdej osi.
Zwykle, gdy chcę utworzyć macierz obrotu, skorzystam z funkcji takich jak D3DXMatrixRotationX przekazując odpowiedni kąt z mojego wektora obrotu powyżej i pomnożę macierze (ZXY), aby utworzyć ogólną macierz obrotu, która jest używana do utworzenia kompletnej macierzy transformacji obiektu.
Jednak ta metoda spowoduje wygenerowanie zestawu obrotów w przestrzeni obiektów. Oznacza to, że przekazanie wektora (90, 0, 90) do mojej metody spowoduje efektywny obrót w przestrzeni świata o (90, 90, 0).
Czy istnieje sposób, aby zawsze zapewnić, że każdy element mojego wektora obrotu spowoduje obrót wokół odpowiednich osi wyrównanych w przestrzeni świata?
EDYTOWAĆ:
To jest animacja tego, co się obecnie dzieje - chcę sposób na obracanie się wokół niebieskich osi, a nie czerwonych.
EDYCJA 2:
Należy zauważyć, że nie szukam rozwiązania obejmującego kąty Eulera, ale po prostu sposób, w jaki mogę przedstawić transformację wielu obrotów wokół osi świata.
źródło
Odpowiedzi:
W oparciu o twoje komentarze, wydaje się, że przechowujesz orientację obiektu jako zestaw kątów Eulera i zwiększasz / zmniejszasz kąty, gdy gracz obraca obiekt. Oznacza to, że masz coś takiego jak ten pseudokod:
Jak zauważa Charles Beattie , ponieważ rotacje nie dojeżdżają do pracy, nie zadziała to zgodnie z oczekiwaniami, chyba że gracz obróci obiekt w tej samej kolejności, w której
eulerAnglesToMatrix()
zastosuje rotacje.W szczególności rozważ następującą sekwencję obrotów:
W naiwnej reprezentacji kąta Eulera, jak zaimplementowano w powyższym pseudokodzie, obroty te zostaną anulowane, a obiekt powróci do pierwotnej orientacji. W prawdziwym świecie tak się nie dzieje - jeśli mi nie wierzysz, weź sześciokątną kostkę lub kostkę Rubika, pozwól x = y = 90 ° i wypróbuj sam!
Jak zauważyłeś we własnej odpowiedzi , rozwiązaniem jest przechowywanie orientacji obiektu jako macierzy obrotu (lub czwartorzędu) i aktualizowanie tej macierzy na podstawie danych wprowadzonych przez użytkownika. Oznacza to, że zamiast powyższego pseudokodu zrobiłbyś coś takiego:
(Technicznie, ponieważ każda macierz obrotu lub kwaternion może być przedstawiony jako zbiór kątów Eulera, to jest można je stosować do przechowywania orientacji obiektu. Jednak fizycznie były zasada łączenia dwóch kolejnych obrotów, reprezentowane jako kątów Eulera, w pojedynczy obrót jest raczej skomplikowany i zasadniczo sprowadza się do przekształcenia obrotu w macierze / ćwiartki, pomnożenia ich, a następnie przekształcenia wyniku z powrotem w kąty Eulera).
źródło
Problem z obrotami polega na tym, że większość ludzi myśli o tym pod kątem kątów Eulera, ponieważ są one łatwe do zrozumienia.
Jednak większość ludzi zapomina o tym, że kąty Eulera to trzy kolejne kąty . Oznacza to, że obrót wokół pierwszej osi spowoduje, że następny obrót będzie związany z pierwszym pierwotnym obrotem, dlatego nie można niezależnie obrócić wektora wokół każdej z 3 osi przy użyciu kątów Eulera.
To bezpośrednio przekłada się na macierze, kiedy mnożymy dwie macierze, można pomyśleć o tym zwielokrotnieniu jako przekształceniu jednej macierzy w przestrzeń drugiej macierzy.
Ma to nastąpić przy 3 dowolnych obrotach sekwencyjnych, nawet przy użyciu czwartorzędów.
Chcę podkreślić fakt, że czwartorzędy nie są rozwiązaniem blokady kłębków. W rzeczywistości blokada drgań zawsze będzie mieć miejsce, jeśli reprezentowałeś kąty Eulera za pomocą czwartorzędów. Problem ten nie jest reprezentacją, problemem jest to , że kolejne etapy 3.
Rozwiązanie?
Rozwiązaniem dla niezależnego obracania wektora wokół 3 osi jest połączenie w jedną oś i jeden kąt, w ten sposób możesz pozbyć się kroku, w którym musisz wykonać sekwencyjne mnożenie. To skutecznie przełoży się na:
Moja macierz obrotu reprezentuje wynik obrotu wokół X, Y i Z.
zamiast interpretacji Eulera
Moja macierz obrotu reprezentuje obrót wokół X, a następnie Y, a następnie Z.
Aby to wyjaśnić, zacytuję z wikipedii Twierdzenie o rotacji Eulera:
Zauważ, że mnożenie 3 macierzy zawsze będzie reprezentowało 3 sekwencyjne obroty.
Teraz, aby połączyć obroty wokół 3 osi, musisz uzyskać jedną oś i pojedyncze kąty, które reprezentują obrót wokół X, Y, Z. Innymi słowy, musisz użyć reprezentacji Oś / Kąt lub czwartorzędu, aby pozbyć się kolejnych obrotów.
Zazwyczaj dokonuje się tego, zaczynając od orientacji początkowej (orientacja może być traktowana jako kąt osi), zwykle reprezentowany jako ćwiartka lub kąt osi, a następnie modyfikując tę orintację, aby reprezentowała orientację docelową. Na przykład zaczynasz od czwartego kwartału tożsamości, a następnie obracasz o różnicę, aby osiągnąć orientację docelową. W ten sposób nie tracisz żadnego stopnia swobody.
źródło
Przełączanie kombinacji rotacji z przestrzeni obiektów na przestrzeń świata jest trywialne: wystarczy odwrócić kolejność stosowania rotacji.
W twoim przypadku zamiast mnożenia macierzy
Z × X × Y
wystarczy tylko wykonać obliczeniaY × X × Z
.Uzasadnienie tego można znaleźć na Wikipedii: konwersja między obrotami wewnętrznymi i zewnętrznymi .
źródło
Z
(przestrzeń obiektu), następnie 50 stopni wokółX
(przestrzeń obiektu), a następnie 45 stopni wokółY
(przestrzeń obiektu). Jest to dokładnie to samo, co obrót o 45 stopni dookołaY
( przestrzeń świata ), następnie o 50 stopni dookołaX
( przestrzeń świata ), a następnie o 50 stopni dookołaZ
( przestrzeń świata ).Podam moje rozwiązanie jako odpowiedź, dopóki ktoś nie wyjaśni, dlaczego to działa.
Przy każdym renderowaniu odbudowywałem czwartorzęd przy użyciu kątów zapisanych w wektorze rotacji, a następnie stosując czwartorzęd do mojej ostatecznej transformacji.
Jednak, aby utrzymać go wokół osi świata, musiałem zachować czwartorzęd we wszystkich ramkach i obracać obiekty tylko przy użyciu różnicy kątów, tj.
(Pełne dla czytelności)
Myślę, że dsilva.vinicius próbował dojść do tego punktu.
źródło
Będziesz musiał zapisać kolejność obrotów.
Przechowuj swoją bieżącą macierz obrotu i przedwcześnie każdy obrót, jak tylko się pojawi.
źródło
Oprócz odpowiedzi @ concept3d możesz użyć 3 zewnętrznych macierzy obrotu, aby obracać się wokół osi we współrzędnych świata. Cytowanie z Wikipedii :
Zatem potrzebujesz odwrócić kolejność obrotów w stosunku do tego, co zrobiłbyś przy użyciu wewnętrznych (lub lokalnych) obrotów. @Syntac poprosił o obrót zxy, więc powinniśmy wykonać obrót zewnętrzny yxz, aby osiągnąć ten sam wynik. Kod jest poniżej:
Wyjaśnienie wartości macierzy tutaj .
Ten kod jest dydaktyczny, a nie optymalny, ponieważ można ponownie użyć kilku macierzy D3DXMATRIX.
źródło