pub use concinnity_asset::{SDF_PARAMS_LEN, SdfVolume};
use crate::ecs::asset_id::AssetId;
use crate::ecs::{Component, PayloadLocator};
pub const SDF_MAX_STEPS_CEILING: u32 = 256;
pub const SDF_MAX_STEPS_FLOOR: u32 = 8;
impl Component for SdfVolume {
const NAME: &'static str = "SdfVolume";
fn from_baked(bytes: &[u8]) -> Result<Self, crate::result::CnResult> {
Ok(crate::blob::decode_exact(bytes)?)
}
fn inject_name(&mut self, id: AssetId) {
self.asset_id = id;
}
fn inject_locator(&mut self, locator: PayloadLocator) {
self.locator = Some(locator);
}
}
pub fn sdf_volume_blob_indices(
ctx: &crate::ecs::PipelineContext,
) -> alloc::collections::BTreeSet<u32> {
ctx.query::<SdfVolume>()
.filter_map(|v| v.locator.as_ref().map(|l| l.blob_index))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_are_sensible() {
let v = SdfVolume::default();
assert_eq!(v.centre, [0.0, 0.0, 0.0]);
assert_eq!(v.extent, [1.0, 1.0, 1.0]);
assert_eq!(v.max_gradient, 1.0);
assert_eq!(v.max_steps, 64);
assert_eq!(v.max_distance, 30.0);
assert!(v.receive_shadows);
assert!(!v.cast_shadows);
assert!(v.visible);
assert_eq!(v.params.len(), SDF_PARAMS_LEN);
assert_eq!(v.cone_ratio(), 1.0);
}
#[test]
fn cone_ratio_inverts_gradient() {
let v = SdfVolume {
max_gradient: 2.0,
..Default::default()
};
assert!((v.cone_ratio() - 0.5).abs() < 1e-6);
}
#[test]
fn volumetric_default_is_off() {
let v = SdfVolume::default();
assert!(!v.volumetric);
}
}