use super::PlanBucket;
use crate::csg::consolidate::{emit_triangle, tri_is_needle};
use crate::mesh::Mesh;
use nalgebra::{Point3, Vector3};
pub(in crate::csg::consolidate) fn emit_plans(
plans: &mut [PlanBucket],
conformed: bool,
) -> (Mesh, bool) {
let mut complete = true;
use crate::triangulation::triangulate_polygon_with_holes_refined;
let mut output = Mesh::new();
for plan in plans.iter_mut() {
for t in &plan.raw {
emit_triangle(&mut output, t, &plan.normal);
}
let basis = (plan.origin, plan.u_axis, plan.v_axis, plan.normal);
for region in plan.regions.iter_mut() {
let (outer, holes) = if conformed {
(®ion.outer_conformed, ®ion.holes_conformed)
} else {
(®ion.outer, ®ion.holes)
};
if conformed && !region.changed {
match ®ion.cached {
Some((pts, idx)) => {
emit_region(&mut output, basis, pts, idx);
continue;
}
None => {
complete = false;
continue;
}
}
}
let (all_2d, indices) = match triangulate_polygon_with_holes_refined(outer, holes) {
Ok((pts, idx)) => (pts, idx),
Err(_) => {
complete = false;
continue;
}
};
if !conformed {
region.cached = Some((all_2d, indices));
let (pts, idx) = region.cached.as_ref().expect("just stored");
emit_region(&mut output, basis, pts, idx);
continue;
}
emit_region(&mut output, basis, &all_2d, &indices);
}
}
(output, complete)
}
fn emit_region(
output: &mut Mesh,
basis: (Point3<f64>, Vector3<f64>, Vector3<f64>, Vector3<f64>),
all_2d: &[nalgebra::Point2<f64>],
indices: &[usize],
) {
let (origin, u_axis, v_axis, normal) = basis;
let verts_3d: Vec<Point3<f64>> = all_2d
.iter()
.map(|p| origin + u_axis * p.x + v_axis * p.y)
.collect();
let base = output.vertex_count() as u32;
for vp in &verts_3d {
output.add_vertex(*vp, normal);
}
for tri in indices.chunks_exact(3) {
let v = [verts_3d[tri[0]], verts_3d[tri[1]], verts_3d[tri[2]]];
if tri_is_needle(&v) {
continue;
}
output.add_triangle(
base + tri[0] as u32,
base + tri[1] as u32,
base + tri[2] as u32,
);
}
}