I'm using OpenTK for a game in C#, and it doesn't come with the project and unproject functions, which convert between world and screen coordinates. Well, it does, but they're deprecated and I couldn't get them to work. I took a shot at implementing them myself based on the opengl spec (see left hand menu, gluProject and gluUnProject, and view in FF, not Chrome). See those formulas, I'm trying to match them. My functions aren't working at all, the points that Project returns are all near the center of my screen, and very close together, even though I'm moving my world point all over the place.
Note that OpenTK's math lib doesn't include functions for multiplying a matrix by a vector, so I just did matrix row by vector dot products for each entry in the resulting vector (that's correct, isn't it?)
public static Vector3d Project(Vector4d point, Matrix4d projection, Matrix4d modelview, int[] view)
{
Matrix4d temp = Matrix4d.Mult(projection, modelview);
// multiply matrix by vector
Vector4d v_prime = new Vector4d(
Vector4d.Dot(temp.Row0, point),
Vector4d.Dot(temp.Row1, point),
Vector4d.Dot(temp.Row2, point),
Vector4d.Dot(temp.Row3, point)
);
v_prime = Vector4d.Divide(v_prime, v_prime.W);
return new Vector3d(
view[0] + view[2] * (v_prime.X + 1) / 2,
view[1] + view[3] * (v_prime.Y + 1) / 2,
(v_prime.Z + 1) / 2
);
}
public static Vector3d UnProject(Vector3d window, Matrix4d modelview, Matrix4d projection, int[] view)
{
Matrix4d inv = Matrix4d.Mult(projection, modelview);
inv.Invert();
double vx = (2 * (window.X - view[0])) / view[2] - 1;
double vy = (2 * (window.Y - view[1])) / view[3] - 1;
double vz = (2 * window.Z) - 1;
Vector4d vect = new Vector4d(vx, vy, vz, 1);
// now multiply matrix times vector, which is really row (dot) vector for each value
// correct, the bottom row of the inv matrix is unused
return new Vector3d(
Vector4d.Dot(inv.Row0, vect),
Vector4d.Dot(inv.Row1, vect),
Vector4d.Dot(inv.Row2, vect)
);
}