Skip to content

Commit

Permalink
Try to fix extrude_xy
Browse files Browse the repository at this point in the history
  • Loading branch information
lbirkert committed Aug 12, 2023
1 parent 8c41e6e commit e484764
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 79 deletions.
11 changes: 6 additions & 5 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ impl eframe::App for KeloApp {
// Don't center on z axis
let transform = -inf - Vector3::new(size.x, size.y, 0.0).scale(0.5);
mesh.translate(&transform);
self.editor.state.push(
self.editor
.state
.insert_object(Object::new(mesh, handle.file_name())),
);
let mut message = self
.editor
.state
.insert_object(Object::new(mesh, handle.file_name()));
self.editor.state.apply(&mut message);
self.editor.log.push(message);
}
}
.block_on();
Expand Down
278 changes: 256 additions & 22 deletions src/core/mesh.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{collections::HashSet, io::Cursor};
use std::{
collections::{HashMap, HashSet},
io::Cursor,
};

use nalgebra::{Matrix4, UnitVector3, Vector3};

Expand Down Expand Up @@ -53,7 +56,9 @@ impl Mesh {

/// Slice a model using a plane. This returns the outline of the cross section.
pub fn slice_raw(triangles: &[Triangle], plane: Plane) -> Vec<Path3> {
// Used for connecting the polygons properly
const EPSILON: f32 = 1e-9;

// Used for connecting the polygons properly. TODO: Look into hashing
let mut points: Vec<Vector3<f32>> = Vec::new();
let mut indicies: Vec<Vec<usize>> = Vec::new();

Expand All @@ -75,8 +80,6 @@ impl Mesh {
_ => continue,
};

const EPSILON: f32 = 1e-9;

// Skip 'zero' length segments
if (seg.0 - seg.1).magnitude_squared() < EPSILON {
continue;
Expand All @@ -89,33 +92,27 @@ impl Mesh {
(seg.1, seg.0)
};

let mut ai = None;
for (i, point) in points.iter().enumerate() {
if (a - point).magnitude_squared() < EPSILON {
ai = Some(i);
break;
let ai = 'ai: {
for (i, point) in points.iter().enumerate() {
if (a - point).magnitude_squared() < EPSILON {
break 'ai i;
}
}
}

let ai = ai.unwrap_or_else(|| {
points.push(a);
indicies.push(Vec::new());
points.len() - 1
});
};

let mut bi = None;
for (i, point) in points.iter().enumerate() {
if (b - point).magnitude_squared() < EPSILON {
bi = Some(i);
break;
let bi = 'bi: {
for (i, point) in points.iter().enumerate() {
if (b - point).magnitude_squared() < EPSILON {
break 'bi i;
}
}
}

let bi = bi.unwrap_or_else(|| {
points.push(b);
indicies.push(Vec::new());
points.len() - 1
});
};

if segments.insert((ai.min(bi), ai.max(bi))) {
indicies[ai].push(bi);
Expand Down Expand Up @@ -219,4 +216,241 @@ impl Mesh {

(inf, sup)
}

/// Extrude this mesh outwards by factor. This is used for cutter compensation.
pub fn extrude_xy(&self, factor: f32) -> Mesh {
let mut triangles: Vec<Triangle> = Vec::new();

const EPSILON: f32 = 1e-9;

let mut points: Vec<Vector3<f32>> = Vec::new();
let mut edges: HashMap<(usize, usize), Vec<(usize, Edge)>> = HashMap::new();
let mut corners: Vec<Vec<(usize, Vertex)>> = Vec::new();

// Construct edges
for (i, triangle) in self.triangles.iter().enumerate() {
let ai = 'ai: {
for (i, point) in points.iter().enumerate() {
if (triangle.a - point).magnitude_squared() < EPSILON {
break 'ai i;
}
}
points.push(triangle.a);
corners.push(Vec::new());
points.len() - 1
};
let bi = 'bi: {
for (i, point) in points.iter().enumerate() {
if (triangle.b - point).magnitude_squared() < EPSILON {
break 'bi i;
}
}
points.push(triangle.b);
corners.push(Vec::new());
points.len() - 1
};
let ci = 'ci: {
for (i, point) in points.iter().enumerate() {
if (triangle.c - point).magnitude_squared() < EPSILON {
break 'ci i;
}
}
points.push(triangle.c);
corners.push(Vec::new());
points.len() - 1
};

corners[ai].push((i, Vertex::A));
corners[bi].push((i, Vertex::B));
corners[ci].push((i, Vertex::C));

let e1 = (ai.min(bi), ai.max(bi));
let e2 = (bi.min(ci), bi.max(ci));
let e3 = (ci.min(ai), ci.max(ai));

if let Some(ref mut edge) = edges.get_mut(&e1) {
edge.push((i, Edge::A));
} else {
edges.insert(e1, vec![(i, Edge::A)]);
}

if let Some(ref mut edge) = edges.get_mut(&e2) {
edge.push((i, Edge::B));
} else {
edges.insert(e2, vec![(i, Edge::B)]);
}

if let Some(ref mut edge) = edges.get_mut(&e3) {
edge.push((i, Edge::C));
} else {
edges.insert(e3, vec![(i, Edge::C)]);
}
}

for triangle in self.triangles.iter() {
let mut triangle = triangle.clone();

let mut e = Vector3::new(triangle.normal.x, triangle.normal.y, 0.0);
//let mut e = triangle.normal.into_inner();
if e.magnitude_squared() > 0.0 {
e.normalize_mut();
e.scale_mut(factor);
}
triangle.a += e;
triangle.b += e;
triangle.c += e;
triangles.push(triangle);
}

for (_, edge) in edges.iter_mut() {
let (ta, tb) = match (edge.pop(), edge.pop()) {
(Some(ta), Some(tb)) => (ta, tb),
_ => continue,
};

let na = triangles[ta.0].normal;
let nb = triangles[tb.0].normal;

//let (&a0, &a1) = ta.1.get(&triangles[ta.0]);
//let (&b0, &b1) = ta.1.get(&triangles[ta.0]);

//// No transformation
//if (c0 - a0).magnitude_squared() < EPSILON || (c0 - b0).magnitude_squared() < EPSILON {
// let normal = UnitVector3::new_normalize(na.into_inner() + nb.into_inner());
// triangles.push(Triangle::new(a1, b1, a0, normal));
// triangles.push(Triangle::new(a1, b0, b1, normal));
// continue;
//}

// Center for radial extrusion
let tra = &self.triangles[ta.0];
let (c0, c1) = ta.1.get(tra);

{
let center = (tra.a + tra.b + tra.c).scale(1.0 / 3.0);
if nb.dot(&(center - c0)) * factor.signum() > 0.0 {
continue;
}
}

let mut nna = Vector3::new(na.x, na.y, 0.0);
let mut nnb = Vector3::new(nb.x, nb.y, 0.0);
nna.normalize_mut();
nnb.normalize_mut();
let mut delta = nna.dot(&nnb).acos();
if delta > 0.0 && delta < std::f32::consts::PI {
let yfac = nna;
let mut xfac = nnb.cross(&nna).cross(&nna);
xfac.normalize_mut();

let res: i32 = ((delta / std::f32::consts::PI) * 10.0 * factor).ceil() as i32;

delta *= xfac.dot(&nb).signum();

let mut b = yfac.scale(factor);
for i in 1..=res {
let normal =
UnitVector3::new_normalize(na.lerp(&nb, i as f32 / (res + 1) as f32));
let angle = delta * (i as f32 / res as f32);
let (mut sin, mut cos) = angle.sin_cos();
sin *= factor;
cos *= factor;

let a = xfac.scale(sin) + yfac.scale(cos);
let a0 = c0 + a;
let a1 = c1 + a;
let b0 = c0 + b;
let b1 = c1 + b;

triangles.push(Triangle::new(a1, b0, a0, normal));
triangles.push(Triangle::new(a1, b1, b0, normal));

b = a;
}
} else {
let (&a0, &a1) = ta.1.get(&triangles[ta.0]);
let (&b0, &b1) = tb.1.get(&triangles[tb.0]);
let mut normal = Vector3::z_axis();
if (na.into_inner() + nb.into_inner()).dot(&normal) < 0.0 {
normal = -normal;
}

//let normal = UnitVector3::new_normalize(na.into_inner() + nb.into_inner());
triangles.push(Triangle::new(a1, b1, a0, normal));
triangles.push(Triangle::new(a1, b0, b1, normal));
}
}

/*
for corner in corners.iter() {
// point + normal
let mut points: Vec<(Vector3<f32>, Vector3<f32>)> = Vec::new();
for point in corner.iter() {
let triangle = &triangles[point.0];
let &point = point.1.get(triangle);
let different = !points
.iter()
.any(|other| (point - other.0).magnitude_squared() < EPSILON);
if different {
points.push((point, triangle.normal.into_inner()));
}
}
loop {
let (a, b, c) = match (points.pop(), points.pop(), points.pop()) {
(Some(a), Some(b), Some(c)) => (a, b, c),
_ => break,
};
triangles.push(Triangle::new(
a.0,
b.0,
c.0,
UnitVector3::new_normalize(a.1 + b.1 + c.1),
));
}
}
*/

Mesh::new(triangles)
}
}

// TODO: move to triangle.rs
#[derive(Debug)]
pub enum Vertex {
A,
B,
C,
}

impl Vertex {
#[inline]
pub fn get<'a>(&self, triangle: &'a Triangle) -> &'a Vector3<f32> {
match self {
Self::A => &triangle.a,
Self::B => &triangle.b,
Self::C => &triangle.c,
}
}
}

#[derive(Debug)]
pub enum Edge {
A,
B,
C,
}

impl Edge {
#[inline]
pub fn get<'a>(&self, triangle: &'a Triangle) -> (&'a Vector3<f32>, &'a Vector3<f32>) {
match self {
Self::A => (&triangle.a, &triangle.b),
Self::B => (&triangle.b, &triangle.c),
Self::C => (&triangle.c, &triangle.a),
}
}
}
4 changes: 2 additions & 2 deletions src/editor/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ pub struct Camera {
pub pitch: f32,
pub zoom: f32,

width: f32,
height: f32,
pub width: f32,
pub height: f32,

pub projection: Projection,
}
Expand Down
Loading

0 comments on commit e484764

Please sign in to comment.