我想将3d位置转换为2d屏幕位置。我看了一个类似的问题:Projecting a 3D point to a 2D screen coordinate,但我完全不明白。我想为了计算2d位置我需要投影矩阵,但我不知道如何使用它,除了将点转换为位置坐标空间。另外,cam.FieldOfView在OpenGL中等于farZ吗?
有人可以帮我完成这个功能。参数是否足以计算2d位置? Pos已经是相对于相机位置的矢量。
Vector2* convert(Vector3& pos, Matrix4& projectionMatrix, int screenWidth, int screenHeight)
{
float ratio = screenWidth / screenHeight;
...
screenX = screenWidth * ( 1.0f - screenX);
screenY = screenHeight * ( 1.0f - screenY);
return new Vector2(screenX, screenY);
}
答案 0 :(得分:10)
在我看来会是这样的:
Vector2 Convert(Vector3 pos, const Matrix& viewMatrix, const Matrix& projectionMatrix, int screenWidth, int screenHeight)
{
pos = Vector3::Transform(pos, viewMatrix);
pos = Vector3::Transform(pos, projectionMatrix);
pos.X = screenWidth*(pos.X + 1.0)/2.0;
pos.Y = screenHeight * (1.0 - ((pos.Y + 1.0) / 2.0));
return Vector2(pos.X, pos.Y);
}
我们在这里做的只是通过两个转换矩阵传递Vector:视图,然后是投影。在投影之后,你得到一个Y和X在-1和1之间的向量。我们进行适当的变换以获得真实的像素坐标并返回一个新的Vector2。请注意,'pos'的Z分量也会在屏幕空间中存储该点的深度。
您需要'view'矩阵,因为它定义了相机的位置和旋转位置。投影仅定义3D空间在2D空间上“展平”的方式。
视野不是farZ。投影矩阵有一些参数,其中包括:
除了数学问题,您可以直接使用Vector2而不是堆分配(返回指针)。 Vector2是一个轻量级结构,指针很可能在这种情况下引起头痛(你要删除它的位置,依此类推)。还要注意我使用'const'引用,因为除了vector之外我们不修改它们。对于这个我们想要一个本地副本,这就是为什么它根本不是一个参考。
答案 1 :(得分:5)
以前的代码仅在您不进行任何轮换时才有效(例如。GL.Rotate(rotation_x, 1.0, 0.0, 0.0)
)。
但如果你这里做的是代码:
private Vector2 Convert(Vector3 pos, Matrix4 viewMatrix, Matrix4 projectionMatrix, int screenWidth, int screenHeight)
{
pos = Vector3.Transform(pos, viewMatrix);
pos = Vector3.Transform(pos, projectionMatrix);
pos.X /= pos.Z;
pos.Y /= pos.Z;
pos.X = (pos.X + 1) * screenWidth / 2;
pos.Y = (pos.Y + 1) * screenHeight / 2;
return new Vector2(pos.X, pos.Y);
}
答案 2 :(得分:0)