OpenGL ES (MonoTouch) - 手动实现 gluUnProject 的挣扎

发布于 2024-11-01 18:58:34 字数 1531 浏览 5 评论 0原文

我在其他地方看到过同样的主题,但在大多数情况下,解决方案提供商正在处理 2D(正交)投影,因此他们掩盖了 Z 值。我的世界具有以下特征:

  1. 透视投影
  2. 相机的“向上”矢量始终为 {0, 1, 0}
  3. 相机的 Z 坐标始终为正(朝 Z=0 方向看)
  4. 我尝试确定击中点的平面是Z=0

我正在使用 gluUnProject 的端口,虽然我认为我的端口实现是合理的,但肯定可能有问题。不过,我希望向社区询问的是我下面的算法是否正确。我正在确定 winZ=0(近平面)和 winZ=1(远平面)的世界坐标。然后,我从这两点确定光线,对其进行归一化,并确定该光线的 Z 坐标在什么值“t”时将为 0(在什么点与 Z=0 平面相交,这就是我所追求的) 。然而,问题是,当我在原点 (0,0,0) 附近单击时,此方法有效,但一旦我开始远离原点单击,错误就会增大(例如,如果正确的世界坐标应该 是 50, 0, 0 根据下面的计算,它们实际上是 85, 0, 0

如果下面的过程是合理的,那么我可以开始研究我的 gluUnProject 的实现。

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    var pt = (touches.AnyObject as UITouch).LocationInView(this);

    int[] viewport = new int[4];
    float[] proj = new float[16];
    float[] model = new float[16];

    GL.GetInteger(All.Viewport, viewport);
    GL.GetFloat(All.ProjectionMatrix, proj);
    GL.GetFloat(All.ModelviewMatrix, model);

    float[] near = new float[3];
    float[] far = new float[3];

    Utils.gluUnProjectf(pt.X, viewport[3] - pt.Y, 0f, model, proj, viewport, out near);
    Utils.gluUnProjectf(pt.X, viewport[3] - pt.Y, 1f, model, proj, viewport, out far);

    Vector rayDirection = new Vector(far[0] - near[0], far[1] - near[1], far[2] - near[2]);
    rayDirection.Normalize();

    float t = (0 - near[2]) / rayDirection.dZ;

    Vertex end = new Vertex();
    end.X = near[0] + rayDirection.dX * t;
    end.Y = near[1] + rayDirection.dY * t;
    end.Z = 0;
}

I've seen this same topic discussed elsewhere, but in most cases the solution provider is dealing with a 2D (ortho) projection and so they gloss over the Z value. My world has the following characteristics:

  1. Perspective projection
  2. Camera's "up" vector is always {0, 1, 0}
  3. The camera's Z coordinate is always positive (looking toward Z=0)
  4. The plane on which I am trying to determine a hit point is Z=0

I'm using a port of gluUnProject, and while I think my implementation of the port is sound, there could certainly be something wrong with that. What I was hoping to ask the community, though, is if my algorithm below looks correct. I'm determining the world coords at winZ=0 (near plane) and at winZ=1 (far plane). I'm then determining the ray from these two points, normalizing this, and determining at what value 't' this ray's Z coordinate will be 0 (at what point it intersections the Z=0 plane, which is what I'm after). The problem, however, is as I click near the origin (0,0,0) this works, but as soon as I start clicking away from the origin, the error grows (e.g. if the correct world coords should be 50, 0, 0 they are actually 85, 0, 0 based on the computations below.

If this procedure below is sound, then I can begin investigating my implementation of gluUnProject.

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    var pt = (touches.AnyObject as UITouch).LocationInView(this);

    int[] viewport = new int[4];
    float[] proj = new float[16];
    float[] model = new float[16];

    GL.GetInteger(All.Viewport, viewport);
    GL.GetFloat(All.ProjectionMatrix, proj);
    GL.GetFloat(All.ModelviewMatrix, model);

    float[] near = new float[3];
    float[] far = new float[3];

    Utils.gluUnProjectf(pt.X, viewport[3] - pt.Y, 0f, model, proj, viewport, out near);
    Utils.gluUnProjectf(pt.X, viewport[3] - pt.Y, 1f, model, proj, viewport, out far);

    Vector rayDirection = new Vector(far[0] - near[0], far[1] - near[1], far[2] - near[2]);
    rayDirection.Normalize();

    float t = (0 - near[2]) / rayDirection.dZ;

    Vertex end = new Vertex();
    end.X = near[0] + rayDirection.dX * t;
    end.Y = near[1] + rayDirection.dY * t;
    end.Z = 0;
}

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

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

发布评论

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

评论(1

哥,最终变帅啦 2024-11-08 18:58:34

我使用完整版本的 OpenGL(使用 gluUnProject 完成)实现了相同的算法,并得到了所需的结果。该算法是健全的,但我的 gluUnProject 实现却不然。

I implemented the same algorithm with a full version of OpenGL (complete with gluUnProject) and got the desired result. The algorithm is sound, my implementation of gluUnProject is not.

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