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