3

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

请注意,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)
            );
    }
4

2 回答 2

2

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

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

于 2010-08-20T09:20:05.450 回答
2

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

于 2010-08-22T02:23:02.720 回答