我正在尝试实现3D相机鼠标旋转。现在我所能做的只是旋转,如果我的鼠标在窗口的边界。这意味着如果我的窗口是1280宽度,如果鼠标坐标丰富0或1279,我就无法旋转更多。我读过相对鼠标应该有帮助。但它对我不起作用。
在主循环之前
SDL_ShowCursor(SDL_DISABLE);
SDL_SetRelativeMouseMode(SDL_TRUE);
SDL_WarpMouseInWindow(window, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
旋转xyz的函数
glm::vec3 MouseMotion(float x, float y)
{
float lastX = SCREEN_WIDTH / 2, lastY = SCREEN_HEIGHT / 2;
float pitch = 0.0f, yaw = -90.0f;
float offsetX = x - lastX;
float offsetY = lastY - y;
lastX = x;
lastY = y;
float sensitivity = 0.3f;
yaw += offsetX * sensitivity;
pitch += offsetY * sensitivity;
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = std::cos(glm::radians(yaw)) * std::cos(glm::radians(pitch));
front.y = std::sin(glm::radians(pitch));
front.z = std::sin(glm::radians(yaw)) * std::cos(glm::radians(pitch));
//std::cout << "Mouse: " << offsetX << ", " << offsetY << std::endl;
//std::cout << "YAW AND PITCH: " << yaw << ", " << pitch << std::endl;
return glm::normalize(front);
}
和事件循环
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
exit(0);
}
if (event.type == SDL_MOUSEMOTION)
{
float mouseX = (float)event.motion.x;
float mouseY = (float)event.motion.y;
cameraFront = MouseMotion(mouseX, mouseY);
}
}
它正在工作,但只有当我的鼠标在边界内时才会有效。
更改为event.motion.xrel和event.motion.yrel不会解决此问题。由于我的相机抖动,即向右移动并返回中心或左侧并返回中心,因此它更容易被窃听。
如何让我的相机完全移动,无限移动?
答案 0 :(得分:0)
继续评论之后,这里列出了一系列问题:
您需要在SDL_WarpMouseInWindow
事件后每次调用SDL_MOUSEMOTION
来重置鼠标,否则它会很快达到您所说的“界限”。
pitch
和yaw
的范围必须高于游戏循环,否则每次都会重置它们,您将无法实现“无限循环”。 / p>
sensitivity
远太高了。典型的~500单位的鼠标移动转换为〜180度转动。
这是尝试修复上述问题,并进行了一些代码重构:
glm::vec3 polarVector(float p, float y)
{
// this form is already normalized
return glm::vec3(std::cos(y) * std::cos(p),
std::sin(p),
std::sin(y) * std::cos(p));
}
// clamp pitch to [-89, 89]
float clampPitch(float p)
{
return p > 89.0f ? 89.0f : (p < -89.0f ? -89.0f : p);
}
// clamp yaw to [-180, 180] to reduce floating point inaccuracy
float clampYaw(float y)
{
float temp = (y + 180.0f) / 360.0f;
return y - ((int)temp - (temp < 0.0f ? 1 : 0)) * 360.0f;
}
int main(int argc, char*args[])
{
// ...
// experiment with this
const float sensitivity = 0.001f;
#define CTR_X (SCREEN_WIDTH / 2)
#define CTR_Y (SCREEN_HEIGHT / 2)
#define RESET_MOUSE SDL_WarpMouseInWindow(window, CTR_X, CTR_Y)
// call once at the start
RESET_MOUSE;
// keep outside the loop
float pitch = 0.0f, yaw = 0.0f;
while (!quit)
{
// ...
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
exit(0);
}
if (event.type == SDL_MOUSEMOTION)
{
float deltaX = (float)event.motion.x - CTR_X;
float deltaY = (float)event.motion.y - CTR_Y;
yaw = clampYaw(yaw + sensitivity * deltaX);
pitch = clampPitch(pitch - sensitivity * deltaY);
// assumes radians input
cameraFront = polarVector(glm::radians(pitch), glm::radians(yaw));
// reset *every time*
RESET_MOUSE;
}
}
// ...
}
}