OpenGL ES (iPhone) Touch Picking

前端 未结 3 1907
情书的邮戳
情书的邮戳 2021-01-18 06:43

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

相关标签:
3条回答
  • 2021-01-18 07:18

    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];
    }
    
    0 讨论(0)
  • 2021-01-18 07:37

    This post is very hard to follow. I'm attempting to roll my own on iOS 5 with GLKView; I've worked out how to touch detect pixel RGBA as I describe here, now I'm trying to work out how to quickly change the colours of my scene objects to be unique, to accompany this method.

    0 讨论(0)
  • 2021-01-18 07:38

    I managed to fix it:

    -(void)view2WorldPoint:(CGPoint)point :(GLfloat*)worldPoint {
        // this is the inverse translation of the modelview
        GLfloat width = (GLfloat)backingWidth;
        GLfloat height = (GLfloat)backingHeight;
    
        float clickX = point.x;
        float clickY = point.y;
        float clickZ = 0.0f;
    
        NSLog(@"click point : x = %f, y = %f, z = %f", clickX, clickY, clickZ);
    
        //  NSLog(@"Me : x = %f, y = %f, z = %f", a[0], a[1], a[2]);
        //  NSLog(@"Dev : x = %f, y = %f, z = %f", squareX, squareY, squareZ);
    
        //viewport -> normalized device coord -> clip
        GLfloat n[] = {
            2 * clickX / width - 1,
            2 * (480-clickY) / height - 1,
            2 * clickZ - 1,
            1
        };
        //  NSLog(@"Obj : x = %f, y = %f, z = %f", rect.origin.x, rect.origin.y, -0.5);
        //  NSLog(@"N : x = %f, y = %f, z = %f", n[0], n[1], n[2]); 
    
        //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 P[16];
        glGetFloatv(GL_PROJECTION_MATRIX, P);
        //  [self dumpMatrix:P :@"P"];
    
        GLfloat Pminus1[] = {
            1/P[0], 0, 0, 0,
            0, 1/P[5], 0, 0,
            0, 0, 0, 1/P[11],
            0, 0, 1/P[14], -(P[10]/ (P[11]*P[14]))
        };
    
        //  [self dumpMatrix:Pminus1 :@"P-1"];
    
        //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])
        };
    
        //  NSLog(@"v = [%f, %f, %f, %f]", v[0], v[1], v[2], v[3]);
    
    
        //  [self dumpMatrix:mv :@"mv"];
    
        //view -> world
        GLfloat Rt[] = {
            mv[0], mv[4], -mv[8],
            mv[1], mv[5], -mv[9],
            -mv[2], -mv[6], mv[10]
        };
    
        //  NSLog(@"Rt0 = [%f, %f, %f]", Rt[0], Rt[1], Rt[2]);
        //  NSLog(@"Rt1 = [%f, %f, %f]", Rt[3], Rt[4], Rt[5]);
        //  NSLog(@"Rt2 = [%f, %f, %f]", Rt[6], Rt[7], Rt[8]);
    
        GLfloat tPrime[] = {
            Rt[0] * mv[12] + Rt[1] * mv[13] + Rt[2] * mv[14],
            Rt[3] * mv[12] + Rt[4] * mv[13] + Rt[5] * mv[14],
            Rt[6] * mv[12] + Rt[7] * mv[13] + Rt[8] * mv[14]
        };
    
        //  NSLog(@"tPrime = [%f, %f, %f]", tPrime[0], tPrime[1], tPrime[2]);
    
        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]
        };
        NSLog(@"W : x = %f, y = %f, z = %f", w[0], w[1], w[2]);
        worldPoint[0] = w[0];
        worldPoint[1] = w[1];
        worldPoint[2] = w[2];
    }
    
    0 讨论(0)
提交回复
热议问题