Bagaimana cara menjaga kamera FPS Quaternion saya dari memiringkan dan mengacaukan?

17

Saya menggunakan kamera seperti FPS, dan menggunakan angka empat. Tapi, setiap kali saya mencoba melihat ke atas dan ke samping, itu miring, dan kadang-kadang bisa terbalik. Bagaimana saya bisa memperbaikinya?

Aeodyn
sumber
3
(Will Self-answer dalam 7 jam) ...
Aeodyn

Jawaban:

16

Anda bisa menguraikan angka empat Anda menjadi seperangkat yaw / pitch / roll, tetapi itu biasanya berlebihan.

Alih-alih menyusun angka empat Anda seperti ini:

cameraOrientation = cameraOrientation * framePitch * frameYaw;

Coba ini:

cameraOrientation = framePitch * cameraOrientation * frameYaw;

Maka tidak akan pernah menghasilkan tilt / roll dan setara dengan menyimpan yaw dan pitch secara terpisah

ltjax
sumber
3
Ini. Ini persis apa yang saya cari. Memecahkan masalah saya dalam satu garis. Bagus!
aardvarkk
1
Apakah framePitchdan frameYaw floattipe? Juga, saya akan berterima kasih atas beberapa klarifikasi pada kalimat pertama Anda.
sirdank
1
@sirdank cameraOrientation,, framePitchdan frameYawsemuanya angka empat (masing-masing angka empat adalah mengapung atau ganda).
Dan
8

Ini adalah masalah yang saya miliki untuk sementara waktu, dan saya tidak dapat menemukan jawaban, jadi saya pikir saya akan mempostingnya di sini.

Ini sebenarnya cukup sederhana. Cara Anda paling mungkin melakukan rotasi adalah seperti ini:

currentDirection * newRotation;

Tetapi, melakukannya seperti ini juga tidak berhasil.

newRotation * currentDirection;

Yang harus Anda lakukan adalah melakukannya dengan urutan pertama untuk rotasi ke atas dan ke bawah, dan urutan kedua untuk rotasi ke samping.

Bagi saya, itu seperti ini:

        if (keyboard.IsKeyDown(Keys.Up))
            Direction = Direction * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Down))
            Direction = Direction * Quaternion.CreateFromAxisAngle(new Vector3(-1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Left))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), TurnSpeed) * Direction;
        if (keyboard.IsKeyDown(Keys.Right))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, -1), TurnSpeed) * Direction;

Untuk alasan mengapa, cara pertama memiliki rotasi relatif terhadap arah sideways saat ini, yang Anda inginkan untuk naik dan turun, tetapi Anda tidak ingin itu untuk rotasi sideways, itulah sebabnya urutan kedua diperlukan.

Aeodyn
sumber
Saya harus menunggu 7 jam untuk menjawab pertanyaan saya sendiri ...
Aeodyn
maaf, bisakah Anda menjelaskan ini dengan beberapa tangkapan layar? "urutan pertama" dan "urutan kedua" agak membingungkan - terima kasih!
Atav32
Ketika bekerja dengan Quaternions, ketertiban memang penting, seperti halnya selalu dengan rotasi 3D. Dalam contoh saya, "Direction * = newRotation" sama dengan "Direction = Direction * newRotation". Tapi, dengan rotasi kiri dan kanan, kami ingin sebaliknya. Ini membuatnya tidak tergantung pada kemiringan atas dan ke bawah, yang menyebabkan gulungan.
Aeodyn
Oh saya pikir titik quarternions adalah bahwa itu menghindari kunci gimbal dan rotasi semua independen, tetapi saya mungkin salah membaca buku teks. Jadi hanya untuk memperjelas, apakah Anda mengatakan bahwa jika Anda membalik urutan transformasi rotasi, Anda dapat mencegah kamera dari memiringkan? Atau apakah secara manual mengatur transformasi roll and pitch ke 0 ketika Anda memutar yaw?
Atav32
5

Untuk kamera FPS Anda biasanya tidak ingin roll dan terbatas pada +/- 90 derajat pitch, jadi saya hanya melacak keadaan saat ini menggunakan sudut yaw dan pitch. Kekuatan penuh angka empat tidak terlalu membantu untuk ini.

Anda masih dapat mengonversi sudut yaw / pitch ke dan dari angka empat jika Anda ingin beralih antara kamera FPS dan kamera animasi menggunakan interpolasi keyframe angka empat, atau sesuatu seperti itu.

Nathan Reed
sumber
0

Trik sederhana lainnya adalah menempatkan kamera dalam GameObject, dan memiliki rotasi Yaw untuk mengontrol objek game, sementara kamera anak dikonfigurasikan dengan koordinat Pitch:

playerCameraHolder.transform.Rotate(0, rotationYaw, 0);
playerCamera.transform.Rotate(rotationPitch, 0, 0);
Victor S
sumber