有两种方法,一种是利用gluProject函数:
GLdouble modelview[16]; GLdouble projection[16]; GLdouble out[3], in[3]; // 对in赋值…… glPushMatrix(); glGetDoublev(GL_MODELVIEW_MATRIX, modelview); glGetDoublev(GL_PROJECTION_MATRIX, projection); gluProject(in[0],in[1],in[2],modelview,projection,viewport,&(out[0]),&(out[1]),&(out[2]));
gluProject源码:
/* Transform a point(column vector) by a 4x4 matrix. Then, out = m * in Input: m ----- the 4x4 matrix, in ---- the 4x1 vector Output: out ---- the resulting 4x1 vector */ static void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4]) { #define M(row,col) m[col*4+row] out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3]; out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3]; out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3]; out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3]; #undef M } // gluProject source code (说明见OpenGL API文档) GLint gluProject(GLdouble objx, GLdouble objy, GLdouble objz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *winx, GLdouble *winy, GLdouble *winz) { // matrice transformation GLdouble in[4], out[4]; //initialize matrice and column vector as a transformer in[0] = objx; in[1] = objy; in[2] = objz; in[3] = 1.0; transform_point(out, modelMatrix, in); //乘以模型视图矩阵 transform_point(in, projMatrix, out); //乘以投影矩阵 //齐次向量的第四项不能为0 if(in[3] == 0.0) return GL_FALSE; //向量齐次化标准化 in[0] /= in[3]; in[1] /= in[3]; in[2] /= in[3]; //视口向量的作用 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2; *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2; *winz = (1 + in[2]) / 2; return GL_TRUE; }
第二种方法就是实现gluProject,照着源码实现就可以了,需要注意的是OpenGL的矩阵是列主序存储的。