1

I'm trying to move camera around the player. Right now I'm using camera class like this:

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

It allows me to free look and move around the world.

Player's update method at the moment:

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

I know that I have to change something with view matrix, but I have not got enough knowledge.

How can I upgrade my camera class that it can look, rotate, around a player, like in a circle, an MMO RPG style?

genpfault
  • 51,148
  • 11
  • 85
  • 139
IScream
  • 49
  • 4

2 Answers2

1

The camera class itself should not be receiving keyboard updates at all - that should be done in the player class. Every time the player moves, update the camera class with its new position. See comments in below code for more details.

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);
}
meowgoesthedog
  • 14,670
  • 4
  • 27
  • 40
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/168016/discussion-on-answer-by-meowgoesthedog-how-to-move-camera-around-and-stick-it-to). –  Apr 02 '18 at 03:17
0

for mouse follow you need:

camera = inverse(player * camera_view_and_offset)

where player is your player direct matrix, camera_view_and_offset is the view offset and turn around matrix relative to your player coordinate system and camera is your camera inverse matrix you should use as part of modelview ....

for more info see:

Spektre
  • 49,595
  • 11
  • 110
  • 380