相机在 3d 空间中无法正确移动

发布于 2025-01-10 16:01:45 字数 2421 浏览 0 评论 0原文

我目前正在研究在 3D 空间中移动相机。我希望它仅在 x 轴和 z 轴(水平)上移动。到目前为止,当相机的旋转全部为零时,它正在正确移动,但是当我更改它的值时,相机开始表现得有点奇怪,朝错误的方向移动。我正在使用 SFML,但我认为是数学导致了问题。这很奇怪,因为我移动相机的代码与我之前编写的项目之一相同,但该项目运行良好。
这是限制旋转的代码:

camera.rot.x += movey;
if (glm::degrees(camera.rot.x) < -180.0f) camera.rot.x = glm::radians(180.0f) + camera.rot.x;
if (glm::degrees(camera.rot.x) > 180.0f) camera.rot.x = camera.rot.x + glm::radians(-180.0f);
camera.rot.y -= movex;
if (glm::degrees(camera.rot.y) < -180.0f) camera.rot.y = glm::radians(180.0f) + camera.rot.y;
if (glm::degrees(camera.rot.y) > 180.0f) camera.rot.y = camera.rot.y + glm::radians(-180.0f);

我用来移动相机的代码:

float x = sin(camera.rot.y) * camera.speed; float z = cos(camera.rot.y) * camera.speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { camera.pos.x -= x; camera.pos.z -= z; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { camera.pos.x += x; camera.pos.z += z; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { camera.pos.x += z; camera.pos.z -= x; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { camera.pos.x -= z; camera.pos.z += x; }

如果有人可以帮助我解决这个问题,请感激。

对于任何想知道的人,这里是我用来将 3d 坐标转换为屏幕坐标的代码:

glm::mat3 x(0.0f);
x[0][0] = 1.0f;
x[1][1] = cos(camera.rot.x);
x[1][2] = sin(camera.rot.x);
x[2][1] = -sin(camera.rot.x);
x[2][2] = cos(camera.rot.x);
glm::mat3 y(0.0f);
y[0][0] = cos(camera.rot.y);
y[0][2] = -sin(camera.rot.y);
y[1][1] = 1.0f;
y[2][0] = sin(camera.rot.y);
y[2][2] = cos(camera.rot.y);
glm::mat3 z(0.0f);
z[0][0] = cos(camera.rot.z);
z[0][1] = sin(camera.rot.z);
z[1][0] = -sin(camera.rot.z);
z[1][1] = cos(camera.rot.z);
z[2][2] = 1.0f;
glm::mat3 trans = x * y * z;
//trans is the perspective matrix
glm::vec3 e(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, (float)tan(camera.fov / 2) * (float)(SCREEN_WIDTH / 2));
//e is the distance from the camera pinhole relate to the 'screen'
glm::mat3 ScreenTrans(0.0f);
ScreenTrans[0][0] = 1.0f;
ScreenTrans[0][2] = e.x / e.z;
ScreenTrans[1][1] = 1.0f;
ScreenTrans[1][2] = e.y / e.z;
ScreenTrans[2][2] = 1.0f / e.z;
//ScreenTrans is the matrix use to transform Camera space into Screen space
std::vector<glm::vec3> 3D_coords = Some3DPoints;
for (glm::vec3 coord: 3D_coords){
    glm::vec3 afterTrans = trans * coord;
    glm::vec3 cameraSpace = afterTrans - camera.pos;
    glm::vec3 2DScreenCoord = cameraSpace * ScreenTrans;
}

I am currently working on moving a camera in 3d space. I want it to move ONLY in the x and z-axis (horizontal). So far it was moving correctly when the rotation of the camera is all zero, but when I change the value of it, the camera starts to act a little weird, moving in the wrong direction. I am using SFML, but I think it's the math that causes the problem. It is weird because the code I move the camera is identical to one of the projects I wrote earlier, but the project works fine.
Here's the code that constrains the rotation:

camera.rot.x += movey;
if (glm::degrees(camera.rot.x) < -180.0f) camera.rot.x = glm::radians(180.0f) + camera.rot.x;
if (glm::degrees(camera.rot.x) > 180.0f) camera.rot.x = camera.rot.x + glm::radians(-180.0f);
camera.rot.y -= movex;
if (glm::degrees(camera.rot.y) < -180.0f) camera.rot.y = glm::radians(180.0f) + camera.rot.y;
if (glm::degrees(camera.rot.y) > 180.0f) camera.rot.y = camera.rot.y + glm::radians(-180.0f);

The code I use to move the camera:

float x = sin(camera.rot.y) * camera.speed; float z = cos(camera.rot.y) * camera.speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { camera.pos.x -= x; camera.pos.z -= z; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { camera.pos.x += x; camera.pos.z += z; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { camera.pos.x += z; camera.pos.z -= x; }
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { camera.pos.x -= z; camera.pos.z += x; }

Appreciate it if anyone can help me with this question.

For anyone that's wondering, here's the code i use to transform 3d coords to screen coords:

glm::mat3 x(0.0f);
x[0][0] = 1.0f;
x[1][1] = cos(camera.rot.x);
x[1][2] = sin(camera.rot.x);
x[2][1] = -sin(camera.rot.x);
x[2][2] = cos(camera.rot.x);
glm::mat3 y(0.0f);
y[0][0] = cos(camera.rot.y);
y[0][2] = -sin(camera.rot.y);
y[1][1] = 1.0f;
y[2][0] = sin(camera.rot.y);
y[2][2] = cos(camera.rot.y);
glm::mat3 z(0.0f);
z[0][0] = cos(camera.rot.z);
z[0][1] = sin(camera.rot.z);
z[1][0] = -sin(camera.rot.z);
z[1][1] = cos(camera.rot.z);
z[2][2] = 1.0f;
glm::mat3 trans = x * y * z;
//trans is the perspective matrix
glm::vec3 e(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, (float)tan(camera.fov / 2) * (float)(SCREEN_WIDTH / 2));
//e is the distance from the camera pinhole relate to the 'screen'
glm::mat3 ScreenTrans(0.0f);
ScreenTrans[0][0] = 1.0f;
ScreenTrans[0][2] = e.x / e.z;
ScreenTrans[1][1] = 1.0f;
ScreenTrans[1][2] = e.y / e.z;
ScreenTrans[2][2] = 1.0f / e.z;
//ScreenTrans is the matrix use to transform Camera space into Screen space
std::vector<glm::vec3> 3D_coords = Some3DPoints;
for (glm::vec3 coord: 3D_coords){
    glm::vec3 afterTrans = trans * coord;
    glm::vec3 cameraSpace = afterTrans - camera.pos;
    glm::vec3 2DScreenCoord = cameraSpace * ScreenTrans;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初相遇 2025-01-17 16:01:45

在深入研究我的代码很长时间后,我发现问题出在我限制旋转的代码中,以及如何获得“反式”矩阵。
首先,约束代码应该是:

camera.rot.x -= movey;
if (glm::degrees(camera.rot.x) < -90.0f) camera.rot.x = glm::radians(180.0f) + camera.rot.x;
if (glm::degrees(camera.rot.x) > 90.0f) camera.rot.x = camera.rot.x + glm::radians(-180.0f);
camera.rot.y += movex;
if (glm::degrees(camera.rot.y) < -180.0f) camera.rot.y = glm::radians(360.0f) + camera.rot.y;
if (glm::degrees(camera.rot.y) > 180.0f) camera.rot.y = camera.rot.y + glm::radians(-360.0f);

我错过了计算值并错误地将 rot.x 作为 y 轴,将 rot.y 作为 x 轴。
接下来是“trans”矩阵。它应该是:

glm::mat3 trans = z * y * x;

它应该首先处理 y 轴的旋转,而不是 x 轴,否则你的 y 轴(相机空间)的旋转将始终在 y 轴(世界空间)上。

After digging into my code for a long time, i find that the problem is in the code where I constrains my rotations, and how I get the "trans" matrix.
First, the constrains code should be:

camera.rot.x -= movey;
if (glm::degrees(camera.rot.x) < -90.0f) camera.rot.x = glm::radians(180.0f) + camera.rot.x;
if (glm::degrees(camera.rot.x) > 90.0f) camera.rot.x = camera.rot.x + glm::radians(-180.0f);
camera.rot.y += movex;
if (glm::degrees(camera.rot.y) < -180.0f) camera.rot.y = glm::radians(360.0f) + camera.rot.y;
if (glm::degrees(camera.rot.y) > 180.0f) camera.rot.y = camera.rot.y + glm::radians(-360.0f);

I miss calculated the value and mistake rot.x as the y-axis and rot.y as the x-axis.
The next is the "trans" matrix. It should be:

glm::mat3 trans = z * y * x;

It should be FIRST handling the rotation of the y-axis, than the x-axis, or else your rotation of the y-axis(camera space) will always be on the y-axis(world space).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文