
Object To Screen Space
Submitted by 
The OpenGL pipeline automatically transforms object space vertices to
homogeneous clip space and then to screen space pixel coordinates and
a zbuffer value betwen 0 and 1. When combining 2D and 3D rendering, you need
to perform that transformation manually. Two example applications are finding
the 3D ray corresponding to a 2D mouse position and the location at which to
render 2D text over 3D vertices.
The glToScreen function listed below transform an object space point to
screen space using the current GL_MODELVIEW and GL_PROJECTION matrices. The
resulting xy values are in pixels, the z value is on the glDepthRange
scale, which defaults to [0, 1]), and the w value contains rhw. The rhw value
is 1/z for camera space z (note that a true mathematical
projection gives w = 1 instead.) The rhw value is useful for scaling line and
point size with perspective, which OpenGL does not do by default.
Morgan McGuire

Download Associated File: glToScreen.txt (1,177 bytes)
Vector4 glToScreen(const Vector4& v) {
// Get the matrices and viewport
double modelView[16];
double projection[16];
double viewport[4];
double depthRange[2];
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetDoublev(GL_VIEWPORT, viewport);
glGetDoublev(GL_DEPTH_RANGE, depthRange);
// Compose the matrices into a single rowmajor transformation
Vector4 T[4];
int r, c, i;
for (r = 0; r < 4; ++r) {
for (c = 0; c < 4; ++c) {
T[r][c] = 0;
for (i = 0; i < 4; ++i) {
// OpenGL matrices are column major
T[r][c] += projection[r + i * 4] * modelView[i + c * 4];
}
}
}
// Transform the vertex
Vector4 result;
for (r = 0; r < 4; ++r) {
result[r] = T[r].dot(v);
}
// Homogeneous divide
const double rhw = 1 / result.w;
return Vector4(
(1 + result.x * rhw) * viewport[2] / 2 + viewport[0],
(1  result.y * rhw) * viewport[3] / 2 + viewport[1],
(result.z * rhw) * (depthRange[1]  depthRange[0]) + depthRange[0],
rhw);
} 

The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
