c++ - 如何移动相机并将其粘贴到播放器上?

标签 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));

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

我如何升级我的相机类,使其可以围绕玩家观看、旋转,就像在一个圆圈中一样,成为 MMO RPG 风格?

最佳答案

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

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

关于c++ - 如何移动相机并将其粘贴到播放器上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49591884/

相关文章:

opengl - 如何在 MonoDevelop (Linux) 中运行 OpenGL 程序?

c++ - 使用 MinGW、freeglut 和 glew 编译简单的静态 OpenGL 4.0 程序

c++ - 如何在 C++ 中创建带有用户定义按钮的消息框?

c - 为什么旋转矩阵不在文本中心旋转?

java - 外推超过两个已知点的直线

algorithm - 从另一组中找到一组中的最远点

xna - 将 3D 添加到 2D 游戏

matlab - 如何在 Matlab 中将 3D 路径数据绘制为带状

c# - 实现共享内存时要考虑的要点

c++ - 在 if() 中比较 LPCWSTR