Menggunakan Quaternions: Apa yang bisa saya lakukan dengan mereka? (tanpa matematika)

24

Saya seorang Pengembang Game dan tidak belajar Matematika. Jadi saya hanya ingin menggunakan Quaternions sebagai alat. Dan untuk dapat bekerja dengan rotasi 3D, perlu menggunakan Quaternions (Atau Matriks, tapi mari kita tetap di Quaternions di sini di Pertanyaan ini). Saya pikir penting bagi banyak pengembang untuk menggunakannya. Itu sebabnya saya ingin berbagi pengetahuan dan mudah-mudahan mengisi lubang yang saya miliki. Sekarang....

Sejauh yang saya mengerti:

Quaternion dapat menggambarkan 2 hal:

  1. Orientasi objek 3d saat ini.
  2. Transformasi rotasi Obyek bisa dilakukan. (perubahan rotasi)

Anda dapat melakukannya dengan Quaternion:

Perkalian:

  1. Quaternion endOrientation = Rotasi Quaternion Ubah * Quaternion currentOrientation;

    Jadi misalnya: Objek 3D saya diputar 90 ° ke kiri - dan rotasi saya, saya kalikan adalah rotasi 180 ° ke kanan, pada akhirnya Obyek 3D 90 ° saya diputar ke kanan.

  2. Rotasi QuaternionChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    Dengan ini, Anda mendapatkan perubahan rotasi, yang dapat diterapkan ke Orientasi lain.

  3. Vector3 endPostion = Rotasi kuarter mengubah * Vector3 currentPosition;

    Jadi misalnya: Objek 3D saya ada di Posisi (0,0,0) dan rotasi saya, saya kalikan adalah rotasi 180 ° ke kanan, endosisi saya kira-kira seperti (0, -50,0). Di dalam Quaternion ada Axis - dan rotasi di sekitar sumbu itu. Anda mengubah titik Anda di sekitar sumbu Y Derajat itu.

  4. Vector3 rotatedOffsetVector = Rotasi QuaternionChange * Vector3 currentOffsetVector;

    Sebagai contoh: Arah awal saya menunjukkan UP - (0,1,0), dan rotasi saya I adalah rotasi 180 ° ke kanan, arah akhir saya ditampilkan ke bawah. (0, -1,0)

Blending (Lerp dan Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)

    jika interpolator adalah 1: currentOrientation = endOrientation

    jika interpolatornya adalah 0: currentOrientation = startOrientation

    Slerp interpolasi lebih tepat, Lerp interpolasi lebih banyak performan.

Pertanyaan saya):

Apakah semua yang saya jelaskan sampai sekarang benar?

Apakah itu "semua" yang dapat Anda lakukan dengan Quaternions? (obv. not)

Apa lagi yang bisa Anda lakukan dengan mereka?

Apa gunanya produk Dot dan produk Cross antara 2 Quaternions?

Edit:

Pertanyaan yang Diperbarui dengan beberapa jawaban

OC_RaizW
sumber
Katakanlah Anda belum 2, tetapi norientasi yang berbeda (sikap, pose, dll). Kemudian Anda dapat rata-rata menggunakan bobot, secara efektif menggeneralisasi slerp / lerp. Anda juga dapat mengubah angka empat menjadi rotor, yang setara dengan menerapkan kecepatan sudut untuk jumlah waktu tertentu ke benda tegar. Karenanya Anda dapat menggambarkan integrasi kecepatan sudut dengan angka empat juga. Anda juga dapat memperkirakan seberapa berbeda dua orientasi itu (menghitung panjang busur yang direntang oleh dua angka empat pada hypersphere).
teodron
Dan ya, pada pandangan pertama, alasan Anda benar (pemahaman Anda tentang angka empat cukup baik untuk orang non-teknis). Ini tidak pantas untuk komentar, tetapi selamat! Bahkan orang-orang yang berbakat secara teknis tahu semua penggunaan angka empat, meskipun mereka menggunakannya hanya sebagai alat rekayasa perangkat lunak untuk suatu tujuan.
teodron
4
"Dan untuk dapat bekerja dengan rotasi 3D, perlu menggunakan Quaternions" Aku tidak bisa cukup menekankan betapa salahnya kalimat ini. Anda dapat menggunakan sudut Euler atau Tait-Bryan untuk pengembangan game, satu-satunya masalah adalah kunci gimbal. Jika Anda ingin menjadi pengembang game, Anda perlu matematika pada satu titik, pelajari itu.
Bálint
1
"pengembang game" dan "tidak belajar matematika" adalah sebuah oxymoron.
Margaret Bloom
2
Saya menghargai apa yang Anda coba lakukan dengan pertanyaan, tetapi jawabannya harus dalam jawaban, bukan pertanyaan. Buat jawaban "ringkasan" jika menurut Anda layak untuk menyusunnya.
Dasar

