del_canvas/
cam3.rs

1use num_traits::AsPrimitive;
2
3pub struct Camera3<T> {
4    pub w: usize,
5    pub h: usize,
6    o: [T; 3],
7    d: [T; 3],
8    cx: [T; 3],
9    cy: [T; 3],
10}
11
12impl<T> Camera3<T>
13where
14    T: num_traits::Float + 'static + Copy,
15    f64: AsPrimitive<T>,
16    usize: AsPrimitive<T>,
17{
18    pub fn new(w: usize, h: usize, o: &[T; 3], d: &[T; 3]) -> Self {
19        use del_geo_core::vec3::Vec3;
20        let half = T::one() / (T::one() + T::one());
21        let d = d.normalize();
22        let cx = [w.as_() * 0.5135.as_() / h.as_(), T::zero(), T::zero()];
23        let cy = cx.cross(&d).normalize().scale(half);
24        Camera3 {
25            w,
26            h,
27            o: *o,
28            d,
29            cx,
30            cy,
31        }
32    }
33
34    pub fn ray(&self, x0: T, y0: T) -> ([T; 3], [T; 3]) {
35        use del_geo_core::vec3::Vec3;
36        let d = del_geo_core::vec3::add_three(
37            &self.cx.scale(x0 / self.w.as_() - 0.5.as_()),
38            &self.cy.scale(y0 / self.h.as_() - 0.5.as_()),
39            &self.d,
40        );
41        (self.o.add(&d.scale(140.as_())), d.normalize())
42    }
43}
44
45/// the ray start from the front plane and ends on the back plane
46pub fn ray3_homogeneous(
47    pix_coord: (usize, usize),
48    image_size: &(usize, usize),
49    transform_ndc_to_world: &[f32; 16],
50) -> ([f32; 3], [f32; 3]) {
51    let x0 = 2. * (pix_coord.0 as f32 + 0.5f32) / (image_size.0 as f32) - 1.;
52    let y0 = 1. - 2. * (pix_coord.1 as f32 + 0.5f32) / (image_size.1 as f32);
53    let p0 =
54        del_geo_core::mat4_col_major::transform_homogeneous(transform_ndc_to_world, &[x0, y0, 1.])
55            .unwrap();
56    let p1 =
57        del_geo_core::mat4_col_major::transform_homogeneous(transform_ndc_to_world, &[x0, y0, -1.])
58            .unwrap();
59    let ray_org = p0;
60    let ray_dir = del_geo_core::vec3::sub(&p1, &p0);
61    (ray_org, ray_dir)
62}