I'm using SharpGL in a WPF window and have navigation and plotting of a survey point cloud with custom shaders for distance-based point size reduction. All working well but I've recently attempted to add the ability to select a point nearest to the ray cast by a mouse click. I used the steps 0 to 4 in this link: http://antongerdelan.net/opengl/raycasting.html
The problem I'm facing is that the ray seems to be very slightly shifted towards the camera vector causing me to miss the points I'm clicking on and only scrape their inside edge. I'm drawing the ray starting from the camera position too so initially the ray should appear as a dot before moving the camera (looking down the trajectory line) but I can see it clearly drawn to the middle of the screen. Here's a screenshot showing where the ray misses the point when I click on its center:
This is the code I'm using to calculate the ray start and end coordinates:
public void CreateVerticesForMouseCoord(OpenGL gl, float winx, float winy)
{
int[] viewport = new int[4];
gl.GetInteger(OpenGL.GL_VIEWPORT, viewport);
float window_width = viewport[2];
float window_height = viewport[3];
Console.WriteLine("Window size: " + window_width + "," + window_height);
vec4 clipPosition = new vec4(0.0f, 0.0f, 1.0f, 1.0f);
// Normalize the x and y coordinates
clipPosition.x = 2.0f * (winx / window_width) - 1.0f;
clipPosition.y = -2.0f * (winy / window_height) + 1.0f;
mat4 viewInv = glm.inverse(viewMatrix);
mat4 projInv = glm.inverse(projectionMatrix);
vec4 camPosition = projInv * clipPosition;
camPosition.w = 0;
camPosition.z = -1;
vec4 worldPosition = viewInv * camPosition;
vec4 camCamPos = new vec4(0.0f, 0.0f, 0.0f, 1.0f);
vec4 objCamPos = glm.inverse(viewMatrix) * camCamPos;
vec4 camCamDir = new vec4(0.0f, 0.0f, -1.0f, 0.0f);
vec4 objCamDir = glm.inverse(viewMatrix) * camCamDir;
float x1 = objCamPos.x + 30.0f * worldPosition.x;
float y1 = objCamPos.y + 30.0f * worldPosition.y;
float z1 = objCamPos.z + 30.0f * worldPosition.z;
float x2 = objCamPos.x - 0.0f * worldPosition.x;
float y2 = objCamPos.y - 0.0f * worldPosition.y;
float z2 = objCamPos.z - 0.0f * worldPosition.z;
Console.WriteLine("Screen coordinates: " + winx + ","+winy);
Console.WriteLine("Clip coordinates: " + clipPosition.x + "," + clipPosition.y + "," + clipPosition.z+ ","+ clipPosition.w);
Console.WriteLine("Camera coordinates: " + camPosition.x + "," + camPosition.y + "," + camPosition.z+","+ camPosition.w);
Console.WriteLine("World coordinates: " + worldPosition.x + "," + worldPosition.y + "," + worldPosition.z+","+ worldPosition.w);
Console.WriteLine("Camera Position: " + objCamPos.x + "," + objCamPos.y + "," + objCamPos.z + "," + objCamPos.w);
Console.WriteLine("Camera Direction: " + objCamDir.x + "," + objCamDir.y + "," + objCamDir.z + "," + objCamDir.w);
float[] mousePointArray = { x1, y1, z1, x2, y2, z2 };
The output looks like this:
Window size: 470,314
Screen coordinates: 316,184
Clip coordinates: 0.3446808,-0.1719745,1,1
Camera coordinates: 0.1877808,-0.06259361,-1,0
World coordinates: 0.1877808,-0.06259361,-1,0
Camera Position: 4,7,6,1
Camera Direction: 0,0,-1,0
The offset does appear to get bigger the further away from the center of the screen I click. Any help I can get diagnosing this would be much appreciated, I've spent two days reading articles and fiddling with the code to no avail.