android - 如何使用近距离和远距离识别 3D 对象内部或外部 3D 对象的点击

标签 android opengl-es opengl-es-2.0 raycasting glsurfaceview

我正在使用 OpenGLES 2.0 和 Android、Java 代码进行 3D 对象渲染。如何使用以下代码识别 3D 对象内部或外部 3D 位置的点击?

public static PointF screenToWorld(float[] viewMatrix,
                                       float[] projMatrix, float screenX, float screenY) {
        float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
        float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);

        Log.d(LOGTAG,"nearPos ->"+nearPos.length+" "+nearPos);
        Log.d(LOGTAG,"farPos ->"+farPos.length+" "+farPos);

        // The click occurred in somewhere on the line between the two points
        // nearPos and farPos. We want to find
        // where that line intersects the plane at z=0
        float distance = nearPos[2] / (nearPos[2] - farPos[2]); // Distance between nearPos and z=0
        float x = nearPos[0] + (farPos[0] - nearPos[0]) * distance;
        float y = nearPos[1] + (farPos[1] - nearPos[0]) * distance;
        return new PointF(x, y);
    }

    private static float[] unProject(float[] viewMatrix,
                                     float[] projMatrix, float screenX, float screenY, float depth) {
        float[] position = {0, 0, 0, 0};
        int[] viewPort = {0, 0, 1, 1};
        GLU.gluUnProject(screenX, screenY, depth, viewMatrix, 0, projMatrix, 0,
                viewPort, 0, position, 0);
        position[0] /= position[3];
        position[1] /= position[3];
        position[2] /= position[3];
        position[3] = 1;
        return position;

    }

最佳答案

How to identify click inside the 3D object or outside 3D objec?

您必须验证是否命中了对象的任何基元。

近平面上的点和远平面上的点定义了一条穿过世界的射线:

float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos  = unProject(viewMatrix, projMatrix, screenX, screenY, 1);

伪代码:

R0 = nearPos
D  = normalize(farPos - nearPos)


找到射线与图元的交点

要找到被射线击中的表面,必须计算每个表面(基元)与射线的交点与射线起点的距离。具有最短距离(在光线方向)的表面被击中。

要找到射线与三角形基元的交点距离,必须执行以下步骤:

  1. 找到射线与由三角形基元的 3 个点定义的平面的交点。
  2. 计算交点与射线起点的距离。
  3. 测试交点是否在射线的方向(不是反方向)
  4. 测试交点是在三角形内还是在三角形上。

求交点和交点距离:

enter image description here

平面由范数向量 (NV) 和平面上的点 (P0) 定义。如果三角形由 PAPBPC 三个点给出,平面可以计算如下:

P0 = PA
NV = normalize( cross( PB-PA, PC-PA ) )

射线与平面的交点是通过代入射线的方程
P_isect = dist * D + R0 转化为平面方程 dot( P_isect - P0, NV ) == 0
如下:

dist_isect = dot( P0 - R0, NV ) / dot( D, NV ) 
P_isect    = R0 + D * dist_isect

测试交点是否在光线方向:

如果 dist_isect 大于或等于 0.0,则交点在射线的方向上。

判断交点是在三角形内还是在三角形上

要找出一个点是否在三角形内,必须测试从角点到交点的线是否在连接到角点的 to 腿之间:

bool PointInOrOn( P1, P2, A, B )
{
    CP1 = cross( B - A, P1 - A )
    CP2 = cross( B - A, P2 - A )
    return dot( CP1, CP2 ) >= 0
}

bool PointInOrOnTriangle( P, A, B, C )
{
    return PointInOrOn( P, A, B, C ) &&
           PointInOrOn( P, B, C, A ) &&
           PointInOrOn( P, C, A, B )
} 


另请参阅:Is it possble get which surface of cube will be click in OpenGL?

关于android - 如何使用近距离和远距离识别 3D 对象内部或外部 3D 对象的点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48048735/

相关文章:

android - 当我按按钮转到“滑动选项卡”菜单时,Android应用程序崩溃

android - 如何在 Android 中与 OpenGL 共享 Renderscript 分配

java - 在 Android Java 中使用 OpenGL 声明要绘制的 Float 数组时出错

ios - CVOpenGLESTextureCacheCreateTextureFromImage 返回错误 6683

Android HTTP GET 参数

android - 失败 [INSTALL_FAILED_UPDATE_INCOMPATIBLE] 即使应用似乎没有安装

android - 谷歌地图未在发布版本中显示

android - Android 设备上的 OpenGL ES 2.0 扩展

android - OpenGL ES 2.0 中 glBlitFrameBuffer() 的替代方案

android - 我可以安全地维护对 GL10 的引用吗?