use super::{MIN_LABEL_SPAN, SolidRasterizer, SolidStyle, diagram2d, render::project};
use glam::DVec3;
use indicatrix::{geometry::stone_metrics::SolidMesh, optics::raytracer::Camera};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum EdgePass {
Ordinary,
Hovered,
MultiSelected,
Selected,
SelectedFacet,
Pending,
}
impl SolidRasterizer {
pub(super) fn draw_facet_edges(
&mut self,
edge_ranges: &[(usize, usize, usize)],
edge_points: &[(f32, f32, f32)],
style: &SolidStyle,
) {
let is_selected = |facet_id: usize| style.selected.get(facet_id).copied().unwrap_or(false);
let is_pending = |facet_id: usize| style.pending.get(facet_id).copied().unwrap_or(false);
let is_hovered = |facet_id: usize| style.hovered == Some(facet_id as u32);
let is_selected_facet = |facet_id: usize| style.selected_facet == Some(facet_id as u32);
let is_multi_selected = |facet_id: usize| style.multi_selected.contains(&(facet_id as u32));
for pass in [
EdgePass::Ordinary,
EdgePass::Hovered,
EdgePass::MultiSelected,
EdgePass::Selected,
EdgePass::SelectedFacet,
EdgePass::Pending,
] {
for &(facet_id, start, count) in edge_ranges {
let selected = is_selected(facet_id);
let pending = is_pending(facet_id);
let hovered = is_hovered(facet_id);
let selected_facet = is_selected_facet(facet_id);
let multi_selected = is_multi_selected(facet_id);
let highlighted = selected || pending || hovered || selected_facet;
let (draw_this_pass, color, width) = match pass {
EdgePass::Ordinary => (!highlighted && !multi_selected, style.edge_color, 1),
EdgePass::Hovered => {
(hovered && !pending && !selected_facet, style.hover_color, 2)
}
EdgePass::MultiSelected => (
multi_selected && !selected && !pending && !selected_facet,
style.multi_selected_color,
2,
),
EdgePass::Selected => (
selected && !pending && !selected_facet,
style.selected_color,
2,
),
EdgePass::SelectedFacet => {
(selected_facet && !pending, style.selected_facet_color, 3)
}
EdgePass::Pending => (pending, style.pending_color, 2),
};
if !draw_this_pass {
continue;
}
let pts = &edge_points[start..start + count];
for (i, &a) in pts.iter().enumerate() {
let b = pts[(i + 1) % count];
self.draw_edge(a, b, color, width);
}
}
}
}
pub(super) fn draw_facet_labels(
&mut self,
label_spots: &[(usize, f32, f32, f32, f32)],
style: &SolidStyle,
) {
for &(facet_id, cx, cy, w, h) in label_spots {
if w < MIN_LABEL_SPAN || h < MIN_LABEL_SPAN {
continue;
}
let Some(label) = style.facet_labels.get(facet_id) else {
continue;
};
if label.is_empty() {
continue;
}
let (px, py) = (cx.round() as i32, cy.round() as i32);
if px < 0 || py < 0 || px as u32 >= self.width || py as u32 >= self.height {
continue;
}
let idx = (py as u32 * self.width + px as u32) as usize;
if self.pick[idx] != facet_id as u32 + 1 {
continue; }
let (label_w, label_h) = diagram2d::text_size(label, 1);
let (width, height) = (self.width, self.height);
diagram2d::draw_text_into_buffer(
diagram2d::TextCanvas {
color_buf: &mut self.color,
width,
height,
},
cx - label_w as f32 / 2.0,
cy - label_h as f32 / 2.0,
label,
1,
style.edge_color,
None,
);
}
}
pub(super) fn draw_orientation_marker(&mut self, mesh: &SolidMesh, camera: &Camera) {
if self.width == 0 || self.height == 0 {
return;
}
let (w, h) = (self.width as f32, self.height as f32);
let radius = mesh
.positions
.iter()
.fold(1e-3_f64, |acc, p| acc.max(p.x.hypot(p.z)));
let marker_color = [240u8, 240, 245];
let origin = DVec3::new(0.0, 0.0, 0.0);
let tip = DVec3::new(radius * 1.25, 0.0, 0.0);
let (width, height) = (self.width, self.height);
if let (Some(from), Some(to)) = (project(camera, origin, w, h), project(camera, tip, w, h))
{
self.draw_edge(from, to, marker_color, 2);
let (label_w, _) = diagram2d::text_size("0", 1);
diagram2d::draw_text_into_buffer(
diagram2d::TextCanvas {
color_buf: &mut self.color,
width,
height,
},
to.0 - label_w as f32 / 2.0,
to.1 - 10.0,
"0",
1,
marker_color,
None,
);
}
let side_label = if camera.origin.y >= 0.0 {
"CROWN"
} else {
"PAVILION"
};
diagram2d::draw_text_into_buffer(
diagram2d::TextCanvas {
color_buf: &mut self.color,
width,
height,
},
8.0,
8.0,
side_label,
1,
marker_color,
None,
);
}
}