mod precision {
pub type Vec2 = glam::DVec2;
pub type Vec3 = glam::DVec3;
pub type Vec4 = glam::DVec4;
pub type Real = f64;
pub const K_PRECISION: f64 = 1e-12;
}
pub type Vec2u = glam::USizeVec2;
pub type Vec3u = glam::USizeVec3;
pub use precision::{Real, Vec2, Vec3, Vec4, K_PRECISION};
pub const K_BEST: Real = Real::MIN;
#[derive(PartialEq)]
pub enum OpType {
Add,
Subtract,
Intersect,
}
#[derive(Clone, Debug)]
pub struct Half {
pub tail: usize,
pub head: usize,
pub pair: usize,
}
impl Default for Half {
fn default() -> Self {
Self {
tail: usize::MAX,
head: usize::MAX,
pair: usize::MAX,
}
}
}
impl Half {
pub fn new(tail: usize, head: usize, pair: usize) -> Self {
Self { tail, head, pair }
}
pub fn new_without_pair(tail: usize, head: usize) -> Self {
Self {
tail,
head,
pair: usize::MAX,
}
}
pub fn is_forward(&self) -> bool {
self.tail < self.head
}
pub fn tail(&self) -> Option<usize> {
if self.tail == usize::MAX {
None
} else {
Some(self.tail)
}
}
pub fn head(&self) -> Option<usize> {
if self.head == usize::MAX {
None
} else {
Some(self.head)
}
}
pub fn pair(&self) -> Option<usize> {
if self.pair == usize::MAX {
None
} else {
Some(self.pair)
}
}
}
pub fn face_of(hid: usize) -> usize {
hid / 3
}
pub fn next_of(hid: usize) -> usize {
let mut i = hid + 1;
if i.is_multiple_of(3) {
i -= 3;
}
i
}
#[derive(Clone, Debug, Copy)]
pub struct Tref {
pub mid: usize, pub fid: usize, pub pid: i32, }
impl Default for Tref {
fn default() -> Self {
Self {
mid: usize::MAX,
fid: usize::MAX,
pid: -1,
}
}
}
pub fn det2x2(a: &Vec2, b: &Vec2) -> Real {
a.x * b.y - a.y * b.x
}
pub fn get_aa_proj_matrix(n: &Vec3) -> (Vec3, Vec3) {
let a = n.abs();
let m: Real;
let r1: Vec3;
let r2: Vec3;
if a.z > a.x && a.z > a.y {
r1 = Vec3::new(1., 0., 0.);
r2 = Vec3::new(0., 1., 0.);
m = n.z;
}
else if a.y > a.x {
r1 = Vec3::new(0., 0., 1.);
r2 = Vec3::new(1., 0., 0.);
m = n.y;
}
else {
r1 = Vec3::new(0., 1., 0.);
r2 = Vec3::new(0., 0., 1.);
m = n.x;
}
if m < 0. {
(-r1, r2)
} else {
(r1, r2)
}
}
pub fn compute_aa_proj(p: &(Vec3, Vec3), v: &Vec3) -> Vec2 {
Vec2::new(p.0.dot(*v), p.1.dot(*v))
}
pub fn is_ccw_2d(p0: &Vec2, p1: &Vec2, p2: &Vec2, t: Real) -> i32 {
let v1 = p1 - p0;
let v2 = p2 - p0;
let area = v1.x * v2.y - v1.y * v2.x;
let base = v1.length_squared().max(v2.length_squared());
if area.powi(2) * 4. <= base * t.powi(2) {
return 0;
}
if area > 0. {
1
} else {
-1
}
}
pub fn is_ccw_3d(p0: &Vec3, p1: &Vec3, p2: &Vec3, n: &Vec3, t: Real) -> i32 {
let p = get_aa_proj_matrix(n);
is_ccw_2d(
&compute_aa_proj(&p, p0),
&compute_aa_proj(&p, p1),
&compute_aa_proj(&p, p2),
t,
)
}
pub fn safe_normalize(v: Vec2) -> Vec2 {
let n = v.normalize();
if n.x.is_finite() && !n.x.is_nan() && n.y.is_finite() && !n.y.is_nan() {
n
} else {
Vec2::new(0., 0.)
}
}