¿Cómo debo implementar una cámara en primera persona?

12

Soy un programador principiante y estoy creando un proyecto que me permite caminar por las habitaciones con una cámara en primera persona. Hasta ahora, tengo los edificios dibujados y encendidos, pero ahora estoy atascado y no sé cómo hacer una cámara en primera persona que me permita caminar.

¿Alguien podría señalarme hacia una clase de cámara que pueda usar, o algún código útil?

DK10
fuente

Respuestas:

7

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:

  1. 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

  2. Mantenga el vector "arriba" de la cámara (no permita el rollo) y vuelva a calcular el vector "de lado"

  3. No permita mirar hacia arriba más allá del eje vertical + y, o hacia abajo más allá del eje -y (demasiado arriba / abajo)

  4. Obtenga el orden de rotaciones correcto (primero arriba / abajo, luego izquierda / derecha)

  5. 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! ; ^)

Mediocrito
fuente
¿De qué estás hablando? ¡El código de estilo C es la piedra angular del espíritu hacker! 8-)
blissfreak
5

Hay varias formas de hacerlo (consulte los tutoriales aquí , aquí y aquí, por ejemplo, con mucho más disponible en Internet a través de Google). La tecnología utilizada en los recursos que puede encontrar en línea puede variar ligeramente (en términos de D3D, XNA, OpenGL, etc.), pero los principios subyacentes serán los mismos:

  • su objeto de cámara mantiene su posición y su dirección, y opcionalmente otro par de vectores que, junto con la dirección, forman una base ortogonal para el sistema de coordenadas de la cámara.
  • La API pública de su cámara expone métodos para guiñar, inclinar y, opcionalmente, hacer girar la cámara alrededor de sus vectores básicos: el acto de ajustar la orientación de la cámara actualizará los vectores básicos para su uso posterior.

Puede optar por almacenar los vectores directamente o volver a calcular la matriz de vista subyacente cada vez que lo necesite y lo prefiera. La técnica tiene mucha flexibilidad, por lo que si necesita ayuda más allá de esos pasos generales, puede publicar una nueva pregunta con una consulta más específica.


fuente
2

Para una referencia específica a una implementación del sistema de cámara usando Direct3D, recomiendo este artículo: http://www.toymaker.info/Games/html/camera.html . El autor también describe otros métodos y características que pueden usarse para ampliar la implementación.

Thomas Anthony
fuente