Cermin rotasi miring


9

Saya memutar karakter permainan saya untuk menonton di target menggunakan kode berikut:

        transform.rotation = Quaternion.Slerp(startQuaternion, lookQuaternion, turningNormalizer*turningSpeed/10f)

startQuaternion adalah rotasi karakter saat ini ketika target baru diberikan.

lookQuaternion adalah arah karakter yang harus dilihat dan diatur seperti ini:

    destinationVector = currentWaypoint.transform.position - transform.position;
    lookQuaternion = Quaternion.LookRotation(destinationVector, Vector3.up);

turningNormalizer baru saja Time.deltaTimebertambah dan turningSpeedmerupakan nilai statis yang diberikan dalam editor.

Masalahnya adalah bahwa sementara karakter berubah sebagaimana mestinya sebagian besar waktu, ia memiliki masalah ketika harus melakukan hampir 180 derajat. Maka kadang-kadang kegugupan dan mencerminkan rotasi:

masukkan deskripsi gambar di sini

Dalam gambar yang digambar dengan buruk ini, karakter (di kanan) mulai berbelok ke arah lingkaran di sebelah kiri. Alih-alih hanya memutar baik melalui kiri atau kanan itu memulai "tarian cermin" ini:

  1. Itu mulai berputar ke arah menghadap baru
  2. Kemudian tiba-tiba terkunci ke sudut yang sama tetapi di sisi lain dan terus berputar

Itu melakukan "mirroring" begitu lama sampai terlihat pada target. Apakah ini hal dengan angka empat, slerping / lerping atau sesuatu yang lain?

EDIT1: Rupanya masalah tidak muncul dari rotasi itu sendiri. Masalah yang lebih mungkin adalah bahwa karakter bergerak ke arah menghadap sementara itu berputar. Seperti membatasi sudut, antara menghadap dan target, ketika karakter dibiarkan bergerak mengurangi dan kadang-kadang menghilangkan rotasi jittering / mirroring.

Ini tentu saja menimbulkan lebih banyak pertanyaan, mengapa karakter tidak dapat bergerak dan berputar pada saat yang sama tanpa masalah? Kode yang digunakan untuk perpindahan:

transform.Translate(Vector3.forward * runningSpeed/10f * Time.deltaTime);

Apakah 'lookQuaternion' diperbarui setiap frame? Jika demikian, maka anggapan saya adalah bahwa beberapa ketidakakuratan kecil mengarah ke semacam kegelisahan di mana pemain 'melampaui' rotasi-tampilan dan jadi arah baru untuk melihat hanya di sisi lain 'tepat di belakang' ... .
Steven Stadnicki

Jawaban:


5

Setiap orientasi dalam ruang 3D dapat diwakili oleh 2 angka kuat unit yang berbeda, qdan -q(komponen dinegasikan q). Misalnya orientasi yang diwakili oleh matriks identitas 3x3 Idapat diwakili oleh 2 angka empat:

 q:  { 0,  0,  0},  1
-q:  {-0, -0, -0}, -1

Keduanya mewakili orientasi yang sama dalam ruang 3D, produk titik mereka persis -1, masing-masing terletak di belahan bumi lain, persis di sisi berlawanan dari hypersphere.

Hasil yang Anda amati ketika slerp membutuhkan busur yang lebih panjang untuk berputar, adalah ketika slerping antara 2 angka empat yang tidak terletak di belahan bumi yang sama. Jika itu terjadi, cukup singkirkan salah satu dari mereka sebelum slerping mereka, maka slerp akan mengambil busur yang lebih pendek.

Produk titik adalah alat yang mudah untuk mengetahui apakah itu terjadi. Jika produk titik dari kedua angka empat kurang dari 0, maka mereka tidak terletak di belahan bumi yang sama. Jadi jika produk titik keduanya kurang dari 0, hanya komponen-bijaksana meniadakan angka empat lainnya sebelum slerping mereka.


Saya ingin tahu apakah saya memahami Anda dengan benar ketika saya mencobanya dengan ini, if(Quaternion.Dot (lookQuaternion, startQuaternion) < 0) { startQuaternion = Quaternion.Inverse(startQuaternion); }tetapi itu tidak memperbaiki masalah. Maaf untuk pemformatan yang buruk, sepertinya saya tidak bisa menjinakkan bagian komentar ini.
Esa

