OpenGL ES(iPhone)Touch Picking [英] OpenGL ES (iPhone) Touch Picking

查看:133
本文介绍了OpenGL ES(iPhone)Touch Picking的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望在ES中进行经典的OpenGL鼠标选择。我不想使用第三方库,GLU端口和OpenGL名称栈等。这几乎离开了逆视图变换和光线交叉,对吗?

Looking to do classic OpenGL mouse picking in ES. I'd prefer not to use third party libs, GLU ports and OpenGL name stacks, etc, are out. This pretty much leaves inverse view transformation and ray intersection, correct?

我在以下的帮助下已经相当远:
http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/MousePicking
http://eigenclass.blogspot.com/ 2008/10 / opengl-es-picking-using-ray-boundingbox.html

I've gotten pretty far with the help of: http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/MousePicking http://eigenclass.blogspot.com/2008/10/opengl-es-picking-using-ray-boundingbox.html

。 。但我还没有。这也是一个方便的方式!

. . .but I'm not there yet. This also reeks of THERE MUST BE AN EASIER WAY!!

这是一些代码:

    -(void)handleTouch:(CGPoint)point {
    GLfloat width = backingWidth;
    GLfloat height = backingHeight;
    GLfloat x = point.x;
    GLfloat y = point.y;
    GLfloat z = 0.0f;

    //viewport -> normalized dev coord -> clip
    GLfloat n[] = {
        2 * x / width - 1,
        2 * y / height,
        2 * z - 1,
        1
    };

    float fov = 45.0f * (M_PI / 180.0f);
    float near = 0.01, far = 10.0f;
    float aspect = (float)backingWidth / (float)backingHeight;
    float top = tan(fov) * near;
    //float bottom = -top;
    //float left = aspect * bottom;
    float right = aspect * top;

    //I'm a viewing volume symmetric projection matrix
    GLfloat P[] = {
        near / right, 0, 0, 0,
        0, near / top, 0, 0,
        0, 0, -(far + near) / (far - near), (-2 * far * near) / (far - near),
        0, 0, -1, 0
    };

    GLfloat Pminus1[] = {
        1/P[0], 0, 0, 0,
        0, 1/P[5], 0, 0,
        0, 0, 0, 1/P[14],
        0, 0, 1/P[11], -(P[10]/ (P[11]*P[14]))
    };

    //clip -> view
    GLfloat v[] = {
        Pminus1[0] * n[0] + Pminus1[1] * n[1] + Pminus1[2] * n[2] + Pminus1[3] * n[3],
        Pminus1[4] * n[0] + Pminus1[5] * n[1] + Pminus1[6] * n[2] + Pminus1[7] * n[3],
        Pminus1[8] * n[0] + Pminus1[9] * n[1] + Pminus1[10] * n[2] + Pminus1[11] * n[3],
        Pminus1[12] * n[0] + Pminus1[13] * n[1] + Pminus1[14] * n[2] + Pminus1[15] * n[3]
    };

    //view -> world
    GLfloat Rt[] = {
        mv[0], mv[4], mv[8],
        mv[1], mv[5], mv[9],
        mv[2], mv[6], mv[10]
    };

    GLfloat tPrime[] = {
        Rt[0] * mv[3] + Rt[1] * mv[7] + Rt[2] * mv[11],
        Rt[3] * mv[3] + Rt[4] * mv[7] + Rt[5] * mv[11],
        Rt[6] * mv[3] + Rt[7] * mv[7] + Rt[8] * mv[11]
    };

    GLfloat Mminus1[] = {
        Rt[0], Rt[1], Rt[2], -(tPrime[0]),
        Rt[3], Rt[4], Rt[5], -(tPrime[1]),
        Rt[6], Rt[7], Rt[8], -(tPrime[2]),
        0, 0, 0, 1
    };

    //point in world space
    GLfloat w[] = {
        Mminus1[0] * v[0] + Mminus1[1] * v[1] + Mminus1[2] * v[2] + Mminus1[3] * v[3],
        Mminus1[4] * v[0] + Mminus1[5] * v[1] + Mminus1[6] * v[2] + Mminus1[7] * v[3],
        Mminus1[8] * v[0] + Mminus1[9] * v[1] + Mminus1[10] * v[2] + Mminus1[11] * v[3],
        Mminus1[12] * v[0] + Mminus1[13] * v[1] + Mminus1[14] * v[2] + Mminus1[15] * v[3]
    };

    //r = a + t(w - a)
    GLfloat a[] = {0.0f, -0.1f, 0.0f};
    GLfloat wminusa[] = {w[0] - a[0], w[1] - a[1], w[2] - a[2]};

    vector[0] = a[0];
    vector[1] = a[1],
    vector[2] = a[2];
    vector[3] = w[0];
    vector[4] = w[1];
    vector[5] = -10.0f;

    //3 non-colinear points on the plane 
    GLfloat p1[] = {rect.origin.x, rect.origin.y, 0};
    GLfloat p2[] = {rect.origin.x + rect.size.width, rect.origin.y, 0};
    GLfloat p3[] = {rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, 0};

    //location plane normal vector, Ax + By + Cz + D = 0
    GLfloat lp[] = {
        p1[1] * (p2[2] - p3[2]) + p2[1] * (p3[2] - p1[2]) + p3[1] * (p1[2] - p2[2]),
        p1[2] * (p2[0] - p3[0]) + p2[2] * (p3[0] - p1[0]) + p3[2] * (p1[0] - p2[0]),
        p1[0] * (p2[1] - p3[1]) + p2[0] * (p3[1] - p1[1]) + p3[0] * (p1[1] - p2[1]),
        -(p1[0] * (((p2[1] * p3[2]) - (p3[1] * p2[2]))) + p2[0] * (((p3[1] * p1[2]) - (p1[1] * p3[2]))) + p3[0] * (((p1[1] * p2[2]) - (p2[1] * p1[2]))))
    };

    GLfloat PnRd = (lp[0] * wminusa[0]) + (lp[1] * wminusa[1]) + (lp[2] * wminusa[2]);
    if(PnRd != 0) {
        GLfloat PnR0D = -((lp[0] * a[0]) + (lp[1] * a[1]) + (lp[2] * a[2]) + lp[3]);
        if(PnR0D != 0) {
            GLfloat t = PnR0D / PnRd;
            if(t >= 0) {
                GLfloat p[] = {
                    a[0] + wminusa[0] * t,
                    a[1] + wminusa[1] * t,
                    a[2] + wminusa[2] * t
                };
                if(p[0] > rect.origin.x &&
                   p[0] < rect.origin.x + rect.size.width &&
                   p[1] > rect.origin.y &&
                   p[1] < rect.origin.y + rect.size.height)
                    NSLog(@"BOOM!!!");
            }
        }
    }
}


