2012-05-07 124 views
2

我正在使用XNA 4.0并尝试将Vector3变成Vector2,它代表其在屏幕上的坐标。 我知道你可以使用Viewport.Project,这给了我完美的结果,但我需要为此做出自己的方法。 我必须将每个顶点转换为2D帧,而不是GPU。 使用提供的Project方法比我想要的慢一点。 它也会返回一个“z”值,我甚至不会使用它。我只想以最简单的方式返回(x,y)。将3D矢量投影到2D屏幕坐标

这是我到目前为止提出的,它给出了几乎正确的结果。但还没有应用

private Vector2 ScreenCoords(Vector3 v) 
    { 
     return new Vector2(
      viewProj.M11 * v.X + viewProj.M21 * v.Y + viewProj.M31 * v.Z + viewProj.M41, 
      viewProj.M12 * v.X + viewProj.M22 * v.Y + viewProj.M32 * v.Z + viewProj.M42); 
    } 

viewProj只是(viewMatrix * ProjectionMatrix)

在屏幕中心的一个顶点,似乎随时回来为(0,0),但我会略微搞砸结果作为顶点改变屏幕坐标(当我移动相机时) 随着顶点向左移动,我的投影结果的X减小,并且随着顶点向下移动,我的预测结果的Y增加。 所以至少我有这个权利,但他们改变的速度是不正确的或一致的。

编辑:这里是它是如何做,可能做它的最快的方法(注意,这个返回的坐标范围为[-1,1])

private Vector2 ScreenCoords(Vector3 v) 
    { 
     float 
      w = viewProj.M14 * v.X + viewProj.M24 * v.Y + viewProj.M34 * v.Z + viewProj.M44; 
     return new Vector2(
      (viewProj.M11 * v.X + viewProj.M21 * v.Y + viewProj.M31 * v.Z + viewProj.M41)/w, 
      (viewProj.M12 * v.X + viewProj.M22 * v.Y + viewProj.M32 * v.Z + viewProj.M42)/w);   
    } 

下面是使用视口的比较。项目获得二维坐标 -
的FPS项目 - 81
的FPS ScreenCoords - 143
FPS没有任何一个 - 152
因此,我建议这样的事情对于别人谁在做每帧投射的手。

回答

2

你应该认识到透视投影需要齐次坐标,则应该由homegeneus因素划分

部件W

这是数学:

Vector4 position = new Vector4(pos3, 1); 
Vector4.Transform(ref position, ref worldViewProjection, out position); 
position /= position.W; 

您也可以找到更多信息在这里:http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection

+0

这让我感谢我! 我试图避免使用变换和项目等东西,并用我自己的数学得到答案,但这让我在那里。 在任何人想要的时候发布新的方法。 – Frobot

+0

很好地知道背后的数学是什么,但我认为这种变换在着色器内部更有效率。 – Blau

+0

是的,变换也获得了Z缓冲区中该像素的值,这是我剪掉的部分,因为我不需要它。 希望我可以在着色器中实现我的整个算法,然后我甚至不需要在CPU上找到2D屏幕坐标,它会快得多 – Frobot