use crate::bridge::frame_cache::stone_width::StoneWidthCache;
pub use indicatrix::render_setup::{
MaterialOverrides, resolve_material, resolve_material_with_override,
};
use indicatrix::{geometry::plane::GpuFacetPlane, optics::materials::GemMaterial, render_setup};
#[must_use]
pub fn apply_material_overrides(
material: GemMaterial,
overrides: &MaterialOverrides,
active_planes: &[GpuFacetPlane],
width_cache: &mut StoneWidthCache,
) -> GemMaterial {
let model_width = if render_setup::needs_model_width(&material) {
width_cache.ensure(active_planes)
} else {
None
};
render_setup::apply_material_overrides(material, overrides, model_width)
}
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,
)
.unwrap_or_else(GemMaterial::diamond);
let current_mat = apply_material_overrides(current_mat, overrides, active_planes, width_cache);
let spp = (target_samples / 64).clamp(1, 8);
(current_mat, spp)
}
#[cfg(test)]
mod tests {
use super::*;
use indicatrix::geometry::cuts::StandardGemCuts;
#[test]
fn the_live_material_equals_the_scoring_material_for_a_sized_stone() {
let planes = StandardGemCuts::standard_round_brilliant();
let builtins = GemMaterial::all_materials();
let banded = GemMaterial::sapphire().with_body_color_bands(&[[550.0, 60.0, 0.3]], 1.0);
for (name, override_material) in [("Emerald", None), ("Sapphire", Some(&banded))] {
for stone_width_mm in [0.0_f32, 10.87] {
let sources = MaterialSources {
materials: &builtins,
custom_materials: &[],
material_override: override_material,
material_name: name,
};
let overrides = MaterialOverrides {
inclusion_sigma_s: 0.0,
c_axis_override: None,
edge_rounding_radius: 0.0,
stone_width_mm,
};
let (live, _) = resolve_material_and_quality(
&sources,
512,
&overrides,
&planes,
&mut StoneWidthCache::new(),
);
let bare = resolve_material_with_override(&builtins, &[], override_material, name)
.expect("resolves");
assert_eq!(
live,
render_setup::material_for_stone(bare, stone_width_mm, &planes),
"{name} at {stone_width_mm} mm"
);
}
}
}
}