Make World own its own memory, along with distant disk lights.
This commit is contained in:
parent
fc7b8da17d
commit
c603e24633
|
@ -1,7 +1,5 @@
|
|||
use std::f64::consts::PI as PI_64;
|
||||
|
||||
use kioku::Arena;
|
||||
|
||||
use crate::{
|
||||
color::{Color, SpectralSample},
|
||||
lerp::lerp_slice,
|
||||
|
@ -13,24 +11,19 @@ use super::WorldLightSource;
|
|||
|
||||
// TODO: handle case where radius = 0.0.
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DistantDiskLight<'a> {
|
||||
radii: &'a [f32],
|
||||
directions: &'a [Vector],
|
||||
colors: &'a [Color],
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DistantDiskLight {
|
||||
radii: Vec<f32>,
|
||||
directions: Vec<Vector>,
|
||||
colors: Vec<Color>,
|
||||
}
|
||||
|
||||
impl<'a> DistantDiskLight<'a> {
|
||||
pub fn new(
|
||||
arena: &'a Arena,
|
||||
radii: &[f32],
|
||||
directions: &[Vector],
|
||||
colors: &[Color],
|
||||
) -> DistantDiskLight<'a> {
|
||||
impl DistantDiskLight {
|
||||
pub fn new(radii: &[f32], directions: &[Vector], colors: &[Color]) -> DistantDiskLight {
|
||||
DistantDiskLight {
|
||||
radii: arena.copy_slice(&radii),
|
||||
directions: arena.copy_slice(&directions),
|
||||
colors: arena.copy_slice(&colors),
|
||||
radii: radii.into(),
|
||||
directions: directions.into(),
|
||||
colors: colors.into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +48,7 @@ impl<'a> DistantDiskLight<'a> {
|
|||
// }
|
||||
}
|
||||
|
||||
impl<'a> WorldLightSource for DistantDiskLight<'a> {
|
||||
impl WorldLightSource for DistantDiskLight {
|
||||
fn sample_from_point(
|
||||
&self,
|
||||
u: f32,
|
||||
|
@ -64,9 +57,9 @@ impl<'a> WorldLightSource for DistantDiskLight<'a> {
|
|||
time: f32,
|
||||
) -> (SpectralSample, Vector, f32) {
|
||||
// Calculate time interpolated values
|
||||
let radius: f64 = lerp_slice(self.radii, time) as f64;
|
||||
let direction = lerp_slice(self.directions, time);
|
||||
let col = lerp_slice(self.colors, time);
|
||||
let radius: f64 = lerp_slice(&self.radii, time) as f64;
|
||||
let direction = lerp_slice(&self.directions, time);
|
||||
let col = lerp_slice(&self.colors, time);
|
||||
let solid_angle_inv = 1.0 / (2.0 * PI_64 * (1.0 - radius.cos()));
|
||||
|
||||
// Create a coordinate system from the vector pointing at the center of
|
||||
|
|
|
@ -9,8 +9,7 @@ use kioku::Arena;
|
|||
use color::rec709_e_to_xyz;
|
||||
|
||||
use crate::{
|
||||
camera::Camera, color::Color, light::WorldLightSource, math::Xform, renderer::Renderer,
|
||||
scene::Scene, scene::World,
|
||||
camera::Camera, color::Color, math::Xform, renderer::Renderer, scene::Scene, scene::World,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -153,7 +152,7 @@ pub fn parse_scene<'a>(
|
|||
let camera = parse_camera(tree.iter_children_with_type("Camera").nth(0).unwrap())?;
|
||||
|
||||
// Parse world
|
||||
let world = parse_world(arena, tree.iter_children_with_type("World").nth(0).unwrap())?;
|
||||
let world = parse_world(tree.iter_children_with_type("World").nth(0).unwrap())?;
|
||||
|
||||
// Parse root scene assembly
|
||||
let assembly = parse_assembly(
|
||||
|
@ -440,10 +439,10 @@ fn parse_camera<'a>(tree: &'a DataTree) -> Result<Camera, PsyParseError> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_world<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<World<'a>, PsyParseError> {
|
||||
fn parse_world(tree: &DataTree) -> Result<World, PsyParseError> {
|
||||
if tree.is_internal() {
|
||||
let background_color;
|
||||
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
||||
let mut lights: Vec<_> = Vec::new();
|
||||
|
||||
// Parse background shader
|
||||
let bgs = {
|
||||
|
@ -519,7 +518,7 @@ fn parse_world<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<World<'a>, Ps
|
|||
for child in tree.iter_children() {
|
||||
match *child {
|
||||
DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => {
|
||||
lights.push(arena.alloc(parse_distant_disk_light(arena, child)?));
|
||||
lights.push(parse_distant_disk_light(child)?);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
@ -529,7 +528,7 @@ fn parse_world<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<World<'a>, Ps
|
|||
// Build and return the world
|
||||
return Ok(World {
|
||||
background_color: background_color,
|
||||
lights: arena.copy_slice(&lights),
|
||||
lights: lights,
|
||||
});
|
||||
} else {
|
||||
return Err(PsyParseError::ExpectedInternalNode(
|
||||
|
|
|
@ -17,10 +17,7 @@ use super::{
|
|||
DataTree,
|
||||
};
|
||||
|
||||
pub fn parse_distant_disk_light<'a>(
|
||||
arena: &'a Arena,
|
||||
tree: &'a DataTree,
|
||||
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
||||
pub fn parse_distant_disk_light<'a>(tree: &'a DataTree) -> Result<DistantDiskLight, PsyParseError> {
|
||||
if let DataTree::Internal { ref children, .. } = *tree {
|
||||
let mut radii = Vec::new();
|
||||
let mut directions = Vec::new();
|
||||
|
@ -77,7 +74,7 @@ pub fn parse_distant_disk_light<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
|
||||
return Ok(DistantDiskLight::new(&radii, &directions, &colors));
|
||||
} else {
|
||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
algorithm::weighted_choice,
|
||||
camera::Camera,
|
||||
color::SpectralSample,
|
||||
light::WorldLightSource,
|
||||
math::{Normal, Point, Vector, XformFull},
|
||||
surface::SurfaceIntersection,
|
||||
};
|
||||
|
@ -19,7 +20,7 @@ pub use self::{
|
|||
pub struct Scene<'a> {
|
||||
pub name: Option<String>,
|
||||
pub camera: Camera,
|
||||
pub world: World<'a>,
|
||||
pub world: World,
|
||||
pub root: Assembly<'a>,
|
||||
}
|
||||
|
||||
|
@ -67,7 +68,7 @@ impl<'a> Scene<'a> {
|
|||
if n < wl_prob {
|
||||
// World lights
|
||||
let n = n / wl_prob;
|
||||
let (i, p) = weighted_choice(self.world.lights, n, |l| l.approximate_energy());
|
||||
let (i, p) = weighted_choice(&self.world.lights, n, |l| l.approximate_energy());
|
||||
let (ss, sv, pdf) =
|
||||
self.world.lights[i].sample_from_point(uvw.0, uvw.1, wavelength, time);
|
||||
return SceneLightSample::Distant {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{color::Color, light::WorldLightSource};
|
||||
use crate::{color::Color, light::DistantDiskLight};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct World<'a> {
|
||||
pub struct World {
|
||||
pub background_color: Color,
|
||||
pub lights: &'a [&'a dyn WorldLightSource],
|
||||
pub lights: Vec<DistantDiskLight>,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user