Reputation: 5678
I understand the basic concept of how to unproject:
let mut z = 0.0;
gl::ReadPixels(x as i32, y as i32, 1, 1, gl::DEPTH_COMPONENT, gl::FLOAT, &z);
// window position to screen position
let screen_position = self.to_screen_position(x, y);
// screen position to world position
let world_position = self.projection_matrix().invert() *
Vector4::new(screen_position.x, screen_position.y, z, 1.0);
But this doesn't take the W coordinate properly - when I render things from world space to screen space, they end up with a W != 1
, because of the perspective transformation (https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml). When I transform back from screen space to world space (with an assumption of W=1
), the objects are in the wrong position.
As I understand it, W
is a scaling factor for all the other coordinates. If this is the case, doesn't it mean screen vectors (0, 0, -1, 1)
and (0, 0, -2, 2)
will map to the same window coordinates, and that unprojecting doesn't necessarily produce unique results without further work?
Thanks!
Upvotes: 0
Views: 725
Reputation: 3369
Because of the perspective transformation, you can't really ignore W.
I would suggest looking at the source code for the gluUnproject
function here: http://www.opengl.org/wiki/GluProject_and_gluUnProject_code. You'll see that what this does is:
Note that if you do it like this, the result's W should be ignored (i.e. assumed to be 1).
You can also look here to see how the transformations in OpenGL work - if you're not familiar with this, I'd suggest reading about Clip coordinates and Normalized Device coordinates.
Upvotes: 2