Ось декілька порад щодо обертання камери (миші). Після наївного впровадження класу камери з нуля, я виявив, що мені потрібно зробити кілька додаткових налаштувань для хорошої ротаційної поведінки:
Скиньте координати миші на центр екрану на кожному кадрі, щоб миша ніколи не потрапляла на межі екрана
Підтримуйте вектор "камери" вгору (забороняйте перекидання) та перераховуйте вектор "набік"
Заборонити дивитися вгору по вертикалі + осі y або вниз по осі -y (занадто далеко вгору / вниз)
Правильний порядок обертів правильний (спочатку вгору / вниз, потім вліво / вправо)
Переосмислити вектори "вгору", "ціль" та "набік" кожного кадру
Сподіваємось, ви можете використати частину цього коду на вашу користь:
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();
Зауважте, що:
mouseAxisX та mouseAxisY визначаються як +/- 1, залежно від того, чи потрібно перевернутий осі x або y миші. Зазвичай ігри пропонують цей варіант принаймні для вертикальної осі.
MIN_UPWARDS_TILT_DEG визначається рівнем 1,0 градуса (тому глядачеві дозволяється дивитись від -89 градусів вниз до +89 градусів вгору, що виглядає досить переконливо, як повний вертикальний діапазон на 180 градусів - відсутні два градуси в крайніх межах досить незначні) .
camera.aim_, camera.right_ і camera.up_ - це звичайно тривимірні вектори, і метод rotateAboutAxis (), який ви можете спільно використовувати з wikipedia та будь-якої кількості Інтернет-джерел. Y_AXIS - фіксований постійний (0,1,0) вектор.
ASSERT_ORTHONORMAL () - це перевірка рівня безпеки на відладку лише в режимі налагодження, яка ніколи не компілюється в режимі оптимізації / випуску.
Заздалегідь вибачте за код у стилі С ... потім знову, ви отримуєте поради від хлопця на ім'я Медіокрит! ; ^)