Hampir, tetapi tidak Inverse, itu operasi yang berbeda dari Negate. if(Quaternion.Dot (lookQuaternion, q) < 0) { q.x = -q.x; q.y = -q.y; q.z = -q.z; q.w = -q.w; }Saya tidak menggunakan C #, tetapi dari tampilan dokumen, sepertinya Anda juga bisa menggunakan Fungsi-Negasi secara langsung.
Maik Semder

if(Quaternion.Dot (lookQuaternion, startQuaternion) < 0) { startQuaternion = Quaternion.Negate(startQuaternion); }
Maik Semder

Saya khawatir ini tidak memperbaiki masalah. Saya telah memperbarui pertanyaan.
Esa

Ya itu mungkin campuran bug yang berbeda. Sederhanakan pengaturan pengujian Anda, uji satu per satu, bukan terjemahan dan rotasi pada saat yang sama. Pertama pastikan satu bekerja, lalu yang lain, dan kemudian keduanya bersama-sama. Fokus hanya pada rotasi pertama, gunakan beberapa nilai orientasi terkenal, seperti mulai dari 170 derajat, bergerak ke nol, lihat di mana ia salah dan posting di sini
Maik Semder

1

Nah masalah Anda adalah karena kedua vektor yang membentuk angka empat Anda membuat 180 derajat, jadi pertanyaan yang harus ditanyakan ketika interpolasi busur mana yang seharusnya diambil? busur atas atau yang lebih rendah ??

Inilah yang pada dasarnya menyebabkan mirroring, setiap kali Anda menginterpolasinya mengambil arah sebaliknya sambil tetap mempertahankan sudutnya.

Menurut tautan ini .

Ketika theta adalah 180 derajat hasilnya tidak terdefinisi karena tidak ada arah terpendek untuk memutar, saya tidak berpikir situasi ini ditangani dengan benar, akan lebih baik jika kita memilih beberapa sumbu sembarang yang normal untuk qa atau qb, saya akan hargai ide apa pun untuk cara terbaik melakukannya.

Yang perlu Anda lakukan adalah menginterpolasi angka awal Anda dengan angka empat menengah (untuk menentukan busur mana yang akan diambil) dan ketika tercapai gunakan angka empat menengah untuk melanjutkan ke angka empat target yang sebenarnya.


1

Masalah yang saya duga Anda lihat tidak ada hubungannya dengan kode Anda, tetapi lebih merupakan masalah mendasar dengan interpolasi di sepanjang permukaan bola (dalam hal ini, untuk viewDirection). Di antara (hampir) dua titik pada sebuah bola ada satu lingkaran besar - misalnya, secara sewenang-wenang memperbaiki titik 'awal' kami di kutub utara, lingkaran besar itu akan menjadi meridian tempat titik akhir berada. Interpolasi dari satu titik ke titik lainnya bergerak di sepanjang lingkaran besar ini.

Sekarang, untuk sebagian besar titik di bola, titik terdekat sesuai dengan lingkaran besar terdekat; misalnya, garis bujur yang dimiliki Los Angeles dan Phoenix cukup dekat satu sama lain. Tetapi ketika titik tujuan adalah antipode dari titik asli - kutub selatan ke kutub utara titik awal - tidak ada lagi lingkaran besar melalui keduanya, tetapi semua lingkaran besar melalui satu melewati yang lain. Yang lebih buruk, ini berarti bahwa titik-titik di dekat kutub selatan bukan 'titik terbanyak'; dua titik saling berdekatan dan keduanya di dekat kutub selatan dapat memiliki meridian yang sangat berbeda.

Saya menduga apa yang Anda lihat adalah manifestasi dari ketidakstabilan ini di meridian - atau dengan kata lain, busur interpolasi. Ketika target tampilan berada tepat di belakang karakter, maka hal-hal seperti ketidaktepatan urutan pertama dalam 'integrasi Euler' Anda dari posisi karakter, dan cara yang mengubah arah tampilan frame-to-frame, akan mengarah ke ini secara liar busur interpolasi berbeda dari satu frame ke yang berikutnya, dan ini kemungkinan akan menyebabkan 'sempoyongan' yang Anda lihat.

Sejauh apa yang harus dilakukan dengan itu, hal terbaik yang muncul dalam pikiran adalah untuk tidak menghitung ulang arah pandangan 'target' setiap frame; alih-alih, gunakan yang sama untuk rentang beberapa frame, lalu hitung yang baru dan gunakan untuk beberapa frame, dll. Jika perlu, Anda bahkan dapat menginterpolasi dari satu target ke target berikutnya selama rentang beberapa frame sehingga arah gerakan tidak berubah terlalu tiba-tiba.

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.