Como devo implementar uma câmera em primeira pessoa?

12

Sou programador iniciante e estou criando um projeto que me permite andar pelas salas por meio de uma câmera em primeira pessoa. Até agora, tenho os prédios desenhados, mas agora estou preso e não sei como fazer uma câmera em primeira pessoa para me permitir andar por aí.

Alguém poderia me indicar uma classe de câmera que eu poderia usar ou algum código útil?

DK10
fonte
Confira isso learnopengl.com/#!Getting-started/Camera
Archmede 2/17/17

Respostas:

7

Aqui estão algumas dicas sobre a rotação da câmera (mouselook). Depois de implementar de forma ingênua uma classe de câmera do zero, descobri que precisava fazer alguns ajustes adicionais para obter um bom comportamento rotacional:

  1. Redefina as coordenadas do mouse para o centro da tela em cada quadro, para que o mouse nunca fique preso nas bordas da tela

  2. Mantenha o vetor "para cima" da câmera (desaprovar rolo) e recompute o vetor "para o lado"

  3. Não permitir olhar para cima além do eixo vertical + y ou para baixo além do eixo -y (muito acima / abaixo)

  4. Corrija a ordem das rotações (para cima / para baixo primeiro e depois para a esquerda / direita)

  5. Renormalize os vetores "para cima", "mira" e "lateralmente" em cada quadro

Espero que você possa usar parte desse código para sua vantagem:

    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();

Observe que:

mouseAxisX e mouseAxisY são definidos como +/- 1, dependendo se você deseja que o eixo x ou y seja invertido. Normalmente, os jogos oferecem essa opção pelo menos para o eixo vertical.

MIN_UPWARDS_TILT_DEG é definido como 1,0 graus (para que o espectador possa olhar de -89 graus para baixo a +89 graus para cima, o que parece bastante convincente como uma faixa vertical completa de 180 graus - os 2 graus ausentes nos extremos são desprezíveis) .

camera.aim_, camera.right_ e camera.up_ são, obviamente, vetores 3D, e o método rotateAboutAxis () você pode juntar na wikipedia e em qualquer número de fontes online. Y_AXIS é um vetor constante fixo (0,1,0).

ASSERT_ORTHONORMAL () é uma verificação de integridade apenas no modo de depuração, que nunca é compilada no modo otimizado / liberação.

Pedimos desculpas antecipadamente pelo código do estilo C ... então, novamente, aqui você está recebendo conselhos de um cara chamado Mediocritus! ; ^)

Mediocritus
fonte
Do que você está falando? O código no estilo C é a pedra angular do espírito hacker! 8-)
blissfreak
5

Existem várias maneiras de fazer isso (consulte os tutoriais aqui , aqui e aqui, por exemplo, com muito mais disponível na Internet via Google). A tecnologia usada nos recursos que você pode encontrar online pode variar um pouco (em termos de D3D, XNA, OpenGL etc.), mas os princípios subjacentes serão os mesmos:

  • o objeto da câmera mantém sua posição e direção e, opcionalmente, outro par de vetores que, juntamente com a direção, formam uma base ortogonal para o sistema de coordenadas da câmera.
  • a API pública da sua câmera expõe métodos para guiar, inclinar e, opcionalmente, rolar a câmera em torno de seus vetores básicos - o ato de ajustar a orientação da câmera atualizará os vetores básicos para uso posterior.

Você pode optar por armazenar os vetores diretamente ou recalcular a matriz de vista subjacente sempre que precisar e preferir. Há muita flexibilidade na técnica; portanto, se você precisar de ajuda além das etapas gerais, poderá postar uma nova pergunta com uma consulta mais específica.


fonte
2

Para uma referência específica a uma implementação do sistema de câmera usando o Direct3D, recomendo este artigo: http://www.toymaker.info/Games/html/camera.html . O autor também descreve outros métodos e recursos que podem ser usados ​​para expandir a implementação.

Thomas Anthony
fonte