Permalink
Browse files

Implement an OrthographicCamera.

  • Loading branch information...
wahn committed Nov 19, 2018
1 parent 323a1ac commit dffa1a280e28b517473384e80d68532c9083ef2d
Showing with 1,212 additions and 615 deletions.
  1. +1 −0 src/cameras/mod.rs
  2. +267 −0 src/cameras/orthographic.rs
  3. +8 −1 src/core/api.rs
  4. +936 −614 src/core/transform.rs
@@ -17,4 +17,5 @@
//!
//! ![Perspective Camera](/doc/img/wikipedia_perspective_camera.png)

pub mod orthographic;
pub mod perspective;
@@ -0,0 +1,267 @@
// std
use std;
use std::sync::Arc;
// pbrt
use core::camera::{Camera, CameraSample};
use core::film::Film;
use core::geometry::vec3_normalize;
use core::geometry::{
Bounds2f, Point2f, Point3f, Ray, RayDifferential, Vector3f,
};
use core::interaction::InteractionCommon;
use core::light::VisibilityTester;
use core::medium::Medium;
use core::paramset::ParamSet;
use core::pbrt::lerp;
use core::pbrt::{Float, Spectrum};
use core::sampling::concentric_sample_disk;
use core::transform::{AnimatedTransform, Transform};

// see orthographic.h

pub struct OrthographicCamera {
// inherited from Camera (see camera.h)
pub camera_to_world: AnimatedTransform,
pub shutter_open: Float,
pub shutter_close: Float,
pub film: Arc<Film>,
pub medium: Option<Arc<Medium + Send + Sync>>,
// inherited from ProjectiveCamera (see camera.h)
pub camera_to_screen: Transform,
pub raster_to_camera: Transform,
pub screen_to_raster: Transform,
pub raster_to_screen: Transform,
pub lens_radius: Float,
pub focal_distance: Float,
// private data (see orthographic.h)
pub dx_camera: Vector3f,
pub dy_camera: Vector3f,
}

impl OrthographicCamera {
pub fn new(
camera_to_world: AnimatedTransform,
screen_window: Bounds2f,
shutter_open: Float,
shutter_close: Float,
lens_radius: Float,
focal_distance: Float,
film: Arc<Film>,
medium: Option<Arc<Medium + Send + Sync>>,
) -> Self {
// see orthographic.cpp
let camera_to_screen: Transform = Transform::orthographic(0.0 as Float, 1.0 as Float);
// see camera.h
// compute projective camera screen transformations
let scale1 = Transform::scale(
film.full_resolution.x as Float,
film.full_resolution.y as Float,
1.0,
);
let scale2 = Transform::scale(
1.0 / (screen_window.p_max.x - screen_window.p_min.x),
1.0 / (screen_window.p_min.y - screen_window.p_max.y),
1.0,
);
let translate = Transform::translate(&Vector3f {
x: -screen_window.p_min.x,
y: -screen_window.p_max.y,
z: 0.0,
});
let screen_to_raster = scale1 * scale2 * translate;
let raster_to_screen = Transform::inverse(&screen_to_raster);
let raster_to_camera = Transform::inverse(&camera_to_screen) * raster_to_screen;
// see orthographic.cpp
// compute differential changes in origin for orthographic camera rays
let dx_camera: Vector3f = raster_to_camera.transform_vector(&Vector3f {
x: 1.0,
y: 0.0,
z: 0.0,
});
let dy_camera: Vector3f = raster_to_camera.transform_vector(&Vector3f {
x: 0.0,
y: 1.0,
z: 0.0,
});
OrthographicCamera {
camera_to_world: camera_to_world,
shutter_open: shutter_open,
shutter_close: shutter_close,
film: film,
medium: medium,
camera_to_screen: camera_to_screen,
raster_to_camera: raster_to_camera,
screen_to_raster: screen_to_raster,
raster_to_screen: raster_to_screen,
lens_radius: lens_radius,
focal_distance: focal_distance,
dx_camera: dx_camera,
dy_camera: dy_camera,
}
}
pub fn create(
params: &ParamSet,
cam2world: AnimatedTransform,
film: Arc<Film>,
medium: Option<Arc<Medium + Send + Sync>>,
) -> Arc<Camera + Send + Sync> {
let shutteropen: Float = params.find_one_float(String::from("shutteropen"), 0.0);
let shutterclose: Float = params.find_one_float(String::from("shutterclose"), 1.0);
// TODO: std::swap(shutterclose, shutteropen);
assert!(shutterclose >= shutteropen);
let lensradius: Float = params.find_one_float(String::from("lensradius"), 0.0);
let focaldistance: Float = params.find_one_float(String::from("focaldistance"), 1e6);
let frame: Float = params.find_one_float(
String::from("frameaspectratio"),
(film.full_resolution.x as Float) / (film.full_resolution.y as Float),
);
let mut screen: Bounds2f = Bounds2f::default();
if frame > 1.0 {
screen.p_min.x = -frame;
screen.p_max.x = frame;
screen.p_min.y = -1.0;
screen.p_max.y = 1.0;
} else {
screen.p_min.x = -1.0;
screen.p_max.x = 1.0;
screen.p_min.y = -1.0 / frame;
screen.p_max.y = 1.0 / frame;
}
let sw: Vec<Float> = params.find_float(String::from("screenwindow"));
if sw.len() > 0_usize {
if sw.len() == 4 {
screen.p_min.x = sw[0];
screen.p_max.x = sw[1];
screen.p_min.y = sw[2];
screen.p_max.y = sw[3];
} else {
panic!("\"screenwindow\" should have four values");
}
}
let camera = Arc::new(OrthographicCamera::new(
cam2world,
screen,
shutteropen,
shutterclose,
lensradius,
focaldistance,
film,
medium,
));
camera
}
}

