gpt4 book ai didi

c++ - 正确调用 glm::unproject() ,感到困惑

转载 作者:行者123 更新时间:2023-11-27 22:42:02 33 4
gpt4 key购买 nike

我正在尝试使用 glm::unproject() 将我的 SDL 鼠标坐标转换为 x/z 平面上的世界位置 vector 。基本上我想弄清楚用户用鼠标点击了哪个“x/z”坐标。

来自 other stack overflow answers我想到需要调用 glm::unproject()。我认为我向它传递了错误的参数,因为我为世界位置返回的值(打印的 std std::cerr)不是我期望的世界位置值。

我是否在下面正确构造了 glm::unproject() 的参数?具体来说,我应该结合相机的世界位置和 View 矩阵(使用 glm::lookAt 计算)来计算传递给 glm::unproject 的模型 View 矩阵吗?

struct Dimensions {
int x, y, w, h;
};

glm::mat4
Camera::view_matrix() const
{
// VIEW matrix is created by looking at some target member
auto const& target = target_->translation;
auto const position_xyz = world_position();

glm::vec3 const UP{0, 1, 0};
return glm::lookAt(position_xyz, target, UP);
}

glm::mat4
Camera::projection_matrix() const
{
auto const fov = glm::radians(90.0f);
return glm::perspective(fov, 4.0f/3.0f, 0.1f, 200.0f);
}

glm::vec3
calculate_worldpos(Camera const& camera, int const mouse_x, int const mouse_y)
{
float const width = 1024.0f, height = 768.0f;
glm::vec4 const viewport = glm::vec4(0.0f, 0.0f, width, height);
glm::mat4 const modelview = camera.view_matrix();
glm::mat4 const projection = camera.projection_matrix();

float z = 0.0;
glm::vec3 screenPos = glm::vec3(mouse_x, height - mouse_y - 1, z);
std::cerr << "screenpos: xyz: '" << glm::to_string(screenPos) << "'\n";

glm::vec3 worldPos = glm::unProject(screenPos, modelview, projection, viewport);
std::cerr << "worldpos: xyz: '" << glm::to_string(worldPos) << "'\n";
return worldPos;
}

在下图中,我有以下设置。

相机注视目标 = (0, 0, 0)

相机世界位置 = (-0.009, 5.107, -0.368)

(mouse_x, mouse_y, mouse_z) = (286, 393, 0)

如果您查看下图,您会发现我的鼠标悬停在世界位置 (3, 0, 0) 上,如网格所示。我希望计算鼠标的世界位置(如图所示)会返回 vector (3, 0, 0)。它没有,而是我得到了 vector :(0.049, 5.007, -0.360)。

enter image description here

有没有人看到我可能哪里出错了?我假设我在某处做出了某种不正确的假设。

最佳答案

您的假设是错误的:glm::unproject 返回由像素坐标中的 xy 位置和存储深度值的 z 坐标给出的输入的世界空间坐标。在屏幕上的每个像素上,世界空间中有无数个点转换到该像素(所有点都位于从投影中心通过该像素的光线上)。你想要哪一个是通过选择深度坐标来识别的,而不是在这条射线上产生一个特定的点。选择 z = 0 意味着结果将始终是相机近平面上的一个点。

您实际上要寻找的是这条射线(通过相机位置和计算点)与 xz 平面(其中 y=0)的交点。

射线由其上的两点(相机位置C,近平面点P)给出如下:

                  -0.009            0.058
C + l * (P-C) = ( 5.107 ) + l * ( -0.100 )
-0.368 0.008

,其中 l 是一个自由变量。

如前所述,我们正在寻找与 y=0 平面的交点 (a,b),因此我们可以制定以下等式:

  -0.009            0.058       a
( 5.107 ) + l * ( -0.100 ) = ( 0 )
-0.368 0.008 b

求解 l 的 y 方程 (5.107 + l * -0.1 = 0) 得到 l = 51.07。粘贴回 x 和 z 的方程式:

a = -0.009 + 51.07 * 0.058 = 2.95306
b = -0.368 + 51.07 * 0.008 = 0.04056

接近预期的世界空间位置。差异很可能是因为您只是在问题中显示了四舍五入的数字。出于准确性原因,我也不会在近平面上计算一个点,而是在远平面 (z=1) 上计算一个点,因为近平面距离通常非常小,可能会导致数值问题。

结论:提供的所有值都是正确的,但您只是没有计算出预期的值。

关于c++ - 正确调用 glm::unproject() ,感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48125247/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com