Aquí hay algunos consejos sobre la rotación de la cámara (mouselook). Después de implementar ingenuamente una clase de cámara desde cero, descubrí que tenía que hacer algunos ajustes adicionales para un buen comportamiento de rotación:
Restablezca las coordenadas del mouse al centro de la pantalla en cada cuadro, para que el mouse nunca quede atrapado en los bordes de la pantalla
Mantenga el vector "arriba" de la cámara (no permita el rollo) y vuelva a calcular el vector "de lado"
No permita mirar hacia arriba más allá del eje vertical + y, o hacia abajo más allá del eje -y (demasiado arriba / abajo)
Obtenga el orden de rotaciones correcto (primero arriba / abajo, luego izquierda / derecha)
Renormalice los vectores "arriba", "apuntar" y "de lado" en cada cuadro
Espero que pueda usar algo de este código para su ventaja:
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();
Tenga en cuenta que:
mouseAxisX y mouseAxisY se definen como +/- 1, dependiendo de si desea que el eje x o y esté invertido. Por lo general, los juegos ofrecen esta opción al menos para el eje vertical.
MIN_UPWARDS_TILT_DEG se define como 1.0 grados (por lo que el espectador puede mirar desde -89 grados hacia abajo hasta +89 grados hacia arriba, lo que se ve bastante convincente como un rango vertical completo de 180 grados: los 2 grados faltantes en los extremos son bastante insignificantes) .
camera.aim_, camera.right_ y camera.up_ son, por supuesto, vectores 3D, y el método rotateAboutAxis () puede improvisar desde wikipedia y cualquier cantidad de fuentes en línea. Y_AXIS es un vector constante fijo (0,1,0).
ASSERT_ORTHONORMAL () es una comprobación de cordura solo en modo de depuración, que nunca se compila en modo optimizado / lanzamiento.
Disculpas de antemano por el código de estilo C ... una vez más, ¡aquí estás siguiendo el consejo de un tipo llamado Mediocritus! ; ^)