Вот несколько советов по повороту камеры (мышиный взгляд). После наивной реализации класса камеры с нуля, я обнаружил, что мне пришлось сделать несколько дополнительных настроек для хорошего поведения вращения:
Сбрасывайте координаты мыши по центру экрана в каждом кадре, чтобы мышь не попадала на границы экрана
Сохраните вектор «вверх» камеры (запретить поворот) и пересчитайте вектор «в сторону»
Не разрешать смотреть вверх за вертикальную ось + ось или вниз за ось -у (слишком далеко вверх / вниз)
Получите правильный порядок поворотов (сначала вверх / вниз, затем влево / вправо)
Перенормируйте векторы «вверх», «цель» и «в сторону» в каждом кадре
Надеюсь, вы можете использовать часть этого кода в ваших интересах:
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 градусов - пропущенные 2 градуса в крайних значениях весьма незначительны) ,
camera.aim_, camera.right_ и camera.up_ - это, конечно, 3D-векторы, и метод rotateAboutAxis (), который вы можете объединять в википедии и любом количестве онлайн-источников. Y_AXIS - вектор с фиксированной константой (0,1,0).
ASSERT_ORTHONORMAL () - это проверка работоспособности только в режиме отладки, которая никогда не компилируется в режиме оптимизации / выпуска.
Заранее извиняюсь за код в стиле C ... опять же, вот вам совет от парня по имени Mediocritus! ; ^)