我的项目和非项目功能有什么问题?

发布于 2024-09-15 09:15:52 字数 1833 浏览 11 评论 0原文

我在 C# 游戏中使用 OpenTK,它没有提供在世界坐标和屏幕坐标之间转换的项目和取消项目功能。嗯,确实如此,但它们已被弃用,我无法让它们工作。我尝试根据 opengl 规范 自己实现它们(请参阅左手菜单、gluProject 和 gluUnProject,并在 FF 中查看,而不是 Chrome)。看看那些公式,我正在尝试匹配它们。我的功能根本不起作用,项目返回的点都靠近屏幕中心,并且非常靠近,即使我正在到处移动我的世界点。

请注意,OpenTK 的数学库不包含矩阵与向量相乘的函数,因此我只是对结果向量中的每个条目进行矩阵逐向量点积(这是正确的,不是吗?)

    public static Vector3d Project(Vector4d point, Matrix4d projection, Matrix4d modelview, int[] view)
    {
        Matrix4d temp = Matrix4d.Mult(projection, modelview);
        // multiply matrix by vector
        Vector4d v_prime = new Vector4d(
            Vector4d.Dot(temp.Row0, point),
            Vector4d.Dot(temp.Row1, point),
            Vector4d.Dot(temp.Row2, point),
            Vector4d.Dot(temp.Row3, point)
            );

        v_prime = Vector4d.Divide(v_prime, v_prime.W);

        return new Vector3d(
            view[0] + view[2] * (v_prime.X + 1) / 2,
            view[1] + view[3] * (v_prime.Y + 1) / 2,
            (v_prime.Z + 1) / 2
            );
    }

    public static Vector3d UnProject(Vector3d window, Matrix4d modelview, Matrix4d projection, int[] view)
    {
        Matrix4d inv = Matrix4d.Mult(projection, modelview);
        inv.Invert();

        double vx = (2 * (window.X - view[0])) / view[2] - 1;
        double vy = (2 * (window.Y - view[1])) / view[3] - 1;
        double vz = (2 * window.Z) - 1;

        Vector4d vect = new Vector4d(vx, vy, vz, 1);

        // now multiply matrix times vector, which is really row (dot) vector for each value
        // correct, the bottom row of the inv matrix is unused
        return new Vector3d(
            Vector4d.Dot(inv.Row0, vect),
            Vector4d.Dot(inv.Row1, vect),
            Vector4d.Dot(inv.Row2, vect)
            );
    }

I'm using OpenTK for a game in C#, and it doesn't come with the project and unproject functions, which convert between world and screen coordinates. Well, it does, but they're deprecated and I couldn't get them to work. I took a shot at implementing them myself based on the opengl spec (see left hand menu, gluProject and gluUnProject, and view in FF, not Chrome). See those formulas, I'm trying to match them. My functions aren't working at all, the points that Project returns are all near the center of my screen, and very close together, even though I'm moving my world point all over the place.

Note that OpenTK's math lib doesn't include functions for multiplying a matrix by a vector, so I just did matrix row by vector dot products for each entry in the resulting vector (that's correct, isn't it?)

    public static Vector3d Project(Vector4d point, Matrix4d projection, Matrix4d modelview, int[] view)
    {
        Matrix4d temp = Matrix4d.Mult(projection, modelview);
        // multiply matrix by vector
        Vector4d v_prime = new Vector4d(
            Vector4d.Dot(temp.Row0, point),
            Vector4d.Dot(temp.Row1, point),
            Vector4d.Dot(temp.Row2, point),
            Vector4d.Dot(temp.Row3, point)
            );

        v_prime = Vector4d.Divide(v_prime, v_prime.W);

        return new Vector3d(
            view[0] + view[2] * (v_prime.X + 1) / 2,
            view[1] + view[3] * (v_prime.Y + 1) / 2,
            (v_prime.Z + 1) / 2
            );
    }

    public static Vector3d UnProject(Vector3d window, Matrix4d modelview, Matrix4d projection, int[] view)
    {
        Matrix4d inv = Matrix4d.Mult(projection, modelview);
        inv.Invert();

        double vx = (2 * (window.X - view[0])) / view[2] - 1;
        double vy = (2 * (window.Y - view[1])) / view[3] - 1;
        double vz = (2 * window.Z) - 1;

        Vector4d vect = new Vector4d(vx, vy, vz, 1);

        // now multiply matrix times vector, which is really row (dot) vector for each value
        // correct, the bottom row of the inv matrix is unused
        return new Vector3d(
            Vector4d.Dot(inv.Row0, vect),
            Vector4d.Dot(inv.Row1, vect),
            Vector4d.Dot(inv.Row2, vect)
            );
    }

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

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

发布评论

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

评论(2

紫南 2024-09-22 09:15:52

我不完全确定,但至少 Project 函数中矩阵乘法的顺序可能是错误的。查看 http://www.opengl.org/wiki/GluProject_and_gluUnProject_code 了解 C 代码,其中临时向量(代码中的 v_prime)是通过首先与模型视图矩阵相乘来计算的,然后将结果依次与投影矩阵相乘。

寻找 gluProject/gluUnProject 实现的另一个好来源是 http ://www.mesa3d.org/

I'm not entirely sure, but at least the order of the matrix multiplications in your Project function might be wrong. Take a look at http://www.opengl.org/wiki/GluProject_and_gluUnProject_code for C code, where the temporary vector (v_prime in your code) is calculated by multiplying with the modelview matrix first and the result is then in turn multiplied with the projection matrix.

Another good source to look for a gluProject/gluUnProject implementation is http://www.mesa3d.org/.

小忆控 2024-09-22 09:15:52

我想通了 - 我的矩阵需要转置。不知道为什么,但 OpenTK 函数返回的模型矩阵与本机调用不同。

I figured it out - my matrices needed to be transposed. Don't know why, but the OpenTK functions gave my model matrices back differently than the native calls.

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