Bagaimana saya harus menerapkan kamera orang pertama?

12

Saya seorang programmer pemula dan saya sedang membuat proyek yang memungkinkan saya berjalan di sekitar ruangan melalui kamera orang pertama. Sejauh ini, saya punya bangunan yang digambar dan terus, tapi sekarang saya macet dan tidak tahu bagaimana membuat kamera orang pertama untuk memungkinkan saya berjalan-jalan.

Adakah yang bisa mengarahkan saya ke kelas kamera yang bisa saya gunakan, atau kode yang berguna?

DK10
sumber

Jawaban:

7

Berikut adalah beberapa tips tentang rotasi kamera (mouselook). Setelah secara naif menerapkan kelas kamera dari awal, saya menemukan saya harus melakukan beberapa penyesuaian tambahan untuk perilaku rotasi yang baik:

  1. Atur ulang koordinat mouse ke tengah layar pada setiap frame, sehingga mouse tidak pernah terjebak pada batas layar

  2. Pertahankan vektor "atas" kamera (disallow roll) dan hitung ulang vektor "ke samping"

  3. Larang melihat ke atas melewati sumbu vertikal + y, atau turun melewati sumbu -y (terlalu jauh ke atas / ke bawah)

  4. Dapatkan urutan rotasi dengan benar (atas / bawah terlebih dahulu, lalu kiri / kanan)

  5. Renormalkan kembali vektor "atas", "bidik", dan "ke samping" setiap bingkai

Semoga Anda dapat menggunakan beberapa kode ini untuk keuntungan Anda:

    const int mouseDeltaX = mouseAxisX * (input.GetMouseX() - int(app.GetWidth()/2));
    const int mouseDeltaY = -mouseAxisY * (input.GetMouseY() - int(app.GetHeight()/2));  // mouse y-offsets are upside-down!

    // HACK:  reset the cursor pos.:
    app.SetCursorPosition(app.GetWidth()/2, app.GetHeight()/2);

    float lookRightRads = mouseDeltaX * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;
    float lookUpRads    = mouseDeltaY * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;

    // Limit the aim vector in such a way that the 'up' vector never drops below the horizon:
    static const float zenithMinDeclination = DEG_TO_RAD * MIN_UPWARDS_TILT_DEG;
    static const float zenithMaxDeclination = DEG_TO_RAD * (180.0f - MIN_UPWARDS_TILT_DEG);

    const float currentDeclination = std::acosf(camera.aim_.y_);  ///< declination from vertical y-axis
    const float requestedDeclination = currentDeclination - lookUpRads;

    // Clamp the up/down rotation to at most the min/max zenith:
    if(requestedDeclination < zenithMinDeclination)
        lookUpRads = currentDeclination - zenithMinDeclination;
    else if(requestedDeclination > zenithMaxDeclination)
        lookUpRads = currentDeclination - zenithMaxDeclination;

    // Rotate both the "aim" vector and the "up" vector ccw by 
    // lookUpRads radians within their common plane -- which should 
    // also contain the y-axis:  (i.e. no diagonal tilt allowed!)
    camera.aim_.rotateAboutAxis(camera.right_, lookUpRads);
    camera.up_.rotateAboutAxis(camera.right_, lookUpRads);
    ASSERT_ORTHONORMAL(camera.aim_, camera.up_, camera.right_);

    // Rotate both the "aim" and the "up" vector ccw about the vertical y-axis:
    // (again, this keeps the y-axis in their common plane, and disallows diagonal tilt)
    camera.aim_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.up_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.updateRightAxis();

Perhatikan bahwa:

mouseAxisX dan mouseAxisY didefinisikan sebagai +/- 1, tergantung pada apakah Anda ingin sumbu x atau y harus dibalik. Biasanya game menawarkan opsi ini setidaknya untuk sumbu vertikal.

MIN_UPWARDS_TILT_DEG didefinisikan sebagai 1,0 derajat (sehingga pemirsa diperbolehkan untuk melihat dari -89 derajat ke bawah hingga +89 derajat ke atas, yang terlihat cukup meyakinkan seperti rentang vertikal 180 derajat penuh - hilangnya 2 derajat pada bagian ekstrem dapat diabaikan) .

camera.aim_, camera.right_, dan camera.up_ tentu saja adalah vektor 3D, dan metode rotateAboutAxis () yang dapat Anda gunakan bersama-sama dari wikipedia dan sejumlah sumber daring. Y_AXIS adalah vektor tetap konstan (0,1,0).

ASSERT_ORTHONORMAL () adalah pemeriksaan kewarasan mode debug saja, yang tidak pernah dikompilasi dalam mode dioptimalkan / rilis.

Mohon maaf sebelumnya untuk kode C-style ... sekali lagi, di sini Anda menerima saran dari seorang pria bernama Mediocritus! ; ^)

Mediokritus
sumber
Apa yang sedang Anda bicarakan? Kode C-style adalah landasan semangat hacker! 8-)
blissfreak
5

Ada beberapa cara untuk melakukan ini (lihat tutorial di sini , di sini dan di sini misalnya, dengan lebih banyak tersedia di Internet melalui Google). Teknologi yang digunakan dalam sumber daya yang Anda temukan online mungkin sedikit berbeda (dalam hal D3D, XNA, OpenGL, dan lain-lain), tetapi prinsip-prinsip yang mendasarinya akan sama:

  • objek kamera Anda mempertahankan posisinya dan arahnya, dan secara opsional sepasang vektor lain yang, di samping arahnya, membentuk basis ortogonal untuk sistem koordinat kamera.
  • API publik kamera Anda memaparkan metode untuk menguap, melempar, dan secara opsional memutar kamera di sekitar vektor basisnya - tindakan menyesuaikan orientasi kamera akan memperbarui vektor basis untuk penggunaan selanjutnya.

Anda dapat memilih untuk menyimpan vektor secara langsung, atau menghitung ulang matriks tampilan yang mendasarinya setiap saat, sesuai kebutuhan dan keinginan Anda. Ada banyak fleksibilitas dalam teknik ini, jadi jika Anda memerlukan bantuan di luar langkah-langkah umum tersebut, Anda mungkin ingin memposting pertanyaan baru dengan permintaan yang lebih spesifik.


sumber
2

Untuk referensi khusus untuk implementasi sistem kamera menggunakan Direct3D, saya merekomendasikan artikel ini: http://www.toymaker.info/Games/html/camera.html . Penulis juga menjelaskan metode dan fitur lain yang dapat digunakan untuk memperluas implementasi.

Thomas Anthony
sumber