如何移动相机并将其粘在播放器上?

时间:2018-03-31 20:02:10

标签: c++ opengl 3d glm-math euler-angles

我正试图在相机周围移动相机。 现在我正在使用这样的相机类:

Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch) 
{
    this->position = position;
    this->m_WorldUp = up;
    this->up = up;
    this->m_Yaw = yaw;
    this->m_Pitch = pitch;
    this->UpdateCameraVectors();
}

glm::mat4 Camera::getViewMatrix() 
{
    return glm::lookAt(position, position + m_Front, up);
}

void Camera::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
{
    float velocity = moveSpeed * deltaTime;

    switch (direction) {
        case FORWARD:   position += m_Front   * velocity; break;
        case BACKWARD:  position -= m_Front   * velocity; break;
        case LEFT:      position -= m_Right   * velocity; break;
        case RIGHT:     position += m_Right   * velocity; break;
        case UPWARDS:   position += m_WorldUp * velocity; break;
        case DOWNWARDS: position -= m_WorldUp * velocity; break;
    }
}

void Camera::ProcessMouseMovement(GLfloat xOffset, GLfloat yOffset, GLboolean     constrainPitch)
{
    xOffset *= sensitivity;
    yOffset *= sensitivity;

    m_Yaw += xOffset;
    m_Pitch += yOffset;

    if (constrainPitch) {
        if (m_Pitch > 89.0f) {
            m_Pitch = 89.0f;
        } else if (m_Pitch < -89.0f) {
            m_Pitch = -89.0f;
        }
    }

    UpdateCameraVectors();
}

void Camera::UpdateCameraVectors() 
{
    glm::vec3 front;
    front.x = cos(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
    front.y = -sin(glm::radians(m_Pitch));
    front.z = sin(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
    m_Front = glm::normalize(front);

    m_Right = glm::normalize(glm::cross(m_Front, m_WorldUp));
    up = glm::normalize(glm::cross(m_Right, m_Front));
}

它让我可以自由地观察和移动世界。

目前玩家的更新方法:

    glm::mat4 projection = glm::mat4(1.0f);
    projection = glm::perspective(glm::radians(45.0f), 16.0f / 9.0f, 0.1f, 1000.0f);

    glm::mat4 view = glm::mat4(1.0f);
    view = camera->getViewMatrix();

    glm::mat4 model = glm::mat4(1.0f); {
        glm::mat4 translate = glm::translate(model, position);
        glm::mat4 rotate = glm::rotate(model, glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
        glm::mat4 scale = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));

        model = translate * rotate * scale;
    }

    glm::mat4 mvp = projection * view * model;
    GLint u_mvp = shader.GetUniformLocation("u_mvp");
    glUniformMatrix4fv(u_mvp, 1, GL_FALSE, glm::value_ptr(mvp));

我知道我必须用视图矩阵改变一些东西,但我没有足够的知识。

如何升级我的相机类,它可以看起来,旋转,围绕播放器,如圆形,MMO RPG风格?

2 个答案:

答案 0 :(得分:1)

相机类本身不应该接收键盘更新 - 应该在播放器类中完成。每次播放器移动时,请使用新位置更新相机类。有关更多详细信息,请参阅以下代码中的注释。

Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch, GLfloat dist) 
{
    m_WorldUp = up;
    // this->up = up; <- delete this variable; lookAt computes it for us

    m_Pos   = position;  // this is the *player* position
    m_Yaw   = yaw;
    m_Pitch = pitch;
    m_Dist  = dist;      // distance from the player

    UpdateViewMatrix(true);
}

// private method
void Camera::UpdateViewMatrix(bool computeDir = false)
{
    // compute the new direction
    if (computeDir)
    {
        glm::vec3 radial;
        radial.x = cos(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
        radial.y = sin(glm::radians(m_Pitch));  // there was a sign error here
        radial.z = sin(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
        m_Dir = -radial;
    }

    glm::vec3 pos = m_Pos - m_Dist * m_Dir; // *camera* position

    // additional view matrix member variable
    // you were using lookAt in the wrong way
    m_View = glm::lookAt(m_Pos, pos, m_WorldUp);
}

// public method - call this everytime the player moves
void Camera::UpdateTargetPosition(glm::vec3 const & pos)
{
    m_Pos = pos;
    UpdateViewMatrix();   
}

void Camera::UpdateAngles(GLfloat yaw, GLfloat pitch, GLboolean constrainPitch)
{
    if (constrainPitch) {
        if (pitch > 89.0f) {
            pitch = 89.0f;
        } else if (pitch < -89.0f) {
            pitch = -89.0f;
        }
    }

    // if yaw is outside the conventional range (-180.0, 180.0], shift it
    if (yaw < -180.0f || yaw > 180.0f) {
        yaw -= floor((yaw + 180.0f) / 360.0f) * 360.0f;
    }

    m_Yaw   = yaw;
    m_Pitch = pitch;
    UpdateViewMatrix(true);
}

void Camera::ProcessMouseMovement(GLfloat xOffset, GLfloat yOffset, GLboolean constrainPitch)
{
    UpdateAngles(m_Yaw + xOffset * sensitivity,
                 m_Pitch + yOffset * sensitivity,
                 constrainPitch);
}

答案 1 :(得分:0)

鼠标按照您需要:

camera = inverse(player * camera_view_and_offset)

其中player是您的播放器直接矩阵,camera_view_and_offset是视图偏移并相对于您的播放器坐标系转动矩阵,camera是您应该用作相机的逆矩阵of modelview ....

了解更多信息,请参阅: