83 lines
2.5 KiB
Rust
83 lines
2.5 KiB
Rust
use crate::core::camera::{CameraBase, CameraRay, CameraTransform};
|
|
use crate::core::film::Film;
|
|
use crate::core::geometry::{Bounds2f, Point2f, Point3f, Ray, Vector3f, spherical_direction};
|
|
use crate::core::medium::Medium;
|
|
use crate::core::pbrt::{Float, PI};
|
|
use crate::core::sampler::CameraSample;
|
|
use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
|
use crate::utils::math::{equal_area_square_to_sphere, wrap_equal_area_square};
|
|
use std::sync::Arc;
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
pub enum Mapping {
|
|
EquiRectangular,
|
|
EqualArea,
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct SphericalCamera {
|
|
pub mapping: Mapping,
|
|
pub base: CameraBase,
|
|
}
|
|
|
|
#[cfg(not(target_os = "cuda"))]
|
|
impl SphericalCamera {
|
|
pub fn init_metadata(&self, metadata: &mut crate::image::ImageMetadata) {
|
|
self.base.init_metadata(metadata)
|
|
}
|
|
}
|
|
|
|
impl CameraTrait for SphericalCamera {
|
|
fn base(&self) -> &CameraBase {
|
|
&self.base
|
|
}
|
|
|
|
fn get_film(&self) -> &Film {
|
|
#[cfg(not(target_os = "cuda"))]
|
|
{
|
|
if self.base.film.is_null() {
|
|
panic!(
|
|
"FilmBase error: PixelSensor pointer is null. This should have been checked during construction."
|
|
);
|
|
}
|
|
}
|
|
unsafe { &*self.base.film }
|
|
}
|
|
|
|
fn generate_ray(
|
|
&self,
|
|
sample: CameraSample,
|
|
_lamdba: &SampledWavelengths,
|
|
) -> Option<CameraRay> {
|
|
// Compute spherical camera ray direction
|
|
let film = self.get_film();
|
|
let mut uv = Point2f::new(
|
|
sample.p_film.x() / film.full_resolution().x() as Float,
|
|
sample.p_film.y() / film.full_resolution().y() as Float,
|
|
);
|
|
let dir: Vector3f;
|
|
if self.mapping == Mapping::EquiRectangular {
|
|
// Compute ray direction using equirectangular mapping
|
|
let theta = PI * uv[1];
|
|
let phi = 2. * PI * uv[0];
|
|
dir = spherical_direction(theta.sin(), theta.cos(), phi);
|
|
} else {
|
|
// Compute ray direction using equal area mapping
|
|
uv = wrap_equal_area_square(&mut uv);
|
|
dir = equal_area_square_to_sphere(uv);
|
|
}
|
|
std::mem::swap(&mut dir.y(), &mut dir.z());
|
|
|
|
let ray = Ray::new(
|
|
Point3f::new(0., 0., 0.),
|
|
dir,
|
|
Some(self.sample_time(sample.time)),
|
|
self.base().medium.clone(),
|
|
);
|
|
Some(CameraRay {
|
|
ray: self.render_from_camera(&ray, &mut None),
|
|
weight: SampledSpectrum::default(),
|
|
})
|
|
}
|
|
}
|