最近在做Android opengl相关的项目, 碰到一个问题, 如何根据用户的手势判断是否点击了某个3d 物体,如果是原生应用, 这个根本就不是问题, 因为Android 系统已经提供给我们view点击回调事件onClickLisenler, opengl 中实现点击某物体的方法为射线拾取(Ray picking)算法.
射线拾取(Ray picking)
OpenGL中射线拾取,就是通过点击屏幕产生的坐标,通过变换到3D坐标空间,然后从摄像机原点与该3D空间坐标产生一个射线(ray),通过该射线与3D世界中的物体做相交检测,即可实现3D物体的拾取。
这个算法主要包换两个步骤:
1. 用户点击手机屏幕的坐标转换成opengl 3D坐标系中的坐标A.
2.坐标A和摄像机原点产生的射线与3d物体做相交检测.
步骤1 Android opengl 库已经提供了相关转换的算法API:
GLU.gluUnProject(float winX, float winY, float winZ, float[] model, int modelOffset, float[] project, int projectOffset, int[] view, int viewOffset, float[] obj, int objOffset)
参数的定义可以参考:https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml
步骤二, opengl 使用点,线, 三角形来构建3d物体, 一般3d 物体都使用三角形来构建, 我们可以把3d物体顶点的坐标看成三角形顶点的集合, 那么只需将3d 物体所有的顶点三角形与步骤一产生的射线做相交检测就行, 更简单的方式是使用3d物体的外接矩形来做相交检测.
做了一个简单的demo实现了Android opengl 的Ray pickig 算法. demo中使用的3d 物体是正方体, 复杂的3d物体使用外交矩形,原理是一样的
点击正方体的任一点,得到的日志:
demo 地址:https://github.com/wxkly8888/Android-Ray-picking-demo
网友评论