OpenGL ES (iPhone) 触摸拾取

发布于 2024-08-21 05:45:00 字数 4697 浏览 5 评论 0原文

希望在 ES 中进行经典的 OpenGL 鼠标拾取。我不想使用第三方库,GLU 端口和 OpenGL 名称堆栈等都已退出。这几乎留下了逆视图变换和光线相交,对吗?

在以下人员的帮助下我已经取得了很大的进展: http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/MousePicking http://eigenclass.blogspot.com/2008 /10/opengl-es-picking-using-ray-boundingbox.html

。 。 .但我还没到那儿。这也让人觉得一定有更简单的方法!

这是一些代码:

    -(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!!!");
            }
        }
    }
}

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?

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!!

Here is some code:

    -(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!!!");
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧夏天 2024-08-28 05:45:00

这篇文章很难理解。我正在尝试使用 GLKView 在 iOS 5 上推出自己的产品;我已经研究出了如何触摸检测像素 RGBA,正如我所描述的 这里,现在我正在尝试找出如何快速将场景对象的颜色更改为唯一的,以配合此方法。

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.

迷荒 2024-08-28 05:45:00

我设法修复它:

-(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];
}

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];
}
爱,才寂寞 2024-08-28 05:45:00

好吧,好吧,这还是有点问题。这是现在最有效的:

-(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];
}

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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文