如何围绕玩家移动相机并将其固定在玩家身上?
实现相机围绕玩家旋转的解决方案
看起来你想要实现相机围绕玩家旋转的第三人称视角效果对吧?我看了你当前的Camera类实现,现在的逻辑是相机基于自身位置和前方向生成视图矩阵,要改成围绕玩家移动的话,我们需要调整核心逻辑——把玩家位置作为固定目标点,相机的位置根据角度和距离围绕这个目标点计算。
首先先把你提供的现有代码格式化出来:
class Camera { public: 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 = ...; // 你这里的代码没写完,不过没关系 // 现有键盘处理逻辑 } private: glm::vec3 position; glm::vec3 m_WorldUp; glm::vec3 up; glm::vec3 m_Front; glm::vec3 m_Right; GLfloat m_Yaw; GLfloat m_Pitch; void UpdateCameraVectors(); };
接下来是具体的修改方案:
1. 新增核心成员变量
我们需要给Camera类添加两个关键变量:
m_Target:存储玩家的位置,也就是相机要围绕旋转的目标点m_Distance:相机到玩家的距离,用来控制视角的远近
修改后的类成员如下:
private: glm::vec3 position; glm::vec3 m_WorldUp; glm::vec3 up; glm::vec3 m_Front; glm::vec3 m_Right; GLfloat m_Yaw; GLfloat m_Pitch; // 新增:玩家目标位置 glm::vec3 m_Target; // 新增:相机与玩家的距离 GLfloat m_Distance;
2. 调整构造函数
更新构造函数,初始化目标点和距离,并且根据初始角度计算相机的初始位置:
Camera::Camera(glm::vec3 target, glm::vec3 up, GLfloat yaw, GLfloat pitch, GLfloat distance) { this->m_Target = target; this->m_Distance = distance; this->m_WorldUp = up; this->up = up; this->m_Yaw = yaw; this->m_Pitch = pitch; // 根据角度和距离计算相机初始位置 UpdateCameraPosition(); this->UpdateCameraVectors(); }
3. 添加相机位置计算方法
新增一个UpdateCameraPosition方法,通过球面坐标转笛卡尔坐标的方式,根据yaw、pitch和距离计算相机相对于玩家的位置:
void Camera::UpdateCameraPosition() { // 球面坐标转换:基于目标点计算相机位置 GLfloat x = m_Target.x + m_Distance * cos(glm::radians(m_Pitch)) * cos(glm::radians(m_Yaw)); GLfloat y = m_Target.y + m_Distance * sin(glm::radians(m_Pitch)); GLfloat z = m_Target.z + m_Distance * cos(glm::radians(m_Pitch)) * sin(glm::radians(m_Yaw)); this->position = glm::vec3(x, y, z); }
4. 修改视图矩阵生成逻辑
原来的getViewMatrix是让相机看向自身前方向,现在要改成看向玩家位置:
glm::mat4 Camera::getViewMatrix() { // 第二个参数改为玩家目标点,而不是相机位置+前方向 return glm::lookAt(position, m_Target, up); }
5. 调整鼠标与键盘输入处理
- 鼠标移动:当用户拖动鼠标时,更新yaw和pitch,然后重新计算相机位置:
void Camera::ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true) { // 调整鼠标灵敏度 xoffset *= 0.1f; yoffset *= 0.1f; m_Yaw += xoffset; m_Pitch += yoffset; // 限制俯仰角,避免相机翻转到奇怪的角度 if (constrainPitch) { if (m_Pitch > 89.0f) m_Pitch = 89.0f; if (m_Pitch < -89.0f) m_Pitch = -89.0f; } // 更新相机位置和方向向量 UpdateCameraPosition(); UpdateCameraVectors(); }
- 键盘输入:可以改成控制相机与玩家的距离(拉近/拉远):
void Camera::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime) { GLfloat speed = 2.5f * deltaTime; if (direction == FORWARD) m_Distance -= speed; if (direction == BACKWARD) m_Distance += speed; // 限制距离范围,避免相机贴脸或者太远 m_Distance = glm::clamp(m_Distance, 1.0f, 20.0f); // 更新相机位置 UpdateCameraPosition(); }
6. 玩家移动时更新目标点
当玩家在场景中移动时,只需要调用一个setter方法更新相机的目标点即可:
void Camera::SetTarget(glm::vec3 newTarget) { m_Target = newTarget; UpdateCameraPosition(); }
这样修改后,相机就会始终围绕玩家(m_Target)旋转,鼠标控制旋转角度,键盘控制视角远近,完全符合你想要的效果。
内容的提问来源于stack exchange,提问作者IScream




