屏幕空间到世界空间


10

我正在编写一个2D游戏,其中我的游戏世界的x轴从左到右,y轴从上到下,z轴在屏幕外:

在此处输入图片说明

尽管我的游戏世界是自上而下的,但游戏的渲染却略有倾斜:

在此处输入图片说明

我正在研究从世界空间到屏幕空间的投影,反之亦然。我的前者工作如下:

var viewport = new Viewport(0, 0, this.ScreenWidth, this.ScreenHeight);
var screenPoint = viewport.Project(worldPoint.NegateY(), this.ProjectionMatrix, this.ViewMatrix, this.WorldMatrix);

NegateY()扩展方法不正是它听起来像,因为XNA的Ÿ线延伸自下而上,而不是自上而下。上面的屏幕截图显示了所有工作。基本上,我在3D空间中有一堆点,然后在屏幕空间中进行渲染。我可以实时修改相机属性,并看到它动画到新位置。显然,我的实际游戏将使用精灵而不是点,并且摄影机的位置将被固定,但是我只是在尝试所有数学运算之前。

现在,我正在尝试以另一种方式转换。也就是说,给定上方屏幕空间中的xy点,请确定世界空间中的相应点。因此,如果将光标指向绿色梯形的左下角,则希望获得世界空间读数(0,480)。该ž坐标无关。或者,当映射回世界空间时,z坐标将始终为零。本质上,我想实现此方法签名:

public Vector2 ScreenPointToWorld(Vector2 point)

我已经尝试了几种方法来使它正常工作,但是没有运气。我最近的想法是,我需要调用Viewport.Unproject近两次不同/远ž值,计算得到的Ray,规范它,然后计算出的交点RayPlane,基本上代表了我的世界的地面。但是,我陷入了最后一步,不确定是否使事情变得过于复杂。

谁能为我指出如何实现这一目标的正确方向?

Answers:


4

我认为您的想法很正确!首先使用近平面和远平面作为2D坐标的Z值(即,将0和1用作Z坐标)为光标计算一条射线。这是处理此问题的辅助方法:

public Ray GetScreenRay(Vector2 screenPosition, Viewport viewport, Matrix projectionMatrix, Matrix viewMatrix, Matrix worldMatrix)
{
    Vector3 nearPoint = viewport.Unproject(new Vector3(screenPosition, 0f), projectionMatrix, viewMatrix, worldMatrix);
    Vector3 farPoint = viewport.Unproject(new Vector3(screenPosition, 1f), projectionMatrix, viewMatrix, worldMatrix);
    return new Ray(nearPoint, Vector3.Normalize(farPoint - nearPoint));
}

接下来,您需要有一个Plane与您的实际情况相匹配的实例。最简单的计算方法是使用构造器,该构造器在平面上占据三个点,并从地面对象传递任何三个顶点。如何计算地平面的示例:

Plane groundPlane = new Plane(ground.Vertices[0], ground.Vertices[1], ground.Vertices[2]);

最后用这种方法找到射线与平面之间的交点。您可以使用out result参数来计算相交坐标,如下例所示:

float? result;
mouseRay.Intersects(ref groundPlane, out result);
if(result != null)
    Vector3 worldPoint = mouseRay.Position + mouseRay.Direction * result.Value;

您可能也需要对该NegateY方法做一些事情,但是我不确定在哪里。


这非常有帮助-非常感谢。那是我错过的最后一行。一旦拿到浮标我就不知道该怎么办!我想我必须在游戏积分中
注明

@ user13414确实,该方法的文档很少,并且没有提供如何使用距离返回交点的任何示例。
David Gouveia,2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.