Jawaban:

23

Perkalian

Paling tidak dalam hal implementasi Quaternions dari Unity, urutan multiplikasi yang dijelaskan dalam pertanyaan itu tidak benar. Ini penting karena rotasi 3D tidak komutatif .

Jadi, jika saya ingin memutar objek dengan rotationChangememulainya, currentOrientationsaya akan menulisnya seperti ini:

Quaternion newOrientation = rotationChange * currentOrientation;

(mis. Transformasi menumpuk ke kiri - sama dengan konvensi matriks Unity. Rotasi paling kanan diterapkan pertama / pada ujung "paling lokal")

Dan jika saya ingin mengubah arah atau mengimbangi vektor dengan rotasi, saya akan menulis seperti ini:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity akan menghasilkan kesalahan kompilasi jika Anda melakukan yang sebaliknya)

Memadukan

Untuk sebagian besar kasus, Anda dapat menggunakan rotasi Lerping. Itu karena sudut yang digunakan "di bawah tenda" dalam angka empat adalah setengah sudut rotasi, membuatnya jauh lebih dekat dengan perkiraan linier Lerp daripada sesuatu seperti Matriks (yang secara umum tidak akan Lerp dengan baik!). Lihat sekitar 40 menit dalam video ini untuk penjelasan lebih lanjut .

Satu-satunya kasus ketika Anda benar-benar membutuhkan Slerp adalah ketika Anda membutuhkan kecepatan yang konsisten dari waktu ke waktu, seperti menginterpolasi antar kerangka kunci pada timeline animasi. Untuk kasus-kasus di mana Anda hanya peduli bahwa output adalah perantara antara dua input (seperti memadukan lapisan animasi) maka biasanya Lerp berfungsi dengan cukup baik.

Apa lagi?

Produk titik dari dua unit angka empat memberikan cosinus sudut di antara mereka, sehingga Anda dapat menggunakan produk titik sebagai ukuran kesamaan jika Anda perlu membandingkan rotasi. Ini sedikit tidak jelas, jadi untuk kode yang lebih mudah dibaca, saya sering menggunakan Quaternion.Angle (a, b) sebagai gantinya, yang lebih jelas menyatakan bahwa kami membandingkan sudut, dalam satuan yang dikenal (derajat).

Jenis metode kenyamanan yang disediakan Unity untuk Quaternions sangat berguna. Di hampir setiap proyek saya menggunakan yang ini setidaknya beberapa kali :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

Ini membangun angka empat yang:

  • memutar sumbu z + lokal untuk menunjuk tepat di sepanjang forwardargumen vektor
  • memutar sumbu y + lokal ke titik sedekat mungkin dengan upargumen vektor, jika disediakan, atau ke (0, 1, 0)jika dihilangkan

Alasan "naik" hanya "sedekat mungkin" adalah karena sistemnya terlalu ditentukan. Menghadapi z + untuk forwardmenggunakan dua derajat kebebasan (mis. Yaw dan pitch) sehingga kita hanya memiliki satu derajat kebebasan tersisa (roll).

Saya menemukan cukup sering saya menginginkan sesuatu dengan sifat ketepatan yang berlawanan: Saya ingin y + lokal untuk menunjukkan tepat bersama up, dan z + lokal untuk sedekat mungkin forwarddengan kebebasan yang tersisa.

Ini muncul misalnya ketika mencoba untuk membentuk kerangka koordinat relatif kamera untuk input gerakan: Saya ingin arah naik lokal saya tetap tegak lurus dengan lantai atau permukaan yang cenderung normal, jadi input saya tidak mencoba untuk memasukkan karakter ke medan. atau mengangkat mereka dari itu.