推荐答案

好吧,好吧那还是有点儿马车。以下是MOSTLY现在正在做的事情:

Okay, okay that was still a bit buggy. Here is what is MOSTLY working now:

-(void)view2WorldPoint:(CGPoint)point :(GLfloat*)worldPoint {
    float clickX = point.x;
    float clickY = point.y;
    float clickZ = -near;

    //viewport -> normalized device coord -> clip
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    GLfloat n[] = {
        (clickX - (float)viewport[0]) / (float)viewport[2] * 2.0 - 1.0,
        -((clickY - (float)viewport[1]) / (float)viewport[3] * 2.0 - 1.0),
        2.0 * clickZ - 1.0,
        1.0
    };

    GLfloat MP[16], MPInv[16];
    MatMatMultiply(MP, projMat, modelMat);
    GenerateInverseMatrix4f(MPInv, MP); // replace this one with the whole 1/p thang?

    GLfloat w[] = {
        (MPInv[0]  * n[0]) + (MPInv[4]  * n[1]) + (MPInv[8]  * n[2]) + (MPInv[12] * n[3]),
        (MPInv[1]  * n[0]) + (MPInv[5]  * n[1]) + (MPInv[9]  * n[2]) + (MPInv[13] * n[3]),
        (MPInv[2]  * n[0]) + (MPInv[6]  * n[1]) + (MPInv[10] * n[2]) + (MPInv[14] * n[3]),
        (MPInv[3]  * n[0]) + (MPInv[7]  * n[1]) + (MPInv[11] * n[2]) + (MPInv[15] * n[3])
    };

    worldPoint[0] = w[0] / w[3];
    worldPoint[1] = w[1] / w[3];
    worldPoint[2] = w[2] / w[3];
}


