axiolid-mesh-boolean-boolmesh 0.3.3

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.
#![allow(clippy::needless_range_loop)]

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

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

impl<'a> Kernel11<'a> {
    pub fn op(&self, p1: usize, q1: usize) -> Option<(i32, Vec4)> {
        let mut k = 0;
        let mut p_rl = [Vec3::ZERO; 2];
        let mut q_rl = [Vec3::ZERO; 2];
        let mut shadow_ = false;
        let mut s11 = 0;

        let p0 = [self.hs_p[p1].tail, self.hs_p[p1].head];
        let q0 = [self.hs_q[q1].tail, self.hs_q[q1].head];

        for i in 0..2 {
            // P casts onto Q.
            let ops = ShadowOperands {
                ps_p: self.ps_p,
                ps_q: self.ps_q,
                hs_q: self.hs_q,
                ns: self.ns,
            };
            if let Some((s, yz)) = shadows01(p0[i], q1, &ops, self.expand, false) {
                s11 += s * if i == 0 { -1 } else { 1 };
                if k < 2 && (k == 0 || (s != 0) != shadow_) {
                    shadow_ = s != 0;
                    p_rl[k] = self.ps_p[p0[i]];
                    q_rl[k] = Vec3::new(p_rl[k].x, yz.x, yz.y);
                    k += 1;
                }
            }
        }

        for i in 0..2 {
            // ...and Q casts onto P: the operands swap roles.
            let ops = ShadowOperands {
                ps_p: self.ps_q,
                ps_q: self.ps_p,
                hs_q: self.hs_p,
                ns: self.ns,
            };
            if let Some((s, yz)) = shadows01(q0[i], p1, &ops, self.expand, true) {
                s11 += s * if i == 0 { -1 } else { 1 };
                if k < 2 && (k == 0 || (s != 0) != shadow_) {
                    shadow_ = s != 0;
                    q_rl[k] = self.ps_q[q0[i]];
                    p_rl[k] = Vec3::new(q_rl[k].x, yz.x, yz.y);
                    k += 1;
                }
            }
        }

        if s11 == 0 {
            return None;
        }

        assert_eq!(k, 2, "Boolean manifold error: s11");
        let xyzz11 = intersect(p_rl[0], p_rl[1], q_rl[0], q_rl[1]);
        let p1s = self.hs_p[p1].tail;
        let p1e = self.hs_p[p1].head;
        let d1 = self.ps_p[p1s] - Vec3::new(xyzz11.x, xyzz11.y, xyzz11.z);
        let d2 = self.ps_p[p1e] - Vec3::new(xyzz11.x, xyzz11.y, xyzz11.z);
        let b2 = d1.length_squared();
        let e2 = d2.length_squared();
        let dir = if b2 < e2 {
            self.ns[p1s].z
        } else {
            self.ns[p1e].z
        };

        if !shadows(xyzz11.z, xyzz11.w, self.expand * dir) {
            s11 = 0;
        }
        Some((s11, xyzz11))
    }
}