Anda juga bisa mendapatkan ini jika Anda ingin rumah menara dari sebuah tank untuk menghadapi target, tanpa terkelupas dari tubuh tangki ketika membidik atas / bawah.

Kita dapat membangun fungsi kenyamanan kita sendiri untuk melakukan ini, menggunakan LookRotationuntuk mengangkat berat:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

Di sini kita pertama-tama memutar lokal y + ke z +, dan lokal z + ke y-.

Kemudian kami memutar z + baru ke arah atas kami (jadi hasil bersihnya adalah titik lokal y + langsung di sepanjang exactUp), dan y + baru sedekat mungkin dengan arah maju yang dinegasikan (jadi hasil bersihnya adalah titik z + lokal sedekat mungkin sepanjang approximateForward)

Metode kenyamanan praktis lainnya adalah Quaternion.RotateTowards, yang sering saya gunakan seperti ini:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

Ini memungkinkan kita mendekat pada targetRotationkecepatan yang konsisten dan terkendali terlepas dari framerate - penting untuk rotasi yang mempengaruhi hasil / keadilan mekanisme permainan (seperti memutar gerakan karakter, atau memiliki track-in turret pada pemain). Lerping / Slerping secara naif dalam situasi ini dapat dengan mudah menyebabkan kasus di mana gerakan menjadi lebih cepat pada framerate tinggi, yang berdampak pada keseimbangan game. (Itu tidak berarti metode ini salah - ada cara untuk menggunakannya dengan benar tanpa mengubah keadilan, itu hanya membutuhkan perawatan. RotateTowardsMemberikan jalan pintas yang nyaman yang menangani ini untuk kita)

DMGregory
sumber
Kiat: Tambahkan & t = 40m ke akhir URL video sehingga URL akan langsung ada (opsional misalnya 40m5s). Produk-produk dot Quaternion sangat berguna ketika berhadapan dengan gameworlds bola juga - atau lebih luas ketika mengorientasikan bongkahan bola berputar.
Luke Briggs
@Luke Briggs: Titik dunia permainan berbentuk bola sepertinya layak dijabarkan dalam jawabannya sendiri (terutama dengan diagram) jika Anda mau. :)
DMGregory
Ide bagus - jam 3 pagi di sini (jadi saya pikir itu akan keluar omong kosong sedikit!) Tapi saya akan senang untuk mengumpulkan sesuatu besok (Jika saya ingat!)
Luke Briggs
1
Sunting: Saya sedikit terbawa memikirkan jawaban sehingga tantangan diterima! Setidaknya saya akan menandainya sebagai potongan kasar sehingga orang-orang dapat mengetahui luka bakar larut malam yang masuk ke dalamnya: P
Luke Briggs
Itu dia! Saya mencoba untuk membahasnya dalam arti gambaran grafis dengan dasar bahwa jawaban Anda sudah mencakup fungsi-fungsi yang mendasarinya dengan sangat baik. Waktu untuk tidur, kurasa!
Luke Briggs
14

Di mana produk titik digunakan?

Di Unity, salah satu pengguna paling umum dari produk titik adalah setiap kali Anda memeriksa apakah angka empat sama dengan ==atau !=. Unity menghitung titik produk untuk memeriksa kesamaan daripada secara langsung membandingkan nilai x, y, z, w internal. Sebaiknya ingat yang satu ini karena membuat panggilan lebih mahal dari yang Anda perkirakan.

Kami juga menggunakannya dalam use case yang menarik juga ..

Bersenang-senang dengan produk titik empat angka - Dunia bola dan orbital

Simulasi seluruh planet dan bahkan seluruh tata surya menjadi semakin umum. Untuk melakukan ini secara realtime, kita memerlukan produk dot angka empat juga. Banyak dari mereka. Produk quaternion dot sangat kurang digunakan tetapi pasti memiliki kegunaannya - Mari kita lihat!

Pertama, kami memiliki serangkaian rotasi untuk dipertimbangkan:

  1. (Opsional) Bintang di sekitar pusat galaksi
  2. Planet di sekitar bintang
  3. Kemiringan planet ini
  4. Perputaran planet ini
  5. Posisi sel-sel jaringan di dekatnya (diputar tentang inti planet) *
  6. Beberapa pesawat orbital

