如何从屏幕确定3D空间中的触摸内容?

时间:2010-03-21 16:05:46

标签: android opengl-es

如何在我的OpenGL ES 1.1 android应用程序中使用gl.gluUnproject来确定用户触摸屏幕时选择的内容?

我的理解是触摸事件导致一条线,我必须找到它与之相交的第一个“东西”。

有没有关于如何做到这一点的教程?

4 个答案:

答案 0 :(得分:4)

如果您正在进行2D到3D拾取,则需要稍微调整矩阵和矢量。 OpenGL ES 1.1不存在GlUnproject,所以你必须自己做一些数学运算。

Ray-object intersection是一种可行的方式。蒂姆斯姆斯的回答已经涵盖了其中的一部分,但还有更多。想法是从2D坐标创建射线到3D。为此需要视图矩阵和投影矩阵的逆。一旦你有射线,你可以使用你选择的射线相交测试,当然你需要选择最接近的对象,如Timmmm的点4.边界球和边界框很容易实现,互联网上有很多交叉测试教程。

This picking tutorial适用于DirectX,但您可能会听到这个想法。射线构造部分是最重要的。

修改 Android实现了它自己的gluUnproject版本。它可用于创建射线,通过调用近距离和远距离平面(0和1)并从远距离平面结果中减去近平面结果来获得射线的方向。 Ray起源是视图位置。更多here

答案 1 :(得分:2)

我认为对于大多数应用程序,你应该采用正确的3D方法:光线投射。

获取用户选择的2D屏幕坐标中的位置,并将它们投影到您的世界空间中。这会产生一个3D光线,它来自相机并指向场景。现在您需要在3D中执行碰撞测试。在大多数情况下,这可以通过将对象减少到一组简单的几何形状(例如椭圆体,球体和盒子)来实现,从而实现加速。

鉴于手持设备的精确度,这已经足够精确了。请注意,根据对象的形式,您可能需要使用多个基本原语。另外,总是使用相同的原语是没有意义的:显然,对于很长的棒,边界球是非常糟糕的近似值。

答案 2 :(得分:1)

这完全取决于你渲染的内容。您可能不应该使用拣选方法,因为

a)听起来会很慢,特别是在Android上。 b)您可能希望为小物体设置更大的“触摸区域”,这样您就不必在中精确地触摸它们。 c)它并没有真正回答正确的问题 - 它为您提供了结果“在我触摸的地方,最顶层的图形项目是什么?”而你想知道“用户触摸或触摸附近的游戏实体是什么?”

正如我所说,这完全取决于你的游戏。如果它是2D或近2D游戏,那么它很简单,您只需将触摸坐标输入游戏模型即可。对于3D游戏,我建议我在现场提出这个简单的算法:

  1. 列出可能触及的所有可触摸游戏对象。
  2. 将其中心坐标转换为3D屏幕坐标。 (此处描述的2D屏幕坐标:http://www.flipcode.com/archives/Plotting_A_3D_Point_On_A_2D_Screen.shtml
  3. 找到每个物体的2D距离,丢弃距离大于触摸阈值的物体。
  4. 根据某个距离指标查找最近的对象。你必须在这一点上进行实验,这取决于游戏的本质。
  5. 为了获得精确的结果,可以使用线交叉点。有算法(搜索'平面线交叉光线投射')。

答案 3 :(得分:1)

我有一个想法是缓存调用gluProject的结果。这可能仅在您处理固定相机时才可行。在相机视角的任何变化结束时,我可以重新生成“触摸”的缓存。

这还有一个额外的好处,就是确保我只针对那些会被触及的事物测试输入。

我对这种做法有任何想法感激不尽!