Search code examples
qt4texturesopengl-3mouse-pickingqtopengl

Retrieve the texture coordinate under the mouse


I'm working with Qt 4.8 and its OpenGL module, with the fixed pipeline and I have a sphere that was cubemapped, with the tex coords for each cube face auto-generated by OpenGL via glTexGenf (R, S and T coordinates).

glEnableClientState(GL_NORMAL_ARRAY);
const GLenum textgt = GL_TEXTURE_CUBE_MAP;
const GLfloat param = GL_REFLECTION_MAP;

glTexGenf( GL_S, GL_TEXTURE_GEN_MODE, param );
GLenum error = glGetError();
if(GL_NO_ERROR != error) { ... }

glTexGenf( GL_T, GL_TEXTURE_GEN_MODE, param );
error = glGetError();
if(GL_NO_ERROR != error) { ... }

glTexGenf( GL_R, GL_TEXTURE_GEN_MODE, param );
error = glGetError();
if(GL_NO_ERROR != error) { ... }

glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glEnable( GL_TEXTURE_GEN_R );

When clicking in the scene, I'm retrieving the vertex coordinates under the mouse cursor via glReadPixels and gluUnProject.

What I'm looking for now is a way to retrieve the texture coordinate associated to that position. I didn't find anything regarding this topic, so I was wondering if there was a way to achieve this.


Solution

  • After searching through the OpenGL specs, I found in the version 1.3 the formula used to compute the texel for a given vertex [Chapter 2, Section 10, Part 4 - Generating Texture Coordinates].

    Starting with an unit vector u that goes from the origin to the vertex in eye coordinates and having n as the normal for that vertex in eye coordinates, we first need to calculate the reflection vector, r:

    r = u - 2nT(nu)

    Then, the S, T and R coordinates we're looking for will be

    rx, ry, rz
    respectively.

    Also, there's a web that "translates" the formula to pseudocode. I'll post here the relevant part for GL_REFLECTION_MAP, in case the page is unavaliable:

     for(i=0; i<total; i++)
     {
       myEyeVertex = MatrixTimesVector(ModelviewMatrix, myVertex[i]);
       myEyeVertex = Normalize(myEyeVertex);
       myEyeNormal = VectorTimesMatrix(myNormal[i], InverseModelviewMatrix);
       dotResult = 2.0 * dot3D(myEyeVertex, myEyeNormal);
       //I am emphasizing that we write to s and t and r. Used to sample a cubemap.
       myTexCoord[i].s = myEyeVertex.x - myEyeNormal.x * dotResult;
       myTexCoord[i].t = myEyeVertex.y - myEyeNormal.y * dotResult;
       myTexCoord[i].r = myEyeVertex.z - myEyeNormal.z * dotResult;
     }