axiolid-mesh-boolean-boolmesh 0.3.2

boolmesh-backed MeshBoolean provider
Documentation
//--- Copyright (C) 2025 Saki Komikado <komietty@gmail.com>,
//--- This Source Code Form is subject to the terms of the Mozilla Public License v.2.0.

use super::kernel01::{interpolate, shadows, shadows01, ShadowOperands};
use crate::csg::{Half, Real, Vec3};

pub struct Kernel02<'a> {
    pub ps_p: &'a [Vec3],
    pub ps_q: &'a [Vec3],
    pub hs_q: &'a [Half],
    pub ns: &'a [Vec3],
    pub expand: Real,
    pub fwd: bool,
}

impl<'a> Kernel02<'a> {
    pub fn op(&self, p0: usize, q2: usize) -> Option<(i32, Real)> {
        let mut s02 = 0;
        let exp = self.expand;
        let fwd = self.fwd;

        // For yzzLR[k], k==0 is the left and k==1 is the right.
        let mut k = 0;
        let mut yzz_rl = [Vec3::ZERO; 2];
        // Either the left or right must shadow, but not both. This ensures the
        // intersection is between the left and right.
        let mut shadows_ = false;
        let mut closest_vid = usize::MAX;
        let mut min_metric = Real::MAX;

        let pos_p = self.ps_p[p0];

        for i in 0..3 {
            let q1 = 3 * q2 + i;
            let half = self.hs_q[q1].clone();
            let q1_f = if half.is_forward() { q1 } else { half.pair };

            if !fwd {
                let q_vert = self.hs_q[q1_f].tail;
                let diff = pos_p - self.ps_q[q_vert];
                let metric = diff.length_squared();
                if metric < min_metric {
                    min_metric = metric;
                    closest_vid = q_vert;
                }
            }

            // If the value is None, then these do not overlap
            let ops = ShadowOperands {
                ps_p: self.ps_p,
                ps_q: self.ps_q,
                hs_q: self.hs_q,
                ns: self.ns,
            };
            if let Some((s01, yz01)) = shadows01(p0, q1_f, &ops, exp, !fwd) {
                s02 += s01 * if fwd == half.is_forward() { -1 } else { 1 };
                if k < 2 && (k == 0 || (s01 != 0) != shadows_) {
                    shadows_ = s01 != 0;
                    yzz_rl[k] = Vec3::new(yz01.x, yz01.y, yz01.y);
                    k += 1;
                }
            }
        }

        if s02 == 0 {
            return None;
        }

        assert_eq!(k, 2, "Boolean manifold error: s02");
        let p = self.ps_p[p0];
        let z02 = interpolate(yzz_rl[0], yzz_rl[1], p.y)[1];
        // Same test either way; `fwd` only decides which operand is the
        // shadow caster and whose normal supplies the expansion.
        let lit = if fwd {
            shadows(p.z, z02, exp * self.ns[p0].z)
        } else {
            shadows(z02, p.z, exp * self.ns[closest_vid].z)
        };
        if !lit {
            s02 = 0;
        }
        Some((s02, z02))
    }
}