Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/195.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 是否有可能在OpenGL中单击立方体的哪个曲面?_Android_Opengl Es_Coordinate Transformation - Fatal编程技术网

Android 是否有可能在OpenGL中单击立方体的哪个曲面?

Android 是否有可能在OpenGL中单击立方体的哪个曲面?,android,opengl-es,coordinate-transformation,Android,Opengl Es,Coordinate Transformation,我已经创建了一个立方体,它的旋转非常完美。我的任务是你点击哪个旋转立方体。例如,如果你点击立方体表面的红色,我会赢,但我找不到立方体点击的表面视图 已编辑 我想要我接触的地方的表面 以下是我的渲染器代码: public void onDrawFrame(GL10 arg0) { // GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BI

我已经创建了一个立方体,它的旋转非常完美。我的任务是你点击哪个旋转立方体。例如,如果你点击立方体表面的红色,我会赢,但我找不到立方体点击的表面视图

已编辑


我想要我接触的地方的表面

以下是我的渲染器代码:

public void onDrawFrame(GL10 arg0) {
    //              GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    GLES20.glUseProgram(iProgId);

    cubeBuffer.position(0);
    GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, cubeBuffer);
    GLES20.glEnableVertexAttribArray(iPosition);

    texBuffer.position(0);
    GLES20.glVertexAttribPointer(iTexCoords, 3, GLES20.GL_FLOAT, false, 0, texBuffer);
    GLES20.glEnableVertexAttribArray(iTexCoords);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, iTexId);
    GLES20.glUniform1i(iTexLoc, 0);

    // Draw a cube.
    // Translate the cube into the screen.
    Matrix.setIdentityM(m_fIdentity, 0);
    //               Matrix.translateM(m_fIdentity, 0, 0.0f, 0.8f, -3.5f);

    // Set a matrix that contains the current rotation.
    Matrix.setIdentityM(mCurrentRotation, 0);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaX, 1.0f, 0.0f, 0.0f);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaY, 0.0f, 1.0f, 0.0f);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaZ, 0.0f, 0.0f, 1.0f);

    mDeltaX = 0.0f;
    mDeltaY = 0.0f;
    mDeltaZ = 0.0f;

    // Multiply the current rotation by the accumulated rotation, and then set the accumulated
    // rotation to the result.
    Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentRotation, 0, mAccumulatedRotation, 0);
    System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);

    // Rotate the cube taking the overall rotation into account.
    Matrix.multiplyMM(mTemporaryMatrix, 0, m_fIdentity, 0, mAccumulatedRotation, 0);
    System.arraycopy(mTemporaryMatrix, 0, m_fIdentity, 0, 16);

    Matrix.multiplyMM(m_fVPMatrix, 0, m_fViewMatrix, 0, m_fIdentity, 0);
    Matrix.multiplyMM(m_fVPMatrix, 0, m_fProjMatrix, 0, m_fVPMatrix, 0);

    Ray ray = null;
    if (mDeltaX != -99) {
        ray = new Ray(arg0, width, height, mDeltaX, mDeltaY);
    }

    mDeltaX = -99;
    //              Matrix.translateM(m_fVPMatrix, 0, 0, 0, 1);
    GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, m_fVPMatrix, 0);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
    //              GLES20.glDisable(GLES20.GL_TEXTURE_CUBE_MAP);
}

最常见和最现代的方法可能是光线相交

