use crate::bridge::frame_cache::stone_width::StoneWidthCache;
use glam::Vec3;
use indicatrix::{
geometry::plane::GpuFacetPlane,
optics::materials::{GemMaterial, OpticalCharacter},
};
pub fn resolve_material(
materials: &[GemMaterial],
custom_materials: &[GemMaterial],
material_name: &str,
) -> 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()
.unwrap_or_else(|| materials[0].clone())
}
#[must_use]
pub fn resolve_material_with_override(
materials: &[GemMaterial],
custom_materials: &[GemMaterial],
material_override: Option<&GemMaterial>,
material_name: &str,
) -> GemMaterial {
material_override
.cloned()
.unwrap_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,
active_planes: &[GpuFacetPlane],
width_cache: &mut StoneWidthCache,
) -> 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) = width_cache.ensure(active_planes)
&& 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
}
pub struct MaterialSources<'a> {
pub materials: &'a [GemMaterial],
pub custom_materials: &'a [GemMaterial],
pub material_override: Option<&'a GemMaterial>,
pub material_name: &'a str,
}
pub(in crate::bridge::render_thread) fn resolve_material_and_quality(
sources: &MaterialSources<'_>,
target_samples: u32,
overrides: &MaterialOverrides,
active_planes: &[GpuFacetPlane],
width_cache: &mut StoneWidthCache,
) -> (GemMaterial, u32) {
let current_mat = resolve_material_with_override(
sources.materials,
sources.custom_materials,
sources.material_override,
sources.material_name,
);
let current_mat = apply_material_overrides(current_mat, overrides, active_planes, width_cache);
let spp = (target_samples / 64).clamp(1, 8);
(current_mat, spp)
}