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

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

问题描述

使用MonoTouch的和OpenTK我想获得一个三维点的屏幕坐标。我有我的世界观投影矩阵设置,和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似乎不重新present适当投射屏幕坐标。我不知道如何从那里计算。

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

我看不到任何错误,但...:•

I cannot see any errors though... :S

推荐答案

您有两种选择。您可以自己进行计算,或者使用 glProject 功能。我preFER第一。

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天全站免登陆