float Determinant4f(const float m[16])
{
    return
    m[12]*m[9]*m[6]*m[3]-
    m[8]*m[13]*m[6]*m[3]-
    m[12]*m[5]*m[10]*m[3]+
    m[4]*m[13]*m[10]*m[3]+
    m[8]*m[5]*m[14]*m[3]-
    m[4]*m[9]*m[14]*m[3]-
    m[12]*m[9]*m[2]*m[7]+
    m[8]*m[13]*m[2]*m[7]+
    m[12]*m[1]*m[10]*m[7]-
    m[0]*m[13]*m[10]*m[7]-
    m[8]*m[1]*m[14]*m[7]+
    m[0]*m[9]*m[14]*m[7]+
    m[12]*m[5]*m[2]*m[11]-
    m[4]*m[13]*m[2]*m[11]-
    m[12]*m[1]*m[6]*m[11]+
    m[0]*m[13]*m[6]*m[11]+
    m[4]*m[1]*m[14]*m[11]-
    m[0]*m[5]*m[14]*m[11]-
    m[8]*m[5]*m[2]*m[15]+
    m[4]*m[9]*m[2]*m[15]+
    m[8]*m[1]*m[6]*m[15]-
    m[0]*m[9]*m[6]*m[15]-
    m[4]*m[1]*m[10]*m[15]+
    m[0]*m[5]*m[10]*m[15];
}

BOOL GenerateInverseMatrix4f(float i[16], const float m[16])
{
    float x=Determinant4f(m);
    if (x==0) return FALSE;

    i[0]= (-m[13]*m[10]*m[7] +m[9]*m[14]*m[7] +m[13]*m[6]*m[11]
           -m[5]*m[14]*m[11] -m[9]*m[6]*m[15] +m[5]*m[10]*m[15])/x;
    i[4]= ( m[12]*m[10]*m[7] -m[8]*m[14]*m[7] -m[12]*m[6]*m[11]
           +m[4]*m[14]*m[11] +m[8]*m[6]*m[15] -m[4]*m[10]*m[15])/x;
    i[8]= (-m[12]*m[9]* m[7] +m[8]*m[13]*m[7] +m[12]*m[5]*m[11]
           -m[4]*m[13]*m[11] -m[8]*m[5]*m[15] +m[4]*m[9]* m[15])/x;
    i[12]=( m[12]*m[9]* m[6] -m[8]*m[13]*m[6] -m[12]*m[5]*m[10]
           +m[4]*m[13]*m[10] +m[8]*m[5]*m[14] -m[4]*m[9]* m[14])/x;
    i[1]= ( m[13]*m[10]*m[3] -m[9]*m[14]*m[3] -m[13]*m[2]*m[11]
           +m[1]*m[14]*m[11] +m[9]*m[2]*m[15] -m[1]*m[10]*m[15])/x;
    i[5]= (-m[12]*m[10]*m[3] +m[8]*m[14]*m[3] +m[12]*m[2]*m[11]
           -m[0]*m[14]*m[11] -m[8]*m[2]*m[15] +m[0]*m[10]*m[15])/x;
    i[9]= ( m[12]*m[9]* m[3] -m[8]*m[13]*m[3] -m[12]*m[1]*m[11]
           +m[0]*m[13]*m[11] +m[8]*m[1]*m[15] -m[0]*m[9]* m[15])/x;
    i[13]=(-m[12]*m[9]* m[2] +m[8]*m[13]*m[2] +m[12]*m[1]*m[10]
           -m[0]*m[13]*m[10] -m[8]*m[1]*m[14] +m[0]*m[9]* m[14])/x;
    i[2]= (-m[13]*m[6]* m[3] +m[5]*m[14]*m[3] +m[13]*m[2]*m[7]
           -m[1]*m[14]*m[7] -m[5]*m[2]*m[15] +m[1]*m[6]* m[15])/x;
    i[6]= ( m[12]*m[6]* m[3] -m[4]*m[14]*m[3] -m[12]*m[2]*m[7]
           +m[0]*m[14]*m[7] +m[4]*m[2]*m[15] -m[0]*m[6]* m[15])/x;
    i[10]=(-m[12]*m[5]* m[3] +m[4]*m[13]*m[3] +m[12]*m[1]*m[7]
           -m[0]*m[13]*m[7] -m[4]*m[1]*m[15] +m[0]*m[5]* m[15])/x;
    i[14]=( m[12]*m[5]* m[2] -m[4]*m[13]*m[2] -m[12]*m[1]*m[6]
           +m[0]*m[13]*m[6] +m[4]*m[1]*m[14] -m[0]*m[5]* m[14])/x;
    i[3]= ( m[9]* m[6]* m[3] -m[5]*m[10]*m[3] -m[9]* m[2]*m[7]
           +m[1]*m[10]*m[7] +m[5]*m[2]*m[11] -m[1]*m[6]* m[11])/x;
    i[7]= (-m[8]* m[6]* m[3] +m[4]*m[10]*m[3] +m[8]* m[2]*m[7]
           -m[0]*m[10]*m[7] -m[4]*m[2]*m[11] +m[0]*m[6]* m[11])/x;
    i[11]=( m[8]* m[5]* m[3] -m[4]*m[9]* m[3] -m[8]* m[1]*m[7]
           +m[0]*m[9]* m[7] +m[4]*m[1]*m[11] -m[0]*m[5]* m[11])/x;
    i[15]=(-m[8]* m[5]* m[2] +m[4]*m[9]* m[2] +m[8]* m[1]*m[6]
           -m[0]*m[9]* m[6] -m[4]*m[1]*m[10] +m[0]*m[5]* m[10])/x;

    return TRUE;
}

