rs_pbrt/cameras/
orthographic.rs

1// std
2use std::cell::Cell;
3use std::sync::Arc;
4// pbrt
5use crate::core::camera::{Camera, CameraSample};
6use crate::core::film::Film;
7use crate::core::geometry::{Bounds2f, Point2f, Point3f, Ray, RayDifferential, Vector3f};
8use crate::core::interaction::InteractionCommon;
9use crate::core::light::VisibilityTester;
10use crate::core::medium::Medium;
11use crate::core::paramset::ParamSet;
12use crate::core::pbrt::lerp;
13use crate::core::pbrt::{Float, Spectrum};
14use crate::core::sampling::concentric_sample_disk;
15use crate::core::transform::{AnimatedTransform, Transform};
16
17// see orthographic.h
18
19pub struct OrthographicCamera {
20    // inherited from Camera (see camera.h)
21    pub camera_to_world: AnimatedTransform,
22    pub shutter_open: Float,
23    pub shutter_close: Float,
24    pub film: Arc<Film>,
25    pub medium: Option<Arc<Medium>>,
26    // inherited from ProjectiveCamera (see camera.h)
27    pub camera_to_screen: Transform,
28    pub raster_to_camera: Transform,
29    pub screen_to_raster: Transform,
30    pub raster_to_screen: Transform,
31    pub lens_radius: Float,
32    pub focal_distance: Float,
33    // private data (see orthographic.h)
34    pub dx_camera: Vector3f,
35    pub dy_camera: Vector3f,
36}
37
38impl OrthographicCamera {
39    pub fn new(
40        camera_to_world: AnimatedTransform,
41        screen_window: Bounds2f,
42        shutter_open: Float,
43        shutter_close: Float,
44        lens_radius: Float,
45        focal_distance: Float,
46        film: Arc<Film>,
47        medium: Option<Arc<Medium>>,
48    ) -> Self {
49        // see orthographic.cpp
50        let camera_to_screen: Transform = Transform::orthographic(0.0 as Float, 1.0 as Float);
51        // see camera.h
52        // compute projective camera screen transformations
53        let scale1 = Transform::scale(
54            film.full_resolution.x as Float,
55            film.full_resolution.y as Float,
56            1.0,
57        );
58        let scale2 = Transform::scale(
59            1.0 / (screen_window.p_max.x - screen_window.p_min.x),
60            1.0 / (screen_window.p_min.y - screen_window.p_max.y),
61            1.0,
62        );
63        let translate = Transform::translate(&Vector3f {
64            x: -screen_window.p_min.x,
65            y: -screen_window.p_max.y,
66            z: 0.0,
67        });
68        let screen_to_raster = scale1 * scale2 * translate;
69        let raster_to_screen = Transform::inverse(&screen_to_raster);
70        let raster_to_camera = Transform::inverse(&camera_to_screen) * raster_to_screen;
71        // see orthographic.cpp
72        // compute differential changes in origin for orthographic camera rays
73        let dx_camera: Vector3f = raster_to_camera.transform_vector(&Vector3f {
74            x: 1.0,
75            y: 0.0,
76            z: 0.0,
77        });
78        let dy_camera: Vector3f = raster_to_camera.transform_vector(&Vector3f {
79            x: 0.0,
80            y: 1.0,
81            z: 0.0,
82        });
83        OrthographicCamera {
84            camera_to_world,
85            shutter_open,
86            shutter_close,
87            film,
88            medium,
89            camera_to_screen,
90            raster_to_camera,
91            screen_to_raster,
92            raster_to_screen,
93            lens_radius,
94            focal_distance,
95            dx_camera,
96            dy_camera,
97        }
98    }
99    pub fn create(
100        params: &ParamSet,
101        cam2world: AnimatedTransform,
102        film: Arc<Film>,
103        medium: Option<Arc<Medium>>,
104    ) -> Arc<Camera> {
105        let shutteropen: Float = params.find_one_float("shutteropen", 0.0);
106        let shutterclose: Float = params.find_one_float("shutterclose", 1.0);
107        // TODO: std::swap(shutterclose, shutteropen);
108        assert!(shutterclose >= shutteropen);
109        let lensradius: Float = params.find_one_float("lensradius", 0.0);
110        let focaldistance: Float = params.find_one_float("focaldistance", 1e6);
111        let frame: Float = params.find_one_float(
112            "frameaspectratio",
113            (film.full_resolution.x as Float) / (film.full_resolution.y as Float),
114        );
115        let mut screen: Bounds2f = Bounds2f::default();
116        if frame > 1.0 {
117            screen.p_min.x = -frame;
118            screen.p_max.x = frame;
119            screen.p_min.y = -1.0;
120            screen.p_max.y = 1.0;
121        } else {
122            screen.p_min.x = -1.0;
123            screen.p_max.x = 1.0;
124            screen.p_min.y = -1.0 / frame;
125            screen.p_max.y = 1.0 / frame;
126        }
127        let sw: Vec<Float> = params.find_float("screenwindow");
128        if !sw.is_empty() {
129            if sw.len() == 4 {
130                screen.p_min.x = sw[0];
131                screen.p_max.x = sw[1];
132                screen.p_min.y = sw[2];
133                screen.p_max.y = sw[3];
134            } else {
135                panic!("\"screenwindow\" should have four values");
136            }
137        }
138        Arc::new(Camera::Orthographic(Box::new(OrthographicCamera::new(
139            cam2world,
140            screen,
141            shutteropen,
142            shutterclose,
143            lensradius,
144            focaldistance,
145            film,
146            medium,
147        ))))
148    }
149    // Camera
150    pub fn generate_ray_differential(&self, sample: &CameraSample, ray: &mut Ray) -> Float {
151        // TODO: ProfilePhase prof(Prof::GenerateCameraRay);
152        // compute raster and camera sample positions
153        let p_film: Point3f = Point3f {
154            x: sample.p_film.x,
155            y: sample.p_film.y,
156            z: 0.0,
157        };
158        let p_camera: Point3f = self.raster_to_camera.transform_point(&p_film);
159        *ray = Ray {
160            o: p_camera,
161            d: Vector3f {
162                x: 0.0,
163                y: 0.0,
164                z: 1.0,
165            },
166            t_max: Cell::new(std::f32::INFINITY),
167            time: lerp(sample.time, self.shutter_open, self.shutter_close),
168            medium: None,
169            differential: None,
170        };
171        // modify ray for depth of field
172        if self.lens_radius > 0.0 as Float {
173            // sample point on lens
174            let p_lens: Point2f = concentric_sample_disk(&sample.p_lens) * self.lens_radius;
175            // compute point on plane of focus
176            let ft: Float = self.focal_distance / ray.d.z;
177            let p_focus: Point3f = ray.position(ft);
178            // update ray for effect of lens
179            ray.o = Point3f {
180                x: p_lens.x,
181                y: p_lens.y,
182                z: 0.0 as Float,
183            };
184            ray.d = (p_focus - ray.o).normalize();
185        }
186        // compute offset rays for _OrthographicCamera_ ray differentials
187        if self.lens_radius > 0.0 as Float {
188            // compute _OrthographicCamera_ ray differentials accounting for lens
189
190            // sample point on lens
191            let p_lens: Point2f = concentric_sample_disk(&sample.p_lens) * self.lens_radius;
192            let ft: Float = self.focal_distance / ray.d.z;
193            let p_focus: Point3f = p_camera
194                + self.dx_camera
195                + (Vector3f {
196                    x: 0.0 as Float,
197                    y: 0.0 as Float,
198                    z: 1.0 as Float,
199                } * ft);
200            let rx_origin = Point3f {
201                x: p_lens.x,
202                y: p_lens.y,
203                z: 0.0 as Float,
204            };
205            let ry_origin = Point3f {
206                x: p_lens.x,
207                y: p_lens.y,
208                z: 0.0 as Float,
209            };
210            let diff = RayDifferential {
211                rx_origin,
212                rx_direction: (p_focus - rx_origin).normalize(),
213                ry_origin,
214                ry_direction: (p_focus - ry_origin).normalize(),
215            };
216            // replace differential
217            ray.differential = Some(diff);
218        } else {
219            let diff: RayDifferential = RayDifferential {
220                rx_origin: ray.o + self.dx_camera,
221                ry_origin: ray.o + self.dy_camera,
222                rx_direction: ray.d,
223                ry_direction: ray.d,
224            };
225            ray.differential = Some(diff);
226        }
227        // ray->medium = medium;
228        if let Some(ref medium_arc) = self.medium {
229            ray.medium = Some(medium_arc.clone());
230        } else {
231            ray.medium = None;
232        }
233        *ray = self.camera_to_world.transform_ray(ray);
234        1.0
235    }
236    pub fn we(&self, _ray: &Ray, _p_raster2: Option<&mut Point2f>) -> Spectrum {
237        panic!("camera::we() is not implemented!");
238        // Spectrum::default()
239    }
240    pub fn pdf_we(&self, _ray: &Ray) -> (Float, Float) {
241        // let mut pdf_pos: Float = 0.0;
242        // let mut pdf_dir: Float = 0.0;
243        panic!("camera::pdf_we() is not implemented!");
244        // (pdf_pos, pdf_dir)
245    }
246    pub fn sample_wi(
247        &self,
248        _iref: &InteractionCommon,
249        _lens_intr: &mut InteractionCommon,
250        _u: Point2f,
251        _wi: &mut Vector3f,
252        _pdf: &mut Float,
253        _p_raster: &mut Point2f,
254        _vis: &mut VisibilityTester,
255    ) -> Spectrum {
256        panic!("camera::sample_wi() is not implemented!");
257        // Spectrum::default()
258    }
259    pub fn get_shutter_open(&self) -> Float {
260        self.shutter_open
261    }
262    pub fn get_shutter_close(&self) -> Float {
263        self.shutter_close
264    }
265    pub fn get_film(&self) -> Arc<Film> {
266        self.film.clone()
267    }
268}