Моя цель - рассчитать луч, который указывает на сцену, для проверки щелчков мыши и прочего. Я не использую обычную перспективную проекцию / камеру, вместо этого я просто использую матрицу наклонной проекции (например, наклонную ортогональную c proj) для моей сцены без камеры (без матрицы просмотра). Все методы, которые я нашел в Интернете, являются своего рода c для перспективной проекции и камер и используют положение камеры непосредственно в качестве источника луча, а затем вычисляют направление луча из положения мыши и матриц проекции / вида. Однако в моем случае (если рассматривать проекцию в контексте реального мира), мое происхождение луча должно быть рассчитано по положению мыши, а направление луча должно быть одинаковым для всех лучей и иметь возможность прямого вычисления из матрицы проекции, но я просто не не знаю, как ..
Это моя матрица наклонной проекции, если это уместно:
fn oblique_projection(cam) -> Mat4 {
let w = cam.screen_width;
let h = cam.screen_height;
let near = cam.near;
let far = cam.far;
// normal orthographic projection matrix:
let (left, right, bottom, top) = (-w / 2.0, w / 2.0, -h / 2.0, h / 2.0);
let tx = -(right + left) / (right - left);
let ty = -(top + bottom) / (top - bottom);
let tz = -(far + near) / (far - near);
let m1 = mat4![
2.0 / (right - left), 0.0, 0.0, 0.0,
0.0, 2.0 / (top - bottom), 0.0, 0.0,
0.0, 0.0, -2.0 / (far - near), 0.0,
tx, ty, tz, 1.0,
];
// apply a skew matrix on top of the orthographic matrix to get an oblique projection matrix
let a = -self.z_scale * f32::cos(self.angle);
let b = -self.z_scale * f32::sin(self.angle);
let m2 = mat4![
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
a, b, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
];
return m1 * m2;
}
(в основном искаженная ортографическая проекция c, в результате получается вид, подобный изометрии c). )
РЕДАКТИРОВАТЬ:
Я нашел очень точное решение c для моей установки (моя наклонная проекция)
let a = -cam.z_scale * cos(cam.angle);
let b = -cam.z_scale * sin(cam.angle);
let skewed = mat4[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
a, b, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
]; // the only the skew part from the projection matrix construction above
let ray_dir = (skewed * vec3!(0, 0, -1)).normalized(); // apply the skew to a unit forward vector
let mouse_pos_clip_space = screen_to_clip(mouse_pos);
let clip_coord = vec4(mouse_pos_clip_space, -1, 1);
let ray_orig = projection_matrix.inverse() * clip_coord; // unproject the oblique projection matrix calculated in the previous code block
return Ray {
origin: ray_orig,
dir: ray_dir,
};
Так что Идея состоит в том, чтобы сначала выяснить, как построить луч для обычной ортографической проекции c, а затем применить перекос
. Это заставляет меня думать, что нет общего алгоритма fn get_ray(proj: Mat4, view: Mat4) -> (ray_origin: Vec3, ray_dir: Vec3)
, потому что, как я строю Луч значительно отличается от обычного проекционного изображения + камера.