Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++/OpenGL convert world coords to screen(2D) coords

Tags:

I am making a game in OpenGL where I have a few objects within the world space. I want to make a function where I can take in an object's location (3D) and transform it to the screen's location (2D) and return it.

I know the the 3D location of the object, projection matrix and view matrix in the following varibles:

Matrix projectionMatrix; Matrix viewMatrix; Vector3 point3D; 
like image 551
Danny Avatar asked Dec 13 '11 14:12

Danny


1 Answers

To do this transform, you must first take your model-space positions and transform them to clip-space. This is done with matrix multiplies. I will use GLSL-style code to make it obvious what I'm doing:

vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0)); 

Notice how I convert your 3D vector into a 4D vector before the multiplication. This is necessary because the matrices are 4x4, and you cannot multiply a 4x4 matrix with a 3D vector. You need a fourth component.

The next step is to transform this position from clip-space to normalized device coordinate space (NDC space). NDC space is on the range [-1, 1] in all three axes. This is done by dividing the first three coordinates by the fourth:

vec3 ndcSpacePos = clipSpacePos.xyz / clipSpacePos.w; 

Obviously, if clipSpacePos.w is zero, you have a problem, so you should check that beforehand. If it is zero, then that means that the object is in the plane of projection; it's view-space depth is zero. And such vertices are automatically clipped by OpenGL.

The next step is to transform from this [-1, 1] space to window-relative coordinates. This requires the use of the values you passed to glViewport. The first two parameters are the offset from the bottom-left of the window (vec2 viewOffset), and the second two parameters are the width/height of the viewport area (vec2 viewSize). Given these, the window-space position is:

vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0) / 2.0) * viewSize + viewOffset; 

And that's as far as you go. Remember: OpenGL's window-space is relative to the bottom-left of the window, not the top-left.

like image 88
Nicol Bolas Avatar answered Oct 04 '22 21:10

Nicol Bolas