c# - 简单的 OpenTK 光线投射
问题描述
好吧,我不知道你是否可以完全考虑它是光线投射,但我基本上是想找到我的 2d 网格上的哪个图块被悬停在上面,这样我就可以在那里放置一个对象。
该解决方案应该只拾取电网,而不是电网上的建筑物。建筑物突出显示将基于建筑物占用的任何瓷砖是否被悬停。
我正在努力实现的一个很好的例子是像异星工厂一样的建筑系统。
编辑:网格是一个包含所有瓷砖信息的二维数组。世界中的瓦片都是 2 个三角形(由顶点数组和索引数组组成)。相机是透视相机(如果 Factorio 使用 Orthographic,如果它使事情变得更简单,我可以切换到它)。
编辑 2:该数组包含一个名为 TileInformation 的类,它有一些与图块包含的内容等相关的内容。瓦片大小为 1x1,阵列为 256x256。(会有多个可以单独更新的网格块。)所有瓦片都在一个网格中,位置表示为 int's (坐标系是正的和负的。)
解决方案
你的问题还不够清楚,但我会做一些假设,希望它们符合你的情况。
首先,我们需要一个代表 3D 空间中 2D 鼠标位置的拾取射线。为此,我们首先将鼠标位置从像素坐标转换为介于 -1 和 1 之间的标准化设备坐标:
mouseNDCX = 2 * mousePixelX / viewportWidth - 1
mouseNDCY = 1 - 2 * mousePixelY / viewportHeight
然后,我们找到了射线。为此,我们需要您的相机的视图投影矩阵。然后:
mouseNear = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 0, 1)
mouseFar = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 1, 1)
这将为您提供拾取射线上的两个位置。一个在 z-near 平面上,一个在 z-far 平面上。不要忘记做透视划分:
mouseNear = (1 / mouseNear.w) * mouseNear
mouseFar = (1 / mouseFar.w) * mouseFar
下一步是计算与网格的交点。这是您的问题严重低估的地方。我假设网格位于与其中一个主平面平行的平面上。在下文中,这将是 xy 平面。如果您有不同的平面,则需要更换相应的组件。我将进一步假设网格位于 height z
。
现在,我们要找到交点,即:
((1 - t) * mouseNear + t * mouseFar).z = z
<=> mouseNear.z + t * (mouseFar.z - mouseNear.z) = z
<=> t = (z - mouseNear.z) / (mouseFar.z - mouseNear.z)
这让我们可以计算交点:
intersection = (1 - t) * mouseNear + t * mouseFar
该交点位于网格平面上。最后,我们需要找到图块索引。为此,我们只需要考虑 x 和 y 分量。假设您的网格原点位于o
并且图块具有 size s
,则图块索引为:
i = floor((intersection.x - o.x) / s)
j = floor((intersection.y - o.y) / s)
推荐阅读
- javascript - React.js 拼接从数组列表中删除错误的项目
- python - 当我尝试在 django 中进行迁移时,出现未定义的 DJANGO_SETTINGS_MODULE 错误
- android - 从 Glide 获取链接以稍后将其用作资源
- javascript - 如何将带有子查询的 SQL 查询解析到字段中?
- f# - 是否可以在内部类型上有一个 F# 运算符重载,可用于程序集中的所有文件?
- java - 动态保存活动当前布局
- mysql - 如何比较当前时间与 26/09/2018 04:10 AM
- wpf - 我的 DLL 中的虚拟 MouseButtonEventHandler 被调用应用程序覆盖
- mysql - talend中的MySQL连接失败
- c# - System.UnauthorizedAccessException:访问路径被拒绝-Xamarin