我以为你有很多立方体

  • 通过触摸android屏幕计算光线

  • (每个表面) if(光线与其相交) 在按距离排序的列表中保存曲面和距离

  • 从排序列表中选择最近的曲面

  • 是否有可能在OpenGL中单击立方体的哪个曲面

    在渲染中,场景的每个对象通常通过视图矩阵和投影矩阵进行变换。视图矩阵描述了查看场景的方向和位置,而投影矩阵描述了从场景的三维点到视口的二维点的映射。投影矩阵从视图空间转换到剪辑空间,剪辑空间中的坐标通过除以剪辑坐标的w分量转换为(-1,-1,-1)到(1,1,1)范围内的标准化设备坐标(NDC)。
    如果必须通过在视图端口上选择一个点来找到场景表面上的一个点,则必须找到一种相反的方法。
    识别对象曲面的常用方法是定义具有起点和方向的光线,并找到光线第一次击中的曲面。视线就是这样的光线,因为它有一个起点和一个方向,但如何通过视线定义光线取决于场景的投影类型。

    当在眼睛空间中的坐标被线性映射到标准化设备坐标时,在相机平截头体(一个截断的棱锥体)中的眼睛空间坐标被映射到一个立方体(标准化设备坐标)。
    在这两种情况下,首先必须将视口位置转换为规格化(XY)设备坐标,范围为(-1,-1)到(1,1)。这是一个简单的线性映射:

    w = with of the viewport
    h = height of the viewport
    x = X position of the mouse
    y = Y position ot the mouse
    
    ndc_x = 2.0 * x/w - 1.0;
    ndc_y = 1.0 - 2.0 * y/h; // invert Y axis
    
    在视图空间中的正交投影处定义视线光线

    光线的起点可以通过使用逆投影矩阵,在近平面(z=0)上的标准化设备坐标中变换视口的点来计算

    R0_view = inverse( projection-matrix ) * (ndc_x, ndc_y, 0.0, 1.0)
    
    视线的方向是进入视图端口的方向(0,0,-1)

    在视图空间中的透视投影处定义视线光线

    视线的起点是摄影机位置,在视图空间中为(0,0,0)

    R0_view = (0.0, 0.0, 0.0)
    
    视线的方向可以通过逆投影矩阵在归一化设备坐标中变换光线上的任何点来计算

    D_view = normalize( inverse( projection-matrix ) * (ndc_x, ndc_y, 0.0, 1.0) )
    
    从视图坐标转换为世界坐标 要从视图空间转换到世界空间,必须通过逆视图矩阵变换视图空间坐标

    R0_world = inverse( view-matrix ) * R0_view
    R1_world = inverse( view-matrix ) * (R0_view + D_view)
    D_world  = normalize(R1_world - R0_world)
    
    查找光线与基本体的交点 要查找被光线击中的曲面,必须计算每个曲面(基本体)与光线的交点与光线起点之间的距离。碰撞距离(在光线方向)最小的曲面

    要查找光线与三角形基本体交点的距离,必须执行以下步骤:

  • 找到光线与由三角形基本体的3个点定义的平面的交点
  • 计算交点和光线起点之间的距离
  • 测试交点是否在光线方向(而不是相反方向)
  • 测试交点是在三角形轮廓内还是在三角形轮廓上
  • 找到交点和交点距离:

    平面由范数向量(
    NV
    )和平面上的点(
    P0
    )定义。如果三角形由3个点
    a
    B
    C
    给出,则平面可按如下方式计算:

    P0 = A
    NV = normalize( cross( B-A, C-A ) )
    
    光线与平面的交点通过替换光线的方程式来计算
    P_isect=dist*D+R0
    进入平面方程
    dot(P_isect-P0,NV)=0

    内容如下:

    P_isect    = R0 + D * dist_isect
    dist_isect = dot( P0 - R0, NV ) / dot( D, NV ) 
    
    测试交点是否在光线方向:

    如果“距离”大于或等于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 )
    } 
    

    以下问题的答案对于解决该问题也很有意义:

    请参见WebGL示例,该示例演示了算法:

    glArrayType=typeof Float32Array=“未定义”?Float32Array:(WebGLFloatArray的类型!=“未定义”?WebGLFloatArray:Array);
    函数标识MT44(){
    var m=新的Glarray类型(16);
    m[0]=1;m[1]=0;m[2]=0;m[3]=0;
    m[4]=0;m[5]=1;m[6]=0;m[7]=0;
    m[8]=0;m[9]=0;m[10]=1;m[11]=0;
    m[12]=0;m[13]=0;m[14]=0;m[15]=1;
    返回m;
    };
    函数旋转轴(matA、angRad、轴){
    var-aMap=[[1,2],[2,0],[0,1];
    var a0=aMap[axis][0],a1=aMap[axis][1];
    var sinAng=Math.sin(angRad),cosAng=Math.cos(angRad);
    var matB=新Glarray类型(16);
    对于(var i=0;i<16;++i)matB[i]=matA[i];
    对于(var i=0;i<3;
    
    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 )
    }