【问题标题】:See what "block" the player is looking at看看玩家在看什么“块”
【发布时间】:2011-08-06 21:38:33
【问题描述】:

我正在创建一个世界由立方体组成的游戏(就像在 Minecraft 中一样),但只有一个小问题我无法解决。我已经创建了世界、玩家、相机移动和旋转(glRotatef 和 glTranslatef)。现在我被困在找出玩家正在看的方块上。

编辑:如果我的问题不够清楚,我不明白如何投射光线以检查与块的碰撞。我正在绘制的所有块都存储在一个 3D 数组中,其中包含块 id(我知道我需要使用八叉树,但我只想让算法工作,优化随之而来)

【问题讨论】:

    标签: opengl 3d camera sdl


    【解决方案1】:

    OpenGL 是一种绘图/渲染 API,而不是某种游戏/图形引擎。你告诉它画东西,它就是这么做的。

    OpenGL 不涵盖您想要的测试,您必须自己实现它们或使用为此设计的一些库。在您的情况下,您想针对视锥体测试世界。玩家看到的确切块可以通过进行射线几何相交测试来找到,即你将一条射线从你的玩家位置投射到玩家看到的方向并测试哪些对象与该射线相交。使用空间细分结构有助于加快速度。在由立方体组成的世界中,最简单和最有效的结构是八叉树,即一个大立方体被细分为包含立方体边缘长度一半的 8 个子立方体。然后这些子立方体被划分等等。

    遍历这样的结构很容易通过递归函数实现 - 不用担心堆栈溢出,因为已经像 10 个细分一样小会产生 2^10^3 = 2^30 sub-sub-...-sub-立方体,需要至少 8GB 的​​数据才能从中构建完整的详细网格。但是10个函数递归层次不是很深。

    【讨论】:

    • 嗯? OpenGL 提供了多种机制来帮助解决这个问题,从弃用的“选择模式”到读取深度缓冲区,再到读取保存对象 ID 的单独属性缓冲区。
    • 嗯,是的,你可以做到这一点。但是您实际上正在做的是以蛮力方法将内容渲染到帧缓冲区,然后读取最终的内容。就我个人而言,我认为 OpenGL 是一个纯粹的绘图 API,根据所需的测试,将光线发送到 CPU 上的场景图更简单,并且比通过整个渲染管道造成的开销更少。尤其是在类似我的世界的环境中,光线→八叉树相交测试非常简单;无论如何,您都必须遍历八叉树进行渲染,但测试光线是否通过八叉树节点所需的工作比渲染该节点要少。
    • OpenGL 实际可以帮助确定位置的确切位置,例如用户用鼠标单击。在某种程度上,确定“用户在哪里看”是同一个问题。然而,通过查看场景图(边界体积),通常可以更有效地识别被拾取/查看的对象。
    • 我同意使用 OpenGL 需要大量额外的不必要的计算。但这是在正常渲染过程中基本上免费完成的额外计算。
    • 使用 OpenGL: 方法 (1): 使用每个块以标识块的颜色来渲染场景。使用 glReadPixels 读取屏幕中心的像素,将获得的像素颜色解释为块 ID。方法(2):渲染场景后读取屏幕中心的像素深度值,通过 gluUnProject 输入,得到读取像素的世界坐标。在这两种情况下,您都必须渲染整个场景 - 或者您事先确定什么是可见的,什么是不可见的(平截头体剔除),但这已经做了你想要的,告诉你看到了什么。这就是为什么我说:不要为此使用 OpenGL。
    【解决方案2】:

    首先想象一个向量,从您的视点到相机的方向,长度等于玩家的“范围”。如果我没记错的话,Minecraft 中的范围大约是 4 个方块(或 4 米)。对于您世界中可能与该矢量相交的每个块(可以像在一个立方体上的 3D 循环一样简单,该立方体由您的到达矢量的最小/最大 x/y/z 值界定)在立方体上投射一条射线(如果它不是空气),看看你是否击中它。 AABB(轴对齐边界框)上的光线投射非常简单,您可以谷歌该算法。现在按距离对结果进行排序,并返回首先击中射线的块。

    【讨论】:

    • 是的。我无法想象从眼睛到相机方向的矢量。那部分我似乎无法理解,然后。我一直在 Google 上搜索 Raycasting,但这让我更加困惑。
    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 2018-12-16
    • 1970-01-01
    相关资源
    最近更新 更多