Подскажите, пожалуйста, формулу или литературу где её взять.
Собственно есть:
- координаты мыши с (0,0) в левом верхнем углу окна
- ортогональная проекция камеры в виде матрицы 4x4
- глобальное положение камеры в виде матрицы 4x4
- ширина и высота окна
У камеры (0,0) в левом нижнем углу.
Как преобразовать координаты мыши в координаты камеры (сцены) с учётом положения и поворота камеры?
Прямо так взять экранную точку и преобразовать в точку в мировом пространстве не выйдет, потому что одно это 2д, другое 3д. Так можно только луч получить, исходящий из наблюдателя. Потом уже можно искать с чем там этот луч сталкивается. Тебе луч нужен или?
Нет, без луча, просто проекция. Что-то вроде Camera.ScreenToWorldPoint
Ну так эта функция принимает 3 координаты, а у тебя только 2.
Точке на экране соответсвует бесконечное количество точек сцены (луч).
Вообще, в лоб, то, кажется, как-то так
struct Camera {
view: Projective3<f32>,
proj: Perspective3<f32>,
}
fn world_from_mouse(pos: Point2<f32>, camera: &Camera) -> Point3<f32> {
let x = pos[0];
let y = 1. 0 - pos[1]; // Переворачиваем потому что `У камеры (0,0) в левом нижнем углу` а `координаты мыши с (0,0) в левом верхнем углу окна`.
// Хотя я б ожидал, что у камеры (0,0) в центре.
let pos = Point3::new(x, y, 0.0).to_homogeneous();
Point3::from_homogeneous(camera.view.to_homogeneous() * camera.projection.inverse() * pos)
}
На выходе будет точка на near-plane камеры.
Так там в примере за z берётся некий cam.nearClipPlane, полагаю его можно заменить на 1.0
У камеры в аметисте у меня выходит в левом нижнем углу, если я что-то не путаю конечно.
Я что-то делаю не так
fn screen_to_2d_scene(
position: (f64, f64),
camera_transform: &GlobalTransform,
camera: &Camera,
screen_dim: &ScreenDimensions,
) -> (f32, f32) {
let projection = Orthographic3::from_matrix_unchecked(camera.proj);
let perspective = Perspective3::from_matrix_unchecked(camera_transform.0);
let screen_x = position.0 as f32;
let screen_y = position.1 as f32;
let pos = Point3::new(screen_x, -screen_y, 1.0).to_homogeneous();
let world = Point3::from_homogeneous(perspective.to_homogeneous() * projection.inverse() * pos)
.unwrap();
(world.x, world.y)
}
выдаёт далеко не то что хотелось бы.
Не получается у меня что-то, размер сцены 409х230 а координаты мыши на выходе получаются
от (205, 115) до (409, 230)
То есть правый верхний угол попадает, а нижний левый нет.
fn screen_to_2d_scene(
position: (f64, f64),
camera_transform: &GlobalTransform,
camera: &Camera,
screen_dim: &ScreenDimensions,
) -> (f32, f32) {
let screen_x = position.0 as f32 / screen_dim.width();
let screen_y = 1.0 - position.1 as f32 / screen_dim.height();
let screen_point = Point3::new(screen_x, screen_y, 0.0).to_homogeneous();
let matrix = camera_transform.0 * camera.proj.try_inverse().unwrap();
let world_point = matrix * screen_point;
(world_point.x, world_point.y)
}
Всё, разобрался, всем спасибо
fn screen_to_2d_scene(
position: (f64, f64),
camera_transform: &GlobalTransform,
camera: &Camera,
screen_dim: &ScreenDimensions,
) -> Point3<f32> {
let screen_x = 2.0 * position.0 as f32 / screen_dim.width() - 1.0;
let screen_y = 1.0 - 2.0 * position.1 as f32 / screen_dim.height();
let screen_point = Point3::new(screen_x, screen_y, 0.0).to_homogeneous();
let world_point = camera_transform.0 * camera.proj.try_inverse().unwrap() * screen_point;
Point3::from_homogeneous(world_point).unwrap()
}