GLM: Kąty Eulera do czwartorzędu

12

Mam nadzieję, że znasz GL Mathematics ( GLM ), ponieważ mam problem, nie mogę złamać:

Mam zestaw kątów Eulera i muszę wykonać płynną interpolację między nimi. Najlepszym sposobem jest ich konwersja do Quaternions i zastosowanie alrogirthm SLERP.

Mam problem z inicjowaniem glm :: quaternion za pomocą Euler Angles, proszę?

Wciąż czytam Dokumentację GLM , ale nie mogę znaleźć odpowiedniego Quaternion constructor signature, który zająłby trzy Kąty Eulera. Najbliższą, jaką znalazłem, jest funkcja angleAxis () , która przyjmuje wartość kąta i oś dla tego kąta. Uwaga, proszę, czego szukam, jak analizować RotX, RotY, RotZ.


Dla Twojej informacji jest to powyższa sygnatura funkcji metnioned angleAxis () :

detail::tquat< valType > angleAxis (valType const &angle, valType const &x, valType const &y, valType const &z)
Bunkai.Satori
źródło

Odpowiedzi:

13

Nie znam GLM, ale przy braku funkcji do bezpośredniej konwersji kątów Eulera na ćwiartki, możesz użyć do tego funkcji „obrotu wokół osi” (takich jak „angleAxis”).

Oto jak (pseudokod):

Quaternion QuatAroundX = Quaternion( Vector3(1.0,0.0,0.0), EulerAngle.x );
Quaternion QuatAroundY = Quaternion( Vector3(0.0,1.0,0.0), EulerAngle.y );
Quaternion QuatAroundZ = Quaternion( Vector3(0.0,0.0,1.0), EulerAngle.z );
Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ;

(Lub może być konieczne przełączenie mnożników czwartorzędu, w zależności od kolejności, w jakiej mają być zastosowane obroty kąta eulera)

Alternatywnie, po przejrzeniu dokumentacji GLM wydaje się, że możesz przekonwertować kąty eulera -> matrix3 -> quaternion w następujący sposób:

toQuat( orient3( EulerAngles ) )
Trevor Powell
źródło
dobra odpowiedź, ponieważ mniej niejasna jest kolejność aplikacji.
Richard Fabian
@ Trevor: +1, Cześć Trevor, dziękuję za dobrą odpowiedź. To wygląda na najbardziej praktyczne rozwiązanie tutaj. Mogę łatwo przełączać się między kolejnością mnożenia obrotu. Być może liczba kombinacji jest przyczyną, dla której konwersja kąta Eulera na kwaternion nie jest możliwa w GLM.
Bunkai.Satori
Mimo, że wszystkie odpowiedzi są dobre i wartościowe, moim zdaniem, to jest najbardziej praktyczny. Chciałbym zaznaczyć to jako odpowiedź zaakceptowaną .
Bunkai.Satori
@ Trevor: In Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ ;, jaki rodzaj mnożenia miałeś na myśli? Dziwi mnie, że GLM nie przeciąża się operator *dla mnożenia Quaternion, więc być może będę musiał ręcznie wykonać mnożenie .
Bunkai.Satori
3
@Bunkai pojęcie mnożenia czwartorzędu jest podobne do mnożenia macierzy, nie jest to ani kropka, ani iloczyn krzyżowy. Jeśli chcesz zrozumieć użycie czwartorzędów, a następnie przyzwyczaić się do macierzy i zrozumieć kąty osi, ich podstawowa koncepcja jest dość podobna do czwartorzędów, matematyka jest nieco bardziej zaawansowana, ale gdy zrozumiesz kąty osi, wówczas czwartorzędy nie są już daleko.
Maik Semder
16
glm::quat myquaternion = glm::quat(glm::vec3(angle.x, angle.y, angle.z));

W przypadku, gdy anglejest glm::vec3zawierającym pak, odchylenie zwijana odpowiednio.

PS. W razie wątpliwości przejdź do nagłówków i spójrz. Definicję można znaleźć w glm / gtc / quaternion.hpp:

