use crate::optics::materials::{GemMaterial, OpticalCharacter};
use glam::Vec3;
#[must_use]
pub fn resolve_material(
materials: &[GemMaterial],
custom_materials: &[GemMaterial],
material_name: &str,
) -> Option<GemMaterial> {
custom_materials
.iter()
.find(|m| m.name.eq_ignore_ascii_case(material_name))
.or_else(|| {
materials
.iter()
.find(|m| m.name.eq_ignore_ascii_case(material_name))
})
.cloned()
}
#[must_use]
pub fn resolve_material_with_override(
materials: &[GemMaterial],
custom_materials: &[GemMaterial],
material_override: Option<&GemMaterial>,
material_name: &str,
) -> Option<GemMaterial> {
material_override
.cloned()
.or_else(|| resolve_material(materials, custom_materials, material_name))
}
#[derive(Clone, Copy)]
pub struct MaterialOverrides {
pub inclusion_sigma_s: f32,
pub c_axis_override: Option<Vec3>,
pub edge_rounding_radius: f32,
pub stone_width_mm: f32,
}
#[must_use]
pub fn apply_material_overrides(
material: GemMaterial,
overrides: &MaterialOverrides,
model_width: Option<f64>,
) -> GemMaterial {
let material = if overrides.inclusion_sigma_s > 0.0 {
material.with_scattering_amount(overrides.inclusion_sigma_s)
} else {
material
};
let mut material = material;
if let Some(axis) = overrides.c_axis_override
&& material.optical_character != OpticalCharacter::Isotropic
{
material.c_axis = axis;
}
let material = if overrides.edge_rounding_radius > 0.0 {
material.with_edge_rounding(overrides.edge_rounding_radius)
} else {
material
};
if overrides.stone_width_mm > 0.0
&& let Some(model_width) = model_width
&& model_width > 1e-9
{
let scale = (f64::from(overrides.stone_width_mm) / model_width) as f32;
if scale.is_finite() && scale > 0.0 {
return material.with_absorption_path_scale(scale);
}
}
material
}