Перевод координат экрана в мировые (реализация unproject)
Как мне реализовать функцию unProject? Чтоб вызывая функцию для определенного x и y в координатах экрана я получал две точки - одну на zNearPlane, а вторую на zFarРlane в мировых координатах.

The unproject function does the inverse the chain of computations, but it requires to specify the z value manually:
• z = -1 for the near plane
• z = 1 for the far plane
glm::vec3 a = unproject(x, y, -1.0);
glm::vec3 b = unproject(x, y, 1.0);
ray cursorRay{a, normalize(b - a)};
Ответы (2 шт):
Автор решения: USSRCoder
→ Ссылка
public Vector3 UnProject(//ref Matrix4 projection,//Matrix4 view,
System.Drawing.Size viewport, Vector3 mouse)
{
Vector4 vec;
vec.X = 2.0f * mouse.X / (float)viewport.Width - 1;
vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1);
vec.Z = mouse.Z;
vec.W = 1.0f;
Matrix4x4 viewInv = new Matrix4x4();
Matrix4x4 projInv = new Matrix4x4();
Matrix4x4.Invert(GetViewMatrix(), out viewInv);
Matrix4x4.Invert(GetProjectionMatrix(), out projInv);
vec = Vector4.Transform(vec, projInv);
vec = Vector4.Transform(vec, viewInv);
if (vec.W > float.Epsilon || vec.W < -float.Epsilon) {
vec.X /= vec.W;
vec.Y /= vec.W;
vec.Z /= vec.W;
}
return new Vector3(vec.X, vec.Y, vec.Z);
}
Использовать так:
//Последний 0 в Vector3 - это zNearPlane
near = Camera.UnProject(new System.Drawing.Size(Width, Height), new Vector3(mouse.Position.X, mouse.Position.Y, 0));
//Последний 1 в Vector3 - это zFarРlane
far = Camera.UnProject(new System.Drawing.Size(Width, Height), new Vector3(mouse.Position.X+1, mouse.Position.Y+1, 1));
Console.WriteLine($"Unproject:{near} {far}");
g3.Vector3d origin = new g3.Vector3f();
g3.Vector3f direction = new g3.Vector3f();
direction = (new g3.Vector3f(far.X,far.Y,far.Z) - new g3.Vector3f(near.X,near.Y, near.Z)).Normalized;
origin = new g3.Vector3f(near.X, near.Y, near.Z);
g3.Ray3d ray = new g3.Ray3d(origin, direction);
И 2 процедуры
public Matrix4x4 GetViewMatrix() {
return Matrix4x4.CreateLookAt(Position, Position + Front, Up);
}
public Matrix4x4 GetProjectionMatrix() {
return Matrix4x4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(Zoom), AspectRatio, 0.1f, 10000.0f);
}
Автор решения: ANGRY SHARK
→ Ссылка
Нашел ответ в исходном коде glm. (Документация по этим функциям)
template<typename T, typename U, qualifier Q>
GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectZO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport)
{
mat<4, 4, T, Q> Inverse = inverse(proj * model);
vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1));
tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]);
tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]);
tmp.x = tmp.x * static_cast<T>(2) - static_cast<T>(1);
tmp.y = tmp.y * static_cast<T>(2) - static_cast<T>(1);
vec<4, T, Q> obj = Inverse * tmp;
obj /= obj.w;
return vec<3, T, Q>(obj);
}
template<typename T, typename U, qualifier Q>
GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectNO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport)
{
mat<4, 4, T, Q> Inverse = inverse(proj * model);
vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1));
tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]);
tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]);
tmp = tmp * static_cast<T>(2) - static_cast<T>(1);
vec<4, T, Q> obj = Inverse * tmp;
obj /= obj.w;
return vec<3, T, Q>(obj);
}