void MatMatMultiply(GLfloat *result, GLfloat *matrix1, GLfloat *matrix2)
{
    result[0]=matrix1[0]*matrix2[0]+
    matrix1[4]*matrix2[1]+
    matrix1[8]*matrix2[2]+
    matrix1[12]*matrix2[3];
    result[4]=matrix1[0]*matrix2[4]+
    matrix1[4]*matrix2[5]+
    matrix1[8]*matrix2[6]+
    matrix1[12]*matrix2[7];
    result[8]=matrix1[0]*matrix2[8]+
    matrix1[4]*matrix2[9]+
    matrix1[8]*matrix2[10]+
    matrix1[12]*matrix2[11];
    result[12]=matrix1[0]*matrix2[12]+
    matrix1[4]*matrix2[13]+
    matrix1[8]*matrix2[14]+
    matrix1[12]*matrix2[15];
    result[1]=matrix1[1]*matrix2[0]+
    matrix1[5]*matrix2[1]+
    matrix1[9]*matrix2[2]+
    matrix1[13]*matrix2[3];
    result[5]=matrix1[1]*matrix2[4]+
    matrix1[5]*matrix2[5]+
    matrix1[9]*matrix2[6]+
    matrix1[13]*matrix2[7];
    result[9]=matrix1[1]*matrix2[8]+
    matrix1[5]*matrix2[9]+
    matrix1[9]*matrix2[10]+
    matrix1[13]*matrix2[11];
    result[13]=matrix1[1]*matrix2[12]+
    matrix1[5]*matrix2[13]+
    matrix1[9]*matrix2[14]+
    matrix1[13]*matrix2[15];
    result[2]=matrix1[2]*matrix2[0]+
    matrix1[6]*matrix2[1]+
    matrix1[10]*matrix2[2]+
    matrix1[14]*matrix2[3];
    result[6]=matrix1[2]*matrix2[4]+
    matrix1[6]*matrix2[5]+
    matrix1[10]*matrix2[6]+
    matrix1[14]*matrix2[7];
    result[10]=matrix1[2]*matrix2[8]+
    matrix1[6]*matrix2[9]+
    matrix1[10]*matrix2[10]+
    matrix1[14]*matrix2[11];
    result[14]=matrix1[2]*matrix2[12]+
    matrix1[6]*matrix2[13]+
    matrix1[10]*matrix2[14]+
    matrix1[14]*matrix2[15];
    result[3]=matrix1[3]*matrix2[0]+
    matrix1[7]*matrix2[1]+
    matrix1[11]*matrix2[2]+
    matrix1[15]*matrix2[3];
    result[7]=matrix1[3]*matrix2[4]+
    matrix1[7]*matrix2[5]+
    matrix1[11]*matrix2[6]+
    matrix1[15]*matrix2[7];
    result[11]=matrix1[3]*matrix2[8]+
    matrix1[7]*matrix2[9]+
    matrix1[11]*matrix2[10]+
    matrix1[15]*matrix2[11];
    result[15]=matrix1[3]*matrix2[12]+
    matrix1[7]*matrix2[13]+
    matrix1[11]*matrix2[14]+
    matrix1[15]*matrix2[15];
}

这篇关于OpenGL ES(iPhone)Touch Picking的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