Android 在OpenGL对象上检测触摸?

Android 在OpenGL对象上检测触摸?,android,Android,我正在开发一个应用程序,它使用OpenGL渲染图像 现在我只想确定opengl sphere对象上的触摸事件,我有drwn 这里我在屏幕上画了4个物体。现在我怎么才能知道哪个物体被击中了 感动。我使用了onTouchEvent()方法。但它只给我x&y坐标,但我的 对象以三维方式绘制 请帮助我,因为我是OpenGL新手 致以最良好的祝愿, ~Anup 在我的项目中,我选择的解决方案是: 将2D屏幕坐标取消投影到穿过场景的虚拟3D线 检测该线与场景对象的可能交点 这是一个相当复杂的尝试。t谷歌IO

我正在开发一个应用程序,它使用OpenGL渲染图像

现在我只想确定opengl sphere对象上的触摸事件,我有drwn

这里我在屏幕上画了4个物体。现在我怎么才能知道哪个物体被击中了

感动。我使用了onTouchEvent()方法。但它只给我x&y坐标,但我的

对象以三维方式绘制

请帮助我,因为我是OpenGL新手

致以最良好的祝愿, ~Anup
在我的项目中,我选择的解决方案是:

  • 将2D屏幕坐标取消投影到穿过场景的虚拟3D线
  • 检测该线与场景对象的可能交点

  • 这是一个相当复杂的尝试。

    t谷歌IO有一个关于OpenGL如何在Android上用于谷歌Body的会议。身体部位的选择是通过在隐藏的缓冲区中使用纯色渲染每个部位来完成的,然后根据触摸屏x、y上的颜色可以找到相应的对象。出于性能目的,触摸点周围只有20x20像素的小裁剪区域以这种方式渲染。

    我只在Direct3D而不是OpenGL ES中进行了此操作,但以下是步骤:

  • 查找模型视图和投影矩阵。OpenGL ES似乎已经取消了检索gluProject()等设置的矩阵的功能。但是您可以使用成员函数来创建这些矩阵,然后使用glLoadMatrix()设置

  • 调用两次,一次使用winZ=0,然后使用winZ=1。传递先前计算的矩阵

  • 这将从每次调用中输出一个3d位置。这对位置定义了OpenGL“世界空间”中的光线

  • 按顺序在每个球体上执行一次。(首先最靠近摄影机,否则您可以选择隐藏在另一个球体后面的球体。)如果检测到交点,则表示您已触摸该球体

  • 这两种方法(1.隐藏颜色缓冲区和2.交集测试)都有自己的优点。 1.隐藏颜色缓冲区:像素读取是一个非常缓慢的操作。 对于一个简单的光线-球体相交测试来说,这无疑是一个过度的杀伤力

  • 光线球体相交测试:这并不难。 下面是Ogre3d中实现的简化版本

    std::pair<bool, m_real> Ray::intersects(const Sphere& sphere) const
     {
    const Ray& ray=*this;
    const vector3& raydir = ray.direction();
    // Adjust ray origin relative to sphere center
    const vector3& rayorig = ray.origin() - sphere.center;
    m_real radius = sphere.radius;
    
    // Mmm, quadratics
    // Build coeffs which can be used with std quadratic solver
    // ie t = (-b +/- sqrt(b*b + 4ac)) / 2a
    m_real a = raydir%raydir;
    m_real b = 2 * rayorig%raydir;
    m_real c = rayorig%rayorig - radius*radius;
    
    // Calc determinant
    m_real d = (b*b) - (4 * a * c);
    if (d < 0)
    {
        // No intersection
        return std::pair<bool, m_real>(false, 0);
    }
    else
    {
        // BTW, if d=0 there is one intersection, if d > 0 there are 2
        // But we only want the closest one, so that's ok, just use the
        // '-' version of the solver
        m_real t = ( -b - sqrt(d) ) / (2 * a);
        if (t < 0)
        t = ( -b + sqrt(d) ) / (2 * a);
        return std::pair<bool, m_real>(true, t);
    }
    
    std::成对光线::相交(常量球体和球体)常量
    {
    const-Ray&Ray=*这个;
    常量向量3&raydir=ray.direction();
    //相对于球体中心调整光线原点
    常量向量3&rayorig=ray.origin()-sphere.center;
    m_实半径=球体半径;
    //嗯,二次曲线
    //构建可与std二次解算器一起使用的系数
    //ie t=(-b+/-sqrt(b*b+4ac))/2a
    m_real a=raydir%raydir;
    m_real b=2*rayorig%raydir;
    m_real c=射线源%rayorig-半径*半径;
    //计算行列式
    m_real d=(b*b)-(4*a*c);
    if(d<0)
    {
    //无交叉路口
    返回std::pair(false,0);
    }
    其他的
    {
    //顺便说一句,如果d=0,则有一个交点,如果d>0,则有两个交点
    //但是我们只想要最接近的一个,所以没关系,只要使用
    //解算器的“-”版本
    m_实t=(-b-sqrt(d))/(2*a);
    if(t<0)
    t=(-b+sqrt(d))/(2*a);
    返回std::pair(true,t);
    }
    
    }


  • 可能还需要计算与光标位置相对应的光线。同样,您可以参考Ogre3d的源代码:搜索getCameraToViewportRay。基本上,您需要视图和投影矩阵从2D位置计算光线(3D位置和3D方向)。

    查找接触点是否在圆内

    public boolean checkInsideCircle(float x,float y, float centerX,float centerY, float Radius)
        {
            if(((x - centerX)*(x - centerX))+((y - centerY)*(y - centerY)) < (Radius*Radius))
                return true;
            else
                return false;
        }
    

    你能给我提供一些更好的代码来描述这一点吗?我不知道我的代码是否适用于你的任务,因为它是C#和特定的OpenGL包装。获取线条的方法是两次取消投影屏幕坐标:从两个不同的虚拟屏幕深度取消投影近和远。GLUT提供了一个基本的非项目函数,可以作为一个模型。我想没有其他方法可以做到这一点。请帮助我。是的,还有另一种技术叫做“拾取”,它将场景渲染到特定的选择缓冲区。但我不熟悉这个。然而,在3D场景中选择对象并不是一项很容易的任务。我认为对于OpenGL ES来说。所以你基本上只剩下非项目方法了。嘿,谢谢你,伙计,你能给我提供任何链接或任何例子吗。帮帮我。作为光线碰撞方法的即兴创作,你必须使用摄影机信息创建光线,你也可以将起点设置为摄影机的当前位置,并使用触摸x计算方向,Y球体表示你有三个圆。?你可以添加3d图像吗…?@CapDroid,我已经添加了图像,想识别图像中显示的这些红色斑点的触摸。嘿,谢谢你的回复,但它不是普通的圆形,而是球体。
    1) centerX,centerY are center point of circle.
    2) Radius is radius of circle.
    3) x,y point of touch..