GLM: Euler Angles to Quaternion


12

Saya harap Anda tahu GL Matematika ( GLM ) karena saya punya masalah, saya tidak bisa memecahkan:

Saya memiliki satu set Euler Angles dan saya perlu melakukan interpolasi yang lancar di antara mereka. Cara terbaik adalah mengonversinya ke Quaternions dan menerapkan alrogirthm SLERP.

Masalah yang saya miliki adalah bagaimana menginisialisasi glm :: angka empat dengan Euler Angles, tolong?

Saya membaca Dokumentasi GLM berulang kali, tetapi saya tidak dapat menemukan yang sesuai Quaternion constructor signature, yang akan membutuhkan tiga Euler Angles. Yang paling dekat yang saya temukan adalah fungsi angleAxis () , mengambil nilai sudut dan sumbu untuk sudut itu. Catatan, tolong, apa yang saya cari si cara, cara mengurai RotX, RotY, RotZ.


Untuk informasi Anda, ini adalah tanda tangan fungsi metnioned angleAxis () di atas :

detail::tquat< valType > angleAxis (valType const &angle, valType const &x, valType const &y, valType const &z)

Jawaban:


13

Saya tidak terbiasa dengan GLM, tetapi dengan tidak adanya fungsi untuk secara langsung mengkonversi dari sudut Euler menjadi angka empat, Anda dapat menggunakan fungsi "rotasi di sekitar sumbu" (seperti "angleAxis") untuk itu sendiri.

Begini caranya (kodesemu):

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;

(Atau Anda mungkin perlu mengganti angka empat tersebut, tergantung pada urutan rotasi sudut euler Anda yang akan diterapkan)

Bergantian, dari melihat melalui dokumentasi GLM, tampaknya Anda mungkin dapat mengubah sudut euler -> matrix3 -> angka empat seperti ini:

toQuat( orient3( EulerAngles ) )

jawaban yang bagus karena kurang ambigu tentang urutan aplikasi.
Richard Fabian

@ Trevor: +1, Hai Trevor, terima kasih atas jawaban Anda yang baik. Ini sepertinya solusi paling praktis di sini. Saya dapat dengan mudah beralih di antara urutan multiplikasi rotasi. Mungkin, jumlah kombinasi adalah alasannya, mengapa konversi Euler Angle ke Quaterion tidak tersedia di GLM.
Bunkai.Satori

Meskipun semua jawaban itu baik dan berharga, menurut saya, ini adalah yang paling praktis. Saya ingin menandainya sebagai Jawaban yang Diterima .
Bunkai.Satori

@ Tevor: Di Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ ;, perkalian seperti apa yang Anda maksud? Saya terkejut, bahwa GLM, tidak kelebihan operator *untuk multiplikasi Quaternion, jadi mungkin, saya harus melakukan multiplikasi secara manual .
Bunkai.Satori

3
@ Bunkai konsep perkalian angka empat mirip dengan perkalian matriks, itu bukan titik atau produk silang. Jika Anda ingin memahami penggunaan angka empat, kemudian terbiasa dengan matriks dan memahami sudut sumbu, konsep dasar mereka sangat mirip dengan angka empat, matematika sedikit lebih maju, tetapi begitu Anda memahami sudut sumbu, maka angka empat tidak jauh lagi.
Maik Semder

16
glm::quat myquaternion = glm::quat(glm::vec3(angle.x, angle.y, angle.z));

Di mana angleadalah glm::vec3yang mengandung pitch, yaw, gulungan masing-masing.

PS. Jika ragu, buka saja tajuk dan lihat. Definisi ini dapat ditemukan di 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;    
}

Di mana quattypedef float untuk tquat.


Itu cukup ambigu, bagaimana urutan ini akan berlaku? Eulers memesan rotasi dan konstruktor angka empat di sini tampaknya tidak peduli tentang itu.
Richard Fabian

Definisi fungsinya sama persis dengan milik Anda; Saya mempostingnya di jawaban saya jika itu penting.
deceleratedcaviar

bukan urutan argumen, urutan penerapan rotasi. Jawaban saya berisi pemesanan XYZ, yang diambil dari artikel wikipedia, namun, kami menggunakan aplikasi pemesanan ZYX di perusahaan lama saya, dan YZX di perusahaan saya saat ini. sudut x masih merupakan nilai pertama dalam daftar vektor / argumen dalam semua kasus, tetapi transformasi yang dihasilkan sebenarnya tidak sama.
Richard Fabian

Saya memperbaiki jawaban saya untuk rotateQuat, sehingga Anda dapat melihat bagaimana Anda dapat dengan mudah mengubah urutan. Secara default ia menerima XYZ, tetapi Anda dapat dengan mudah mengubahnya.
deceleratedcaviar

2
-1 untuk tidak menyebutkan urutan rotasi, yang sangat penting untuk pertanyaan
Maik Semder

7

Solusi ada di wikipedia: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

menggunakan itu:

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

Konstruktor untuk angka empat, diberi Euler (di mana aplikasi rotasi adalah XYZ atau ZYX). Namun, itu hanya dua dari enam kemungkinan kombinasi sudut Euler. Anda benar-benar perlu mencari tahu apa urutan sudut Euler dibangun ketika mengkonversi ke matriks transformasi. Hanya dengan demikian solusinya dapat didefinisikan.

Di perusahaan lama saya bekerja, kami memiliki Z sebagai maju (seperti kebanyakan kartu grafis) sehingga pesanan aplikasi adalah ZYX, dan di perusahaan saya saat ini sumbu Y maju dan Z naik, jadi pesanan aplikasi kami adalah YZX. Urutan ini adalah urutan Anda mengalikan angka empat Anda bersama-sama untuk menghasilkan transformasi akhir Anda, dan urutan masalah untuk rotasi adalah perkalian tidak komutatif.


1
+1, hai dan terima kasih atas jawaban yang bagus. Saat saya menggunakan OpenGL , nilai Z keluar dari layar. Dalam aplikasi saya, saya melakukan urutan multiplikasi ZYX . Awalnya, saya pikir, bahwa GLM memiliki fungsi ini tersedia, tetapi saya melihat, mereka belum mengimplementasikannya, jadi salah satu alternatif adalah membuat konversi secara manual , seperti yang Anda rekomendasikan.
Bunkai.Satori

Ini jawaban terbaik di sini.
plasmacel

1
vec3 myEuler (fAngle[0],fAngle[1],fAngle[2]);
glm::quat myQuat (myEuler);

fAngle harus dalam radian!


2
Apakah ini lelucon? Atau apakah Anda tidak membaca jawaban yang lain (terutama jawaban Daniel)?
Chris berkata Reinstate Monica
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.