I was experimenting with ray casting to implement mouse picking in my application.
What I wanted to do is literally draw the line that is cast from the screen when the mouse is clicked.
Here's what i did:
float xNormalised = ((float)200/w.getWidth())*2 -1;
float yNormalised = -(((float)300/w.getHeight())*2 -1);
glm::vec4 nearP = glm::vec4(xNormalised,yNormalised,-1,1);
glm::vec4 farP = glm::vec4(xNormalised,yNormalised,1,1);
For simplicity i hard code the mouse coordinates from which the ray should be cast, i map them to normalised device coordinates and then i create two vectors representing two points: the point nearest to the screen and the point farthest on the same line.
worldNear = getInversedPoint(nearP,proj, view);
worldFar = getInversedPoint(farP,proj, view);
Then i call this function on each of the points to basically reverse the pipeline to get their version in the world space, here's what it does:
glm::vec4 getInversedPoint(glm::vec4 point,glm::mat4& proj,glm::mat4 view){
//glm::mat4 inv = inverse(proj*view);
point = point*inverse(proj);
auto v = vec4(point.x/point.w,point.y/point.w,point.z/point.w,1);
//auto v = vec4(point.x/point.w,point.y/point.w,point.z/point.w,point.w);
point = v*inverse(view);
return vec4(point.x,point.y,point.z,point.w);
}
After this i should have gotten the two points in world space if i didn't get it wrong, so i put these two points in a buffer and call gldraw to draw the line that connects them.
What i'm expecting is basically a red dot in the coordinates that i put, because it is a straight line from the click point to the point in front of it... but i get a strange line more or less in the center of the screen, which is not where i specified..
What am i doing wrong?
You can see the red line in the center, near the sideways triangle.
My vertex shader:
#version 330 core
layout(location = 1)in vec4 pos;
uniform mat4 projectMat;
uniform mat4 viewMat;
void main(){
gl_Position = pos;
}
I also tried to multiply the points by the two matrices as well but it only slightly change.
You can use glm::unproject to get you far and near points :
glm::vec3 near = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, 0), // the screen-space coordinate
camera.view,
camera.projection,
glm::vec4(0, 0, winSize)); // your viewport
glm::vec3 far = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, 0), // the screen-space coordinate
camera.view,
camera.projection,
glm::vec4(0, 0, winSize)); // your viewport
You could also get the point under the mouse directly by reading the framebuffer :
/** read depth buffer and get the point under the cursor **/
float depth;
glReadPixels(mouseX, winSize.y - mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
if (depth < 1.0)
point_on_plane = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, depth), camera.view,
camera.projection,
glm::vec4(0, 0, winSize));