计算块/面相机/光标在3d块世界中具有焦点

时间:2013-11-30 19:29:13

标签: java 3d

用自我克隆游戏教我自己编程。我有一个无限的地图,加载成16x16x64块的块。

当玩家(相机)四处走动时,相机的中心(游戏光标)指向一个区域。我正在试图弄清楚如何确定用户指向的块。

我的相机有三维坐标,偏航,俯仰,所以我知道用户在哪里。

我已经尝试找到从该原点绘制的“线”上的坐标,但是这并不考虑相机指向块的边缘/角落的时间,系统将无法知道。 / p>

我尝试在网上寻找例子,但我找不到任何有用的东西,只是一些例子,但它们非常错误并且记录不完整。

如何正确转换相机中心正在查看正在查看哪个块/面的位置?

3 个答案:

答案 0 :(得分:3)

  

“我已经尝试找到从该原点绘制的”线“上的坐标,但这并不考虑相机指向块的边缘/角落的时间,系统将无法知道。 “ ..“我怎样才能正确地转换到相机中心正在查看它正在看哪个块/面的位置?”

OpenGL程序执行鼠标拾取的两种常用方法是颜色选择光线投射。听起来你正试图迭代你的块网格来获得有点不寻常的位置,或者想做一些像光线投射这样的事情。

光线投射已完成from the camera -> through the mouse -> onto a plane on the screen -> map screen space to world space -> collide with scene

  

“我尝试过在网上寻找示例,但我找不到任何有用的东西,只是一些例子,但它们非常错误并且文档记录很差。”

以下是一些光线投射教程one with maths and diagramsone with some code examplesand another的链接。

注意如果您发现任何较旧的OpenGL教程,他们可能会提到“选择模式”“名称堆栈”这是真的旧的,不要使用它 - OpenGL wiki

答案 1 :(得分:1)

有一个名为CraftMania的Minecraft类型克隆,它是https://github.com/mcourteaux/CraftMania

的开源

可能有一些关于3D拾取的文档信息。

答案 2 :(得分:0)

首先,关于相机高度问题的注意事项:确保保持相机位置并指向ModelView矩阵而不是Projection矩阵。 Projection矩阵仅用于补偿人眼相对于真实屏幕(视锥体)的影响。 “缩放”是一个棘手的主题。

上一个答案的链接显示了如何从相机获取视线矢量,查看模型空间(屏幕中心或十字线)。

调用此视线矢量l。它应该是一个单位列向量,以与块相同的坐标系表示。 在偏航(h为航向)和俯仰(p)方面,如果+ y为向上,0偏航有-z向前和x向右,则l的(x,y,z)分量为:l =(cp) * sh,sp,-cp * ch),其中cp是cos(音高),sh是sin(yaw = heading)等。

我们希望相机前面的最近的立方体有任何面朝向来自相机的光线穿过l方向。

在每一步,您都要排除要考虑的多维数据集,以节省吞吐量。 OpenGL有一种方法可以判断一个基元(例如三角形)是否写入深度缓冲区(可见)。如果你愿意,你可以渲染两次,并注意在第二遍中在* - 或 - 等规则下写入深度缓冲区的立方体,并且只考虑那些立方体。如果没有,你可以跳过它,只考虑所有立方体。

如果您没有选择有限数量的16x16x64块,您可以考虑使用大型立方块块(例如16 ^ 3)作为整体进行整体拒绝,使用下面的粗块方法对于单个块,接受门槛由例如按比例放大16。

假设立方体是2x2x2单位(中心的角+ x,y,z的+/- 1)。 相机“眼睛”位于e位置。 对于每个立方体,中心位于c,计算眼睛的位移:d = c - e。 计算距离方向l:u = d dot l。 (即u = dx * lx + dy * ly + dz * lz。) 如果你<那么丢弃这个立方体-1.5(立方体完全在相机后面)。 从射线计算立方体中心的垂直位移矢量:p = d - u * l。

粗略检查: 如果p的分量的绝对值之和> 1,则丢弃立方体。 3。 这是一个快速检查,将消除除了视线之外非常接近的立方体 将所有剩余的立方体按最小到最大的顺序排序。
第一个通过以下详细检查获胜。

详细检查: 在处理任何多维数据集之前,首先必须根据l向量做一些准备: 指定所有立方体通用的8个角顶点数和位置向量,如下所示:

no  x  y  z
1   1  1  1
2   1 -1  1
3   1 -1 -1
4   1  1 -1
5  -1  1  1
6  -1 -1  1
7  -1 -1 -1
8  -1  1 -1

接下来,根据l的x,y,z分量的符号,选择形成精确碰撞的二维凸包的4或6个顶点,如眼睛所见:

xyz Vertices (cyclic)
+++ 234856
--- 658432 (reverse order of +++)
++- 123785 (6->1, 4->7) of +++
--+ 587321 reverse order of ++-
+-+ 156734
-+- 437651 reverse of +-+
-++ 148762
+-- 267841 reverse of -++

退化情况,当l的x,y或z分量中的任何2个为零时:

+00 1234
-00 4321
0+0 1485
0-0 5841
00+ 1562
00- 2651

根据您的视线l矢量,选择上述14个船体中的一个,一次。然后对每个剩余的范围排序多维数据集执行以下详细测试。 现在,对于光线在此船体内,意味着立方体的至少一个面被刺穿(或至少被擦过),光线必须位于由后续的船体顶点对指定的每个线段的左侧(我们绕逆时针方向绕船体进行6或4次检查。这与要求船体段的叉积从该段的任一端到射线的位移具有负或零投影到视线矢量l的情况相同: 从左到右成对地取船体顶点,并从最后到第一个环绕,最左边的顶点指定为“a”,右边的顶点指定为“b”, ((b - a) cross (p - a)) dot l <= 0.(与上面相同的“p”,p = d - u * l.p可以从上面存储,或者在此重新计算。) 第一个立方体,从最近到最远的顺序,从船体的所有4或6个线段通过这个测试是玩家面前的立方体。可以预先计算四个或六个(b-a)向量(一次)。 您还可以为退化情况提出4个顶点集合,其中只有l的一个分量为零,但这是可选的,与l的两个分量为零的情况不同,其中您必须只使用4个顶点。 / p>

这些都是纸上谈兵,未经过编码或测试。