从相机投影线
Projecting line from camera
我正在尝试将视口点击转换为对象的世界位置。
如果我只想在用户点击 canvas:
void Canvas::getClickPosition(int x, int y, Vector3d(&out)[2]) const
{
Vector4d point4d[2];
Vector2d point2d(x, y);
int w = canvas.width();
int h = canvas.height();
Matrix4d model = m_world * m_camera;
for (int i = 0; i < 2; ++i) {
Vector4d sw(point2d.x() / (0.5 * w) - 1,
point2d.y() / (0.5* h) - 1, i * 1, 1);
point4d[i] = (m_proj * model).inverse() * sw;
out[i] = point4d.block<1, 3>(0, 0);
}
}
预期的行为是通过这个简单的代码实现的。
当我尝试实际制作一条在用户首次单击时看起来像 一个像素 的线时,问题就出现了。在相机朝任何方向旋转之前,它应该看起来像是从相机中完美拍摄的,并且它具有任何长度(无关紧要)。
我尝试了显而易见的方法:
Vector4d sw(point2d.x() / (0.5 * w) - 1,
point2d.y() / (0.5* h) - 1, 1, 1); // Z is now 1 instead of 0.
正如你们大多数人所预料的那样,结果是一条在屏幕中央追寻 消失点 的线。因此,我点击离中心越远,线条偏离预期方向的幅度就越大。
无论在屏幕的哪个位置,如何使一条线从点击的角度显示为一个点?
编辑:为了更清楚起见,我试图画出这样的线条:
glBegin(GL_LINES);
line.p1 = m_proj * (m_world * m_camera) * line.p1;
line.p2 = m_proj * (m_world * m_camera) * line.p2;
glVertex3f(line.p1.x(), line.p1.y(), line.p1.z());
glVertex3f(line.p2.x(), line.p2.y(), line.p2.z());
glEnd();
您的初步尝试实际上非常接近。你唯一缺少的是透视鸿沟:
out[i] = point4d.block<1, 3>(0, 0) / point4d.w();
根据您的投影矩阵,您可能还需要为近平面指定 -1
的 z 值,而不是 0
。
是的,您的矩阵顺序 projection * model * view
看起来很奇怪。但是只要您在两个过程中保持相同的顺序,您应该会得到一致的结果。
确保 window 坐标系的 y 轴指向上方。否则,您将得到反映在水平中线的结果。
我正在尝试将视口点击转换为对象的世界位置。
如果我只想在用户点击 canvas:
void Canvas::getClickPosition(int x, int y, Vector3d(&out)[2]) const
{
Vector4d point4d[2];
Vector2d point2d(x, y);
int w = canvas.width();
int h = canvas.height();
Matrix4d model = m_world * m_camera;
for (int i = 0; i < 2; ++i) {
Vector4d sw(point2d.x() / (0.5 * w) - 1,
point2d.y() / (0.5* h) - 1, i * 1, 1);
point4d[i] = (m_proj * model).inverse() * sw;
out[i] = point4d.block<1, 3>(0, 0);
}
}
预期的行为是通过这个简单的代码实现的。
当我尝试实际制作一条在用户首次单击时看起来像 一个像素 的线时,问题就出现了。在相机朝任何方向旋转之前,它应该看起来像是从相机中完美拍摄的,并且它具有任何长度(无关紧要)。
我尝试了显而易见的方法:
Vector4d sw(point2d.x() / (0.5 * w) - 1,
point2d.y() / (0.5* h) - 1, 1, 1); // Z is now 1 instead of 0.
正如你们大多数人所预料的那样,结果是一条在屏幕中央追寻 消失点 的线。因此,我点击离中心越远,线条偏离预期方向的幅度就越大。
无论在屏幕的哪个位置,如何使一条线从点击的角度显示为一个点?
编辑:为了更清楚起见,我试图画出这样的线条:
glBegin(GL_LINES);
line.p1 = m_proj * (m_world * m_camera) * line.p1;
line.p2 = m_proj * (m_world * m_camera) * line.p2;
glVertex3f(line.p1.x(), line.p1.y(), line.p1.z());
glVertex3f(line.p2.x(), line.p2.y(), line.p2.z());
glEnd();
您的初步尝试实际上非常接近。你唯一缺少的是透视鸿沟:
out[i] = point4d.block<1, 3>(0, 0) / point4d.w();
根据您的投影矩阵,您可能还需要为近平面指定 -1
的 z 值,而不是 0
。
是的,您的矩阵顺序 projection * model * view
看起来很奇怪。但是只要您在两个过程中保持相同的顺序,您应该会得到一致的结果。
确保 window 坐标系的 y 轴指向上方。否则,您将得到反映在水平中线的结果。