Kombinasikan semuanya dan Anda berakhir dengan banyak kerumitan (dan banyak sekali!). Ketika pemirsa berdiri di permukaan planet ini, kami tidak ingin mereka meluncur dengan kecepatan gila melalui ruang gameworld kami. Kami sebenarnya lebih suka mereka diam dan di suatu tempat dekat asal - pindahkan alam semesta di sekitar pemain sebagai gantinya.

Rotasi planet

Yang penting, agar kita bisa mendapatkan putaran dan kemiringan planet yang benar dalam skenario ini, kita perlu mengunci poros tiang sehingga hanya bisa mengayun ke atas / ke bawah pada gambar di atas (yaitu mengayunkan "ke atas" saat pemain bergerak utara). Di situlah produk dot angka empat masuk. Jika kami tidak menggunakan produk dot di sini dan sebagai gantinya hanya mengalikan kemiringan juga, ini akan terjadi:

'Planet' yang dimiringkan dengan salah

Perhatikan bagaimana kutub 'planet' kita yang mengorbit selalu miring ke arah bintang. Ini bukan yang terjadi dalam kenyataan - kemiringannya berada pada arah yang tetap .

Tanpa membahas topik yang terlalu jauh, berikut ringkasan singkatnya:

  • Pada bola, suatu orientasi juga dengan rapi menggambarkan posisi permukaan.
  • Kami punya banyak rotasi untuk digabungkan bersama.
  • Jelaskan semuanya sebagai rotasi; posisi pemirsa juga. Ini membantu meningkatkan kinerja karena pada akhirnya kami melakukan lebih sedikit operasi.
  • Sudut antara rotasi (produk titik kami) kemudian membantu mengukur garis bujur dan bekerja sangat baik dalam menangani kemiringan.

Dengan hanya memperoleh sudut, kita menjatuhkan beberapa rotasi yang tidak diinginkan . Pada saat yang sama kami juga berakhir dengan pengukuran bujur yang berguna untuk navigasi serta iklim lokal.

* Planet dibangun dari banyak sel jaringan . Hanya yang terdekat yang benar-benar ditampilkan.

Luke Briggs
sumber
2
Ini melakukan pekerjaan yang hebat dalam mengatur adegan dan memotivasi masalah, tapi saya masih agak bingung tentang bagaimana matematika dari produk dot angka empat (yaitu produk skalar dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wsebagai lawan dari komposisi angka empat yang akan kita gunakan untuk rantai bersama-sama rotasi) akan membantu kami menyelesaikan masalah ini. Saya dengan senang hati akan mendukung jika Anda dapat menguraikan hal ini sedikit kemudian (saya tidak bermaksud menjauhkan Anda dari slerp Anda ... maksud saya tidur!)
DMGregory
@ DmGregory jawaban singkatnya adalah tilt adalah yang aneh; semuanya menyusun dengan baik kecuali yang itu (planet ini akan tampak bergoyang-goyang di sekitar bintangnya). Saya akan (semoga!) Menambahkan beberapa konteks lagi besok!
Luke Briggs
@DMGregory Saya telah menambahkan beberapa informasi tambahan (saya tidak bisa tidur!) - mudah-mudahan itu membuatnya lebih jelas.
Luke Briggs
1
Maaf jika saya menjadi agak padat, tetapi setelah membaca kembali beberapa kali saya masih tidak tahu bagaimana saya akan menggunakan produk titik dalam formula untuk mencapai transformasi yang Anda gambarkan. Apakah Anda dapat menambahkan pseudocode kecil meletakkan operasi yang Anda lakukan secara eksplisit?
DMGregory
@ DMGregory Saya tidak terbiasa dengan angka empat tetapi jika ini adalah rotasi pada bola, maka ini bukan komposisi rotasi. Ini menggunakan geometri bola dengan vektor untuk menghitung vektor normal untuk "garis" pada permukaan bola AKA setiap keliling. Sekali lagi, jawabannya tidak masuk akal juga tidak pertanyaan ini, tapi saya percaya mereka menggunakan geometri bola.
The Great Duck