Reputation: 975
The general Ray picking process should be as follows(experiment result proved to be right):
transform screen point to normalized device space direction vector:
float x = (2.0f * mouse_x) / width - 1.0f;
float y = 1.0f - (2.0f * mouse_y) / height;
float z = 1.0f;
vec3 ray_nds = vec3 (x, y, z);
transform direction vector to Homogeneous Clip Coordinates
vec4 ray_clip = vec4 (ray_nds.xy, -1.0, 1.0);
transform direction vector to eye space direction vector
vec4 ray_eye = inverse (projection_matrix) * ray_clip;
transform direction vector to world space, get a pick ray with world space camera position and the direction vector
My problem is, in normalized device space, why the z component of the direction vector is 1.0? I mean, in OpenGL normalized device space, xyz component should all be in the range of -1~1, so the camera should be in the center of the plane z=-1. So the direction vector should be: view target position - camera position, and the z component should be 1-(-1)=2.0f. (in DirectX normalized device space, xy component is in the range of -1~1, z component is in the range of 0~1, the camera position should be in the center of the plane z=0, say, (0,0,0), and the z component of the direction vector should be 1-0=1)
Upvotes: 3
Views: 908
Reputation: 6775
the camera is NOT located at z=-1 (or 0) it is even behind that.
The near clip plane
is located at z=-1. this makes all the complexity of this kind of maths, because all equations involves if traced would make curves that don't pass through 0. because of that we always carry over lots of zn
and zm
.
check that out, equation 4.2 : http://www.arcsynthesis.org/gltut/Positioning/Tut04%20Perspective%20Projection.html.
even scarier but more complete: http://www.songho.ca/opengl/gl_projectionmatrix.html
http://schabby.de/projection-matrix/
Upvotes: 0
Reputation: 32587
ray_nds.z
is completely irrelevant, because you don't use it anyway. That's because you don't know the pixel's depth.
ray_clip
is not a direction, but a position on the near clipping plane (z=-1) after projection. If you undo this projection (with the inverse projection matrix) you end up with the same point in camera space. In camera space, the camera is centered at (0, 0, 0)
. The direction vector of the ray can be calculated with ray_eye - (0, 0, 0)
, which is essentially ray_eye
. So if we ignore the w-component, we can use the position as a direction. This does only work in camera space! Both clip space and world space are most likely to have the projection center somewhere else.
Don't mix up the camera position in the different spaces. In camera space, it is at the origin. In clip space it can be assumed to be at (0, 0, -infinity)
. The point (x, y, ...)
is just an arbitrary point that is covered by the according pixel. And you need any of them to define the ray.
Upvotes: 1