90 lines
3 KiB
Rust
90 lines
3 KiB
Rust
use ash::vk::Image;
|
|
use shared::cameras::{Mapping, RealisticCamera, realistic::LensElementInterface};
|
|
|
|
struct RealisticCameraData {
|
|
aperture_image: Arc<Image>,
|
|
element_interfaces: Vec<LensElementInterface>,
|
|
}
|
|
|
|
pub struct RealisticCameraHost {
|
|
device: RealisticCamera,
|
|
data: RealisticCameraData,
|
|
}
|
|
|
|
impl RealisticCameraHost {
|
|
pub fn new(
|
|
base: CameraBase,
|
|
lens_params: &[Float],
|
|
focus_distance: Float,
|
|
set_aperture_diameter: Float,
|
|
aperture_image: Arc<Image>,
|
|
) -> Self {
|
|
let film_ptr = base.film;
|
|
if film_ptr.is_null() {
|
|
panic!("Camera must have a film");
|
|
}
|
|
let film = &*film_ptr;
|
|
|
|
let aspect = film.full_resolution().x() as Float / film.full_resolution().y() as Float;
|
|
let diagonal = film.diagonal();
|
|
let x = (square(diagonal) / (1.0 + square(diagonal))).sqrt();
|
|
let y = x * aspect;
|
|
let physical_extent =
|
|
Bounds2f::from_points(Point2f::new(-x / 2., -y / 2.), Point2f::new(x / 2., y / 2.));
|
|
let mut element_interface: Vec<LensElementInterface> = Vec::new();
|
|
|
|
for i in (0..lens_params.len()).step_by(4) {
|
|
let curvature_radius = lens_params[i] / 1000.0;
|
|
let thickness = lens_params[i + 1] / 1000.0;
|
|
let eta = lens_params[i + 2];
|
|
let mut aperture_diameter = lens_params[i + 3] / 1000.0;
|
|
|
|
if curvature_radius == 0.0 {
|
|
aperture_diameter /= 1000.0;
|
|
if set_aperture_diameter > aperture_diameter {
|
|
println!("Aperture is larger than possible")
|
|
} else {
|
|
aperture_diameter = set_aperture_diameter;
|
|
}
|
|
}
|
|
let el_int = LensElementInterface {
|
|
curvature_radius,
|
|
thickness,
|
|
eta,
|
|
aperture_radius: aperture_diameter / 2.0,
|
|
};
|
|
element_interface.push(el_int);
|
|
}
|
|
|
|
let half_diag = film.diagonal() / 2.0;
|
|
let mut exit_pupil_bounds = [Bounds2f::default(); EXIT_PUPIL_SAMPLES];
|
|
|
|
for i in 0..EXIT_PUPIL_SAMPLES {
|
|
let r0 = (i as Float / EXIT_PUPIL_SAMPLES as Float) * half_diag;
|
|
let r1 = ((i + 1) as Float / EXIT_PUPIL_SAMPLES as Float) * half_diag;
|
|
exit_pupil_bounds[i] = Self::compute_exit_pupil_bounds(&element_interface, r0, r1);
|
|
}
|
|
|
|
let n_elements = element_interface.len();
|
|
let element_interfaces = element_interface.as_ptr();
|
|
std::mem::forget(element_interface);
|
|
|
|
let data = RealisticCameraData {
|
|
element_interfaces,
|
|
aperture_image,
|
|
};
|
|
|
|
let device = RealisticCamera {
|
|
base,
|
|
focus_distance,
|
|
element_interfaces: Ptr::from(element_interfaces),
|
|
n_elements,
|
|
physical_extent,
|
|
set_aperture_diameter,
|
|
aperture_image,
|
|
exit_pupil_bounds,
|
|
};
|
|
|
|
Self { device, data }
|
|
}
|
|
}
|