explicit tquat(tvec3<T> const & eulerAngles) {
        tvec3<T> c = glm::cos(eulerAngle * value_type(0.5));
    tvec3<T> s = glm::sin(eulerAngle * value_type(0.5));

    this->w = c.x * c.y * c.z + s.x * s.y * s.z;
    this->x = s.x * c.y * c.z - c.x * s.y * s.z;
    this->y = c.x * s.y * c.z + s.x * c.y * s.z;
    this->z = c.x * c.y * s.z - s.x * s.y * c.z;    
}

Gdzie quatjest typ zmiennoprzecinkowy tquat.

spowolniony
źródło
To dość niejednoznaczne, w jakiej kolejności miałyby one zastosowanie? Eulery mają uporządkowane obroty i wydaje się, że konstruktor czwartorzędu nie przejmuje się tym.
Richard Fabian
Definicja funkcji jest dokładnie taka sama jak twoja; Umieściłem to w mojej odpowiedzi, jeśli miało to znaczenie.
spowolniłaviar
nie kolejność argumentów, kolejność stosowania rotacji. Moja odpowiedź zawiera kolejność XYZ, zaczerpniętą z artykułu w Wikipedii, jednak w mojej starej firmie korzystamy z kolejności ZYX, a w mojej obecnej YZX. kąt x jest nadal pierwszą wartością na liście wektor / argument we wszystkich przypadkach, ale rzeczywista wynikowa transformacja nie jest taka sama.
Richard Fabian
Naprawiłem swoją odpowiedź na pytanie o rotację, abyś mógł zobaczyć, jak łatwo zmienić kolejność. Domyślnie akceptuje XYZ, ale możesz to łatwo zmienić.
spowolniłaviar
2
-1 za brak wzmianki o kolejności rotacji, co jest bardzo ważne dla pytania
Maik Semder
7

Rozwiązanie jest w wikipedii: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

używając tego:

sx = sin(x/2); sy = sin(y/2); sz = sin(z/2);
cx = cos(x/2); cy = cos(y/2); cz = cos(z/2);

q( cx*cy*cz + sx*sy*sz,
   sx*cy*cz - cx*sy*sz,
   cx*sy*cz + sx*cy*sz,
   cx*cy*sz - sx*sy*cz ) // for XYZ application order

q( cx*cy*cz - sx*sy*sz,
   sx*cy*cz + cx*sy*sz,
   cx*sy*cz - sx*cy*sz,
   cx*cy*sz + sx*sy*cz ) // for ZYX application order

Konstruktory dla czwartorzędu, biorąc pod uwagę Euler (gdzie zastosowanie obrotu to XYZ lub ZYX). Są to jednak tylko dwie z sześciu możliwych kombinacji kątów Eulera. Naprawdę musisz dowiedzieć się, w jakiej kolejności konstruowane są kąty Eulera podczas konwersji na macierz transformacji. Tylko wtedy można zdefiniować rozwiązanie.

W starej firmie, w której pracowałem, mieliśmy Z jako naprzód (jak większość kart graficznych), więc kolejność aplikacji była ZYX, aw mojej obecnej firmie oś Y jest do przodu, a Z jest w górze, więc nasza kolejność aplikacji to YZX. Ta kolejność to kolejność, w której mnożą się twoje czwartorzędy, aby wygenerować ostateczną transformację, a kolejność ma znaczenie dla rotacji, ponieważ mnożenia nie są przemienne.

Richard Fabian
źródło
1
+1, cześć i dzięki za świetną odpowiedź. Gdy korzystam z OpenGL , wartość Z znika z ekranu. W mojej aplikacji wykonuję kolejność mnożenia ZYX . Początkowo myślałem, że GLM ma tę funkcjonalność dostępną, ale widzę, że jeszcze jej nie zaimplementowali, więc jedną alternatywą jest ręczne utworzenie konwersji , jak to zalecasz.
Bunkai.Satori
To najlepsza odpowiedź tutaj.
plasmacel
1
vec3 myEuler (fAngle[0],fAngle[1],fAngle[2]);
glm::quat myQuat (myEuler);

fAngle musi być w radianach!

Carlos
źródło
2
Czy to był żart? A może po prostu nie przeczytałeś innych odpowiedzi (zwłaszcza Daniela)?
Chris mówi Przywróć Monikę