Saya memiliki realisasi sederhana dari mesin permainan entitas / komponen.
Transform komponen memiliki metode untuk mengatur posisi lokal, rotasi lokal, posisi global dan rotasi global.
Jika transformasi sedang mengatur posisi global baru, maka posisi lokal juga berubah, untuk memperbarui posisi lokal dalam kasus seperti itu, saya hanya menerapkan matriks transformasi lokal saat ini ke matriks transformasi dunia induk.
Sampai saat itu saya tidak punya masalah, saya bisa mendapatkan matriks transformasi lokal yang diperbarui.
Tetapi saya sedang berjuang bagaimana memperbarui posisi lokal dan nilai rotasi dalam transformasi. Satu-satunya solusi yang ada dalam pikiran saya adalah mengekstraksi nilai terjemahan & rotasi dari localMatrix of transform.
Untuk terjemahannya cukup mudah - saya hanya mengambil nilai kolom ke-4. tapi bagaimana dengan rotasi?
Bagaimana cara mengekstrak sudut euler dari matriks transformasi?
Apakah solusi seperti itu benar ?:
Untuk menemukan rotasi di sekitar sumbu Z, kita dapat menemukan perbedaan antara vektor sumbu X dari localTransform dan vektor sumbu X dari parent.localTransform dan menyimpan hasil di Delta, lalu: localRotation.z = atan2 (Delta.y, Delta .x);
Sama untuk rotasi di sekitar X & Y, hanya perlu menukar sumbu.
Ada proses penulisan bagus untuk proses ini oleh Mike Day: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
Itu juga sekarang diimplementasikan di glm, pada versi 0.9.7.0, 02/08/2015. Lihat implementasinya .
Untuk memahami matematika, Anda harus melihat nilai-nilai yang ada dalam matriks rotasi Anda. Selain itu, Anda harus mengetahui urutan rotasi diterapkan untuk membuat matriks Anda agar dapat mengekstrak nilai dengan benar.
Matriks rotasi dari sudut Euler dibentuk dengan menggabungkan rotasi di sekitar sumbu x, y, dan z. Misalnya, memutar θ derajat di sekitar Z dapat dilakukan dengan matriks
Matriks serupa ada untuk memutar sumbu X dan Y:
Kita dapat mengalikan matriks-matriks ini bersama-sama untuk membuat satu matriks yang merupakan hasil dari ketiga rotasi. Penting untuk dicatat bahwa urutan matriks ini dikalikan bersama adalah penting, karena perkalian matriks tidak komutatif . Ini artinya
Rx*Ry*Rz ≠ Rz*Ry*Rx
. Mari kita pertimbangkan satu kemungkinan urutan rotasi, zyx. Ketika tiga matriks digabungkan, ini menghasilkan matriks yang terlihat seperti ini:dimana
Cx
cosinus darix
sudut rotasi,Sx
adalah sinus darix
sudut rotasi, dll.Sekarang, tantangannya adalah untuk mengekstrak asli
x
,y
danz
nilai-nilai yang masuk ke matriks.Pertama mari kita
x
keluar sudut. Jika kita tahusin(x)
dancos(x)
, kita bisa menggunakan fungsi tangen terbalikatan2
untuk mengembalikan sudut kita. Sayangnya, nilai-nilai itu tidak muncul sendiri dalam matriks kami. Tapi, jika kita melihat lebih dekat pada unsur-unsurM[1][2]
danM[2][2]
, kita dapat melihat kita tahu-sin(x)*cos(y)
sertacos(x)*cos(y)
. Karena fungsi tangen adalah rasio sisi yang berlawanan dan berdekatan dari sebuah segitiga, penskalaan kedua nilai dengan jumlah yang sama (dalam hal inicos(y)
) akan menghasilkan hasil yang sama. Jadi,Sekarang mari kita coba
y
. Kami tahusin(y)
dariM[0][2]
. Jika kita memiliki cos (y), kita bisa menggunakanatan2
lagi, tetapi kita tidak memiliki nilai itu dalam matriks kita. Namun, karena identitas Pythagoras , kita tahu bahwa:Jadi, kita dapat menghitung
y
:Terakhir, kita perlu menghitung
z
. Di sinilah pendekatan Mike Day berbeda dari jawaban sebelumnya. Karena pada titik ini kita mengetahui jumlahx
dany
rotasi, kita dapat membangun matriks rotasi XY, dan menemukan jumlahz
rotasi yang diperlukan untuk mencocokkan matriks target. TheRxRy
matriks terlihat seperti ini:Karena kita tahu bahwa
RxRy
*Rz
sama dengan matriks inputM
kita, kita dapat menggunakan matriks ini untuk kembali keRz
:The inverse dari matriks rotasi transposnya , sehingga kita dapat memperluas ini untuk:
Kita sekarang dapat memecahkan untuk
sinZ
dancosZ
dengan melakukan perkalian matriks. Kami hanya perlu menghitung elemen[1][0]
dan[1][1]
.Berikut ini adalah implementasi lengkap untuk referensi:
sumber
M[1][3]
denganM[1][2]
, danM[2][3]
denganM[2][2]
.