将 3d 位置转换为 2d 屏幕位置

发布于 2024-12-09 07:27:35 字数 705 浏览 0 评论 0原文

我想将 3d 位置转换为 2d 屏幕位置。我查看了类似的问题:将 3D 点投影到2D 屏幕坐标 ,但我不完全理解它。我认为为了计算二维位置,我需要投影矩阵,但除了将点转换为位置坐标空间之外,我不知道它是如何使用的。另外,OpenGL中cam.FieldOfView等于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); 
       }

I'd like to convert a 3d position into 2d screen position. I had a look at a similar question: Projecting a 3D point to a 2D screen coordinate , but I dont understand it completely. I thought in order to calculate the 2d position I would need the projection matrix, but I dont see how it is used, apart from converting a point into the location coordinate space. Besides, is cam.FieldOfView equal to farZ in OpenGL?

Could someone please help me complete this function. Are the parameters sufficient to calculate the 2d position? Pos is already a vector relative to the camera position.

       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); 
       }

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

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

发布评论

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

评论(3

烟燃烟灭 2024-12-16 07:27:35

在我看来,事情是这样的:

    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);
    }

我们在这里所做的只是将向量传递给两个变换矩阵:视图,然后是投影。投影后,您将得到一个 Y 和 X 介于 -1 和 1 之间的向量。我们进行适当的变换以获得真实的像素坐标并返回一个新的 Vector2。请注意,“pos”的 Z 分量还存储函数末尾的屏幕空间中的点的深度。

您需要“视图”矩阵,因为它定义了相机的位置和旋转位置。投影仅定义 3D 空间在 2D 空间上“展平”的方式。

视野不是farZ。投影矩阵有一些参数,其中:

  • 视野,FOV,即水平视角,单位为弧度;
  • 远平面或farZ:这定义了一个点距相机的最大距离;
  • 近平面,nearZ:点距相机的最小距离。

除了数学问题之外,您可以直接使用 Vector2 而不是堆分配(返回指针)。 Vector2 是一个轻量级结构,在这种情况下指针很可能会引起头痛(你要在哪里删除它,等等)。另请注意,我使用了“const”引用,因为除了向量之外,我们不修改它们。对于这个,我们需要一个本地副本,这就是为什么它根本不是参考。

Seems to me it would be something like that:

    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);
    }

What are we doing here is just passing the Vector though the two transformation matrices: the view, then the projection. After the projection you get a vector with Y and X between -1 and 1. We do the appropriate transformation to obtain real pixel coordinates and return a new Vector2. Note that the Z component of 'pos' also store the depth of the point, in the screen space, at the end of the function.

You need the 'view' matrix because it defines where the camera is located and rotated. The projection only defines the way the 3D space is 'flattened' on the 2D space.

A field of view is not the farZ. A projection matrix has some parameters, among them:

  • the field of view, FOV, that is the horizontal angle of view, in radians;
  • the far plane, or farZ : this defines the maximum distance a point can be from the camera;
  • the near plane, nearZ: the minimum distance a point can be from the camera.

Besides the math problem, you may use directly the Vector2 instead of a heap allocation (returning a pointer). Vector2 is a light structure and pointers are very likely to cause headaches in this context (where are you going to delete it, and so on). Also note that I used 'const' references as we do not modify them, except the vector. For this one we want a local copy, this is why it is not a reference at all.

写给空气的情书 2024-12-16 07:27:35

以前的代码仅在不进行任何旋转的情况下才有效(例如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);
}

Previous code only work if you do not do any rotations (for eg. GL.Rotate(rotation_x, 1.0, 0.0, 0.0)).
But if you do here is the code:

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);
}
昇り龍 2024-12-16 07:27:35

我认为您正在寻找的是 gluLookAt 的替代品。给定位置和方向,它将场景几何图形转换为屏幕坐标以进行渲染。正如文章所述,它依赖于 OpenGL 的许多已弃用功能,但它确实提供了一个可以使用矢量/矩阵库实现的代码示例。有关投影矩阵的更多详细信息,请访问此处

一旦你有了投影矩阵,你只需将它应用到你的向量上(将场景的向量后乘以投影矩阵),然后删除结果向量的 Z 分量......也就是说,只需使用得到的向量。

I think what you're looking for is a replacement for gluLookAt. Given a position and orientation it converts the scene geometry into screen coordinates for rendering. As the article says, it relies on a number of deprecated features of OpenGL, but it does provide a code sample you can implement using your vector / matrix library. More detailed information on the projection matrices is available from here.

Once you have the projection matrix you simply apply it to your vectors (post-multiply your scene's vectors by the projection matrix) and then just drop the Z component of the resulting vector ... that is, just use the X and Y components of the resultant vectors.

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