impl Camera for OrthographicCamera {
fn generate_ray_differential(&self, sample: &CameraSample, ray: &mut Ray) -> Float {
// TODO: ProfilePhase prof(Prof::GenerateCameraRay);
// compute raster and camera sample positions
let p_film: Point3f = Point3f {
x: sample.p_film.x,
y: sample.p_film.y,
z: 0.0,
};
let p_camera: Point3f = self.raster_to_camera.transform_point(&p_film);
let mut diff: RayDifferential = RayDifferential {
rx_origin: ray.o + self.dx_camera,
ry_origin: ray.o + self.dy_camera,
rx_direction: ray.d,
ry_direction: ray.d,
};
// *ray = RayDifferential(pCamera, Vector3f(0, 0, 1));
let mut in_ray: Ray = Ray {
o: p_camera,
d: Vector3f {
x: 0.0,
y: 0.0,
z: 1.0,
},
t_max: std::f32::INFINITY,
time: lerp(sample.time, self.shutter_open, self.shutter_close),
medium: None,
differential: Some(diff),
};
// modify ray for depth of field
if self.lens_radius > 0.0 as Float {
// sample point on lens
let p_lens: Point2f = concentric_sample_disk(&sample.p_lens) * self.lens_radius;
// compute point on plane of focus
let ft: Float = self.focal_distance / in_ray.d.z;
let p_focus: Point3f = in_ray.position(ft);
// update ray for effect of lens
in_ray.o = Point3f {
x: p_lens.x,
y: p_lens.y,
z: 0.0 as Float,
};
in_ray.d = vec3_normalize(&(p_focus - in_ray.o));
}
// compute offset rays for _OrthographicCamera_ ray differentials
if self.lens_radius > 0.0 as Float {
// compute _OrthographicCamera_ ray differentials accounting for lens

// sample point on lens
let p_lens: Point2f = concentric_sample_disk(&sample.p_lens) * self.lens_radius;
let ft: Float = self.focal_distance / ray.d.z;
let p_focus: Point3f = p_camera
+ self.dx_camera
+ (Vector3f {
x: 0.0 as Float,
y: 0.0 as Float,
z: 1.0 as Float,
} * ft);
diff.rx_origin = Point3f {
x: p_lens.x,
y: p_lens.y,
z: 0.0 as Float,
};
diff.rx_direction = vec3_normalize(&(p_focus - diff.rx_origin));
let p_focus: Point3f = p_camera + self.dy_camera + (Vector3f {
x: 0.0 as Float,
y: 0.0 as Float,
z: 1.0 as Float,
} * ft);
diff.ry_origin = Point3f {
x: p_lens.x,
y: p_lens.y,
z: 0.0 as Float,
};
diff.ry_direction = vec3_normalize(&(p_focus - diff.ry_origin));
// replace differential
in_ray.differential = Some(diff);
}
// ray->medium = medium;
if let Some(ref medium_arc) = self.medium {
in_ray.medium = Some(medium_arc.clone());
} else {
in_ray.medium = None;
}
*ray = self.camera_to_world.transform_ray(&in_ray);
1.0
}
fn we(&self, _ray: &Ray, _p_raster2: Option<&mut Point2f>) -> Spectrum {
panic!("camera::we() is not implemented!");
// Spectrum::default()
}
fn pdf_we(&self, _ray: &Ray) -> (Float, Float) {
// let mut pdf_pos: Float = 0.0;
// let mut pdf_dir: Float = 0.0;
panic!("camera::pdf_we() is not implemented!");
// (pdf_pos, pdf_dir)
}
fn sample_wi(
&self,
_iref: &InteractionCommon,
_u: &Point2f,
_wi: &mut Vector3f,
_pdf: &mut Float,
_p_raster: &mut Point2f,
_vis: &mut VisibilityTester,
) -> Spectrum {
panic!("camera::sample_wi() is not implemented!");
// Spectrum::default()
}
fn get_film(&self) -> Arc<Film> {
self.film.clone()
}
}
@@ -5,6 +5,7 @@ use std::path::PathBuf;
use std::sync::Arc;
// pbrt
use accelerators::bvh::{BVHAccel, SplitMethod};
use cameras::orthographic::OrthographicCamera;
use cameras::perspective::PerspectiveCamera;
use core::camera::Camera;
use core::film::Film;
@@ -1679,7 +1680,13 @@ pub fn pbrt_cleanup(api_state: &ApiState) {
);
some_camera = Some(camera);
} else if api_state.render_options.camera_name == String::from("orthographic") {
println!("TODO: CreateOrthographicCamera");
let camera: Arc<Camera + Send + Sync> = OrthographicCamera::create(
&api_state.render_options.camera_params,
animated_cam_to_world,
film,
medium_interface.outside,
);
some_camera = Some(camera);
} else if api_state.render_options.camera_name == String::from("realistic") {
println!("TODO: CreateRealisticCamera");
} else if api_state.render_options.camera_name == String::from("environment") {
Oops, something went wrong.

0 comments on commit dffa1a2

Please sign in to comment.