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 std::f64::consts::PI as PI_64;
|
||||||
|
|
||||||
use kioku::Arena;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
color::{Color, SpectralSample},
|
color::{Color, SpectralSample},
|
||||||
lerp::lerp_slice,
|
lerp::lerp_slice,
|
||||||
|
@ -13,24 +11,19 @@ use super::WorldLightSource;
|
||||||
|
|
||||||
// TODO: handle case where radius = 0.0.
|
// TODO: handle case where radius = 0.0.
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DistantDiskLight<'a> {
|
pub struct DistantDiskLight {
|
||||||
radii: &'a [f32],
|
radii: Vec<f32>,
|
||||||
directions: &'a [Vector],
|
directions: Vec<Vector>,
|
||||||
colors: &'a [Color],
|
colors: Vec<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DistantDiskLight<'a> {
|
impl DistantDiskLight {
|
||||||
pub fn new(
|
pub fn new(radii: &[f32], directions: &[Vector], colors: &[Color]) -> DistantDiskLight {
|
||||||
arena: &'a Arena,
|
|
||||||
radii: &[f32],
|
|
||||||
directions: &[Vector],
|
|
||||||
colors: &[Color],
|
|
||||||
) -> DistantDiskLight<'a> {
|
|
||||||
DistantDiskLight {
|
DistantDiskLight {
|
||||||
radii: arena.copy_slice(&radii),
|
radii: radii.into(),
|
||||||
directions: arena.copy_slice(&directions),
|
directions: directions.into(),
|
||||||
colors: arena.copy_slice(&colors),
|
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(
|
fn sample_from_point(
|
||||||
&self,
|
&self,
|
||||||
u: f32,
|
u: f32,
|
||||||
|
@ -64,9 +57,9 @@ impl<'a> WorldLightSource for DistantDiskLight<'a> {
|
||||||
time: f32,
|
time: f32,
|
||||||
) -> (SpectralSample, Vector, f32) {
|
) -> (SpectralSample, Vector, f32) {
|
||||||
// Calculate time interpolated values
|
// Calculate time interpolated values
|
||||||
let radius: f64 = lerp_slice(self.radii, time) as f64;
|
let radius: f64 = lerp_slice(&self.radii, time) as f64;
|
||||||
let direction = lerp_slice(self.directions, time);
|
let direction = lerp_slice(&self.directions, time);
|
||||||
let col = lerp_slice(self.colors, time);
|
let col = lerp_slice(&self.colors, time);
|
||||||
let solid_angle_inv = 1.0 / (2.0 * PI_64 * (1.0 - radius.cos()));
|
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
|
// 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 color::rec709_e_to_xyz;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::Camera, color::Color, light::WorldLightSource, math::Xform, renderer::Renderer,
|
camera::Camera, color::Color, math::Xform, renderer::Renderer, scene::Scene, scene::World,
|
||||||
scene::Scene, scene::World,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -153,7 +152,7 @@ pub fn parse_scene<'a>(
|
||||||
let camera = parse_camera(tree.iter_children_with_type("Camera").nth(0).unwrap())?;
|
let camera = parse_camera(tree.iter_children_with_type("Camera").nth(0).unwrap())?;
|
||||||
|
|
||||||
// Parse world
|
// 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
|
// Parse root scene assembly
|
||||||
let assembly = parse_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() {
|
if tree.is_internal() {
|
||||||
let background_color;
|
let background_color;
|
||||||
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
let mut lights: Vec<_> = Vec::new();
|
||||||
|
|
||||||
// Parse background shader
|
// Parse background shader
|
||||||
let bgs = {
|
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() {
|
for child in tree.iter_children() {
|
||||||
match *child {
|
match *child {
|
||||||
DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => {
|
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
|
// Build and return the world
|
||||||
return Ok(World {
|
return Ok(World {
|
||||||
background_color: background_color,
|
background_color: background_color,
|
||||||
lights: arena.copy_slice(&lights),
|
lights: lights,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return Err(PsyParseError::ExpectedInternalNode(
|
return Err(PsyParseError::ExpectedInternalNode(
|
||||||
|
|
|
@ -17,10 +17,7 @@ use super::{
|
||||||
DataTree,
|
DataTree,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_distant_disk_light<'a>(
|
pub fn parse_distant_disk_light<'a>(tree: &'a DataTree) -> Result<DistantDiskLight, PsyParseError> {
|
||||||
arena: &'a Arena,
|
|
||||||
tree: &'a DataTree,
|
|
||||||
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
|
||||||
if let DataTree::Internal { ref children, .. } = *tree {
|
if let DataTree::Internal { ref children, .. } = *tree {
|
||||||
let mut radii = Vec::new();
|
let mut radii = Vec::new();
|
||||||
let mut directions = 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 {
|
} else {
|
||||||
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
algorithm::weighted_choice,
|
algorithm::weighted_choice,
|
||||||
camera::Camera,
|
camera::Camera,
|
||||||
color::SpectralSample,
|
color::SpectralSample,
|
||||||
|
light::WorldLightSource,
|
||||||
math::{Normal, Point, Vector, XformFull},
|
math::{Normal, Point, Vector, XformFull},
|
||||||
surface::SurfaceIntersection,
|
surface::SurfaceIntersection,
|
||||||
};
|
};
|
||||||
|
@ -19,7 +20,7 @@ pub use self::{
|
||||||
pub struct Scene<'a> {
|
pub struct Scene<'a> {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
pub world: World<'a>,
|
pub world: World,
|
||||||
pub root: Assembly<'a>,
|
pub root: Assembly<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ impl<'a> Scene<'a> {
|
||||||
if n < wl_prob {
|
if n < wl_prob {
|
||||||
// World lights
|
// World lights
|
||||||
let n = n / wl_prob;
|
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) =
|
let (ss, sv, pdf) =
|
||||||
self.world.lights[i].sample_from_point(uvw.0, uvw.1, wavelength, time);
|
self.world.lights[i].sample_from_point(uvw.0, uvw.1, wavelength, time);
|
||||||
return SceneLightSample::Distant {
|
return SceneLightSample::Distant {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{color::Color, light::WorldLightSource};
|
use crate::{color::Color, light::DistantDiskLight};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct World<'a> {
|
pub struct World {
|
||||||
pub background_color: Color,
|
pub background_color: Color,
|
||||||
pub lights: &'a [&'a dyn WorldLightSource],
|
pub lights: Vec<DistantDiskLight>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user