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:
Atur ulang koordinat mouse ke tengah layar pada setiap frame, sehingga mouse tidak pernah terjebak pada batas layar
Pertahankan vektor "atas" kamera (disallow roll) dan hitung ulang vektor "ke samping"
Larang melihat ke atas melewati sumbu vertikal + y, atau turun melewati sumbu -y (terlalu jauh ke atas / ke bawah)
Dapatkan urutan rotasi dengan benar (atas / bawah terlebih dahulu, lalu kiri / kanan)
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! ; ^)