使用glm与glfw实现鼠标控制相机绕模型旋转的问题求助
现有代码核心问题
- 直接使用鼠标绝对像素坐标
xpos/ypos作为三角函数输入,没有转换为角度偏移量,过大的坐标数值导致旋转逻辑完全混乱 - 相机坐标计算不符合绕点旋转的球坐标转换规则,无法保持到目标点的半径固定,也不能对应鼠标的移动方向
解决方案
第一步:新增必要的全局/类成员变量
// 鼠标状态变量,初始值可根据你的窗口尺寸调整 float lastX = 400.0f, lastY = 300.0f; float yaw = -90.0f; // 初始偏航角,默认朝向Z轴负方向 float pitch = 0.0f; // 初始俯仰角 bool firstMouse = true; const float mouseSensitivity = 0.1f; // 鼠标灵敏度,可自行调整旋转速度
第二步:修改鼠标回调函数
void mouseCallback(GLFWwindow* window, double xpos, double ypos) { // 处理第一次进入窗口的鼠标跳变问题 if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } // 计算鼠标偏移量 float xoffset = xpos - lastX; float yoffset = lastY - ypos; // Y轴反转,适配屏幕坐标从上到下递增的规则 lastX = xpos; lastY = ypos; // 仅左键按下时更新旋转 if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) { // 偏移量乘以灵敏度 xoffset *= mouseSensitivity; yoffset *= mouseSensitivity; // 更新俯仰角和偏航角 yaw += xoffset; pitch += yoffset; // 限制俯仰角范围,避免视角翻转 if (pitch > 89.0f) pitch = 89.0f; if (pitch < -89.0f) pitch = -89.0f; // 计算旋转中心,和你lookAt的目标点保持一致 glm::vec3 targetPos = glm::vec3(0.0f, 0.0f, 5.0f) + cameraFront; // 取当前相机到目标点的距离作为半径,旋转时保持距离不变 float radius = glm::distance(glm::vec3(camX, camY, camZ), targetPos); // 球坐标转笛卡尔坐标,计算新的相机位置 camX = targetPos.x + radius * cos(glm::radians(yaw)) * cos(glm::radians(pitch)); camY = targetPos.y + radius * sin(glm::radians(pitch)); camZ = targetPos.z + radius * sin(glm::radians(yaw)) * cos(glm::radians(pitch)); } }
第三步:保留原有view矩阵构造代码即可
你现有的lookAt代码无需修改,和上述旋转逻辑完全兼容,不会影响已有的平移功能。
如果需要固定绕(0,0,0)的模型旋转,不需要平移时旋转中心跟着移动,把上面的targetPos改成glm::vec3(0.0f, 0.0f, 0.0f)即可。
内容的提问来源于stack exchange,提问作者BenEat
相关产品推荐
相关产品推荐

