将 3D 点投影到 2D 屏幕坐标 OpenTK [英] Projecting a 3D point to 2D screen coordinate OpenTK

查看:40
本文介绍了将 3D 点投影到 2D 屏幕坐标 OpenTK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Monotouch 和 OpenTK 我试图获得一个 3D 点的屏幕坐标.我设置了我的世界视图投影矩阵,OpenGL 理解它并完美地投影了我的 3D 模型,但是如何使用相同的矩阵将一个点从 2D 投影到 3D?

Using Monotouch and OpenTK I am trying to get the screen coordinate of one 3D point. I have my world view projection matrix set up, and OpenGL makes sense of it and projects my 3D model perfectly, but how to use the same matrix to project just one point from 2D to 3D?

我以为我可以简单地使用:

I thought I could simply use:

Vector3.Transform(ref input3Dpos, ref matWorldViewProjection, out projected2Dpos);

然后在projected2DPos中有投影屏幕坐标.但由此产生的 Vector4 似乎并不代表正确的投影屏幕坐标.我不知道从那以后如何计算它.

Then have the projected screen coordinate in projected2DPos. But the resulting Vector4 does not seem to represent the proper projected screen coordinate. And I do not know how to calculate it from there on.

我发现我需要除以 Vector4.w,但是我仍然得到错误的值.现在使用这个方法:

I found I need to divide by Vector4.w, however I am still getting the wrong values. Using this method now:

private static bool GluProject(OpenTK.Vector3 objPos, OpenTK.Matrix4 matWorldViewProjection, int[] viewport, out OpenTK.Vector3 screenPos)
{
    OpenTK.Vector4 _in;

    _in.X = objPos.X;
    _in.Y = objPos.Y;
    _in.Z = objPos.Z;
    _in.W = 1f;

    Vector4 _out = OpenTK.Vector4.Transform(_in, matWorldViewProjection);

    if (_out.W <= 0.0)
    {
        screenPos = OpenTK.Vector3.Zero;
        return false;
    }

    _out.X /= _out.W;
    _out.Y /= _out.W;
    _out.Z /= _out.W;
    /* Map x, y and z to range 0-1 */
    _out.X = _out.X * 0.5f + 0.5f;
    _out.Y = -_out.Y * 0.5f + 0.5f;
    _out.Z = _out.Z * 0.5f + 0.5f;

    /* Map x,y to viewport */
    _out.X = _out.X * viewport[2] + viewport[0];
    _out.Y = _out.Y * viewport[3] + viewport[1];

    screenPos.X = _out.X;
    screenPos.Y = _out.Y;
    screenPos.Z = _out.Z;

    return true;
}

虽然我看不到任何错误... :S

I cannot see any errors though... :S

推荐答案

您有两个选择.您可以自己计算,也可以使用glProject 函数.我更喜欢第一个.

You have two options. You can calculate it yourself, or use the glProject function. I prefer the first.

数字 1:

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:

public Vector2 form3Dto2D(Vector3 our3DPoint)
{
    Vector3 our2DPoint;

    float[] modelviewMatrix =  new float[16];
    float[] projectionMatrix = new float[16];
    int[] viewport = new int[4];

    GL.GetFloat(GetPName.ModelviewMatrix, modelviewMatrix);
    GL.GetFloat(GetPName.ProjectionMatrix, projectionMatrix);
    GL.GetInteger(GetPName.Viewport, viewport);

    OpenTK.Graphics.Glu.Project(our3DPoint, convertFloatsToDoubles(modelviewMatrix),
        convertFloatsToDoubles(projectionMatrix), viewport, out our2DPoint);

    return new Vector2(our2DPoint.X, our2DPoint.Y)
}   

public static double[] convertFloatsToDoubles(float[] input)
{
    if (input == null)
    {
        return null; // Or throw an exception - your choice
    }

    double[] output = new double[input.Length];
    for (int i = 0; i < input.Length; i++)
    {
        output[i] = input[i];
    }
    return output;
}

这篇关于将 3D 点投影到 2D 屏幕坐标 OpenTK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