mirror of
https://github.com/Theaninova/Bampy.git
synced 2025-12-11 03:56:17 +00:00
stuff
This commit is contained in:
@@ -23,6 +23,8 @@ bvh = "0.8.0"
|
||||
nalgebra = "0.32.4"
|
||||
num = "0.4.1"
|
||||
approx = "0.5.1"
|
||||
serde = "1.0.197"
|
||||
tsify = { version = "0.4.5", features = ["js"] }
|
||||
|
||||
[dependencies.getrandom]
|
||||
features = ["js"]
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use nalgebra::{vector, Vector3};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
use crate::slicer::{
|
||||
base_slices::create_base_slices, mesh::Mesh, split_surface::split_surface, triangle::Triangle,
|
||||
base_slices::create_slices, mesh::Mesh, split_surface::split_surface, triangle::Triangle,
|
||||
SlicerOptions,
|
||||
};
|
||||
|
||||
@@ -11,8 +13,32 @@ mod util;
|
||||
|
||||
const BED_NORMAL: Vector3<f32> = vector![0f32, 0f32, 1f32];
|
||||
|
||||
#[derive(Tsify, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[tsify(from_wasm_abi)]
|
||||
pub struct SliceOptions {
|
||||
#[tsify(type = "Float32Array")]
|
||||
positions: Vec<f32>,
|
||||
layer_height: f32,
|
||||
max_angle: f32,
|
||||
}
|
||||
|
||||
#[derive(Tsify, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[tsify(into_wasm_abi)]
|
||||
pub struct SliceResult {
|
||||
#[tsify(type = "Array<Float32Array>")]
|
||||
rings: Vec<Vec<f32>>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn slice(positions: &[f32], layer_height: f32, max_angle: f32) {
|
||||
pub fn slice(
|
||||
SliceOptions {
|
||||
positions,
|
||||
layer_height,
|
||||
max_angle,
|
||||
}: SliceOptions,
|
||||
) -> SliceResult {
|
||||
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
assert_eq!(positions.len() % 9, 0);
|
||||
@@ -29,21 +55,34 @@ pub fn slice(positions: &[f32], layer_height: f32, max_angle: f32) {
|
||||
if triangle.normal.angle(&BED_NORMAL) > max_angle {
|
||||
slicable_triangles.push(triangle);
|
||||
} else {
|
||||
slicable_triangles.push(triangle);
|
||||
surface_triangles.push(triangle);
|
||||
}
|
||||
}
|
||||
slicable_triangles.shrink_to_fit();
|
||||
surface_triangles.shrink_to_fit();
|
||||
|
||||
console_log!("Computing BVH");
|
||||
|
||||
let slicer_options = SlicerOptions { layer_height };
|
||||
|
||||
console_log!("Creating Surfaces");
|
||||
let surfaces = split_surface(surface_triangles);
|
||||
|
||||
console_log!("Creating Slices");
|
||||
console_log!("Computing BVH");
|
||||
let slicable = Mesh::from(slicable_triangles);
|
||||
let base_slices = create_base_slices(&slicer_options, &slicable);
|
||||
console_log!("Creating Slices");
|
||||
let slices = create_slices(&slicer_options, &slicable);
|
||||
console_log!("Done");
|
||||
|
||||
SliceResult {
|
||||
rings: slices
|
||||
.into_iter()
|
||||
.map(|slice| {
|
||||
slice
|
||||
.points
|
||||
.into_iter()
|
||||
.flat_map(|point| [point.x, point.y, point.z])
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
use bvh::bvh::BvhNode;
|
||||
|
||||
use super::{line::Line3, mesh::Mesh, SlicerOptions};
|
||||
use crate::console_log;
|
||||
|
||||
use super::{
|
||||
line::Line3,
|
||||
mesh::Mesh,
|
||||
slice_rings::{find_slice_rings, SliceRing},
|
||||
SlicerOptions,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BaseSlice {
|
||||
@@ -10,11 +17,12 @@ pub struct BaseSlice {
|
||||
|
||||
/// Creates base slices from the geometry, excluding surfaces.
|
||||
/// The slicse are not sorted or separated into rings.
|
||||
pub fn create_base_slices(options: &SlicerOptions, slicable: &Mesh<f32>) -> Vec<BaseSlice> {
|
||||
pub fn create_slices(options: &SlicerOptions, slicable: &Mesh<f32>) -> Vec<SliceRing> {
|
||||
let layer_count = f32::floor(slicable.aabb.max.z / options.layer_height) as usize;
|
||||
let mut base_slices = Vec::<BaseSlice>::with_capacity(layer_count);
|
||||
let mut rings = vec![];
|
||||
|
||||
for i in 0..layer_count {
|
||||
console_log!("Layer {}", i);
|
||||
let layer = i as f32 * options.layer_height;
|
||||
let mut base_slice = BaseSlice {
|
||||
z: layer,
|
||||
@@ -33,10 +41,10 @@ pub fn create_base_slices(options: &SlicerOptions, slicable: &Mesh<f32>) -> Vec<
|
||||
child_r_aabb,
|
||||
} => {
|
||||
if layer >= child_l_aabb.min.z && layer <= child_l_aabb.max.z {
|
||||
stack.push(child_r_index);
|
||||
stack.push(child_l_index);
|
||||
}
|
||||
if layer >= child_r_aabb.min.z && layer <= child_r_aabb.max.z {
|
||||
stack.push(child_l_index);
|
||||
stack.push(child_r_index);
|
||||
}
|
||||
}
|
||||
BvhNode::Leaf {
|
||||
@@ -52,8 +60,8 @@ pub fn create_base_slices(options: &SlicerOptions, slicable: &Mesh<f32>) -> Vec<
|
||||
}
|
||||
}
|
||||
|
||||
base_slices.push(base_slice);
|
||||
rings.append(&mut find_slice_rings(base_slice));
|
||||
}
|
||||
|
||||
base_slices
|
||||
rings
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::fmt::Debug;
|
||||
pub mod base_slices;
|
||||
pub mod line;
|
||||
pub mod mesh;
|
||||
pub mod slice_rings;
|
||||
pub mod split_surface;
|
||||
pub mod triangle;
|
||||
|
||||
|
||||
54
bampy/src/slicer/slice_rings.rs
Normal file
54
bampy/src/slicer/slice_rings.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use approx::{relative_eq, relative_ne};
|
||||
use nalgebra::Vector3;
|
||||
|
||||
use crate::console_log;
|
||||
|
||||
use super::base_slices::BaseSlice;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SliceRing {
|
||||
pub z: f32,
|
||||
pub points: Vec<Vector3<f32>>,
|
||||
}
|
||||
|
||||
pub fn find_slice_rings(mut slice: BaseSlice) -> Vec<SliceRing> {
|
||||
let mut rings = vec![];
|
||||
while let Some(line) = slice.lines.pop() {
|
||||
let mut ring = SliceRing {
|
||||
z: slice.z,
|
||||
points: vec![line.start, line.end],
|
||||
};
|
||||
let mut right = ring.points[1];
|
||||
|
||||
let mut previous_len = usize::MAX;
|
||||
while relative_ne!(ring.points[0], right) {
|
||||
if previous_len == ring.points.len() {
|
||||
console_log!(
|
||||
"Error: Could not find a ring for slice at z = {}, {} items left.",
|
||||
slice.z,
|
||||
ring.points.len()
|
||||
);
|
||||
break;
|
||||
}
|
||||
previous_len = ring.points.len();
|
||||
|
||||
slice.lines.retain_mut(|line| {
|
||||
if relative_eq!(line.start, right, epsilon = 0.001) {
|
||||
ring.points.push(line.end);
|
||||
right = line.end;
|
||||
false
|
||||
} else if relative_eq!(line.end, right, epsilon = 0.001) {
|
||||
ring.points.push(line.start);
|
||||
right = line.start;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
rings.push(ring)
|
||||
}
|
||||
|
||||
rings
|
||||
}
|
||||
@@ -23,16 +23,24 @@ fn vec_inside_aabb<T: SimdPartialOrd + Scalar + Copy + Float>(
|
||||
aabb: &Aabb<T, 3>,
|
||||
) -> bool {
|
||||
vec.x >= aabb.min.x
|
||||
&& vec.x <= aabb.max.x
|
||||
&& vec.y >= aabb.min.y
|
||||
&& vec.y <= aabb.max.y
|
||||
&& vec.z >= aabb.min.z
|
||||
&& vec.x <= aabb.max.x
|
||||
&& vec.y <= aabb.max.y
|
||||
&& vec.z <= aabb.max.z
|
||||
}
|
||||
|
||||
impl<T> Triangle<T>
|
||||
where
|
||||
T: SimdPartialOrd + Scalar + Copy + ClosedMul + ClosedAdd + ClosedSub + Float + FromPrimitive,
|
||||
T: SimdPartialOrd
|
||||
+ RelativeEq
|
||||
+ Scalar
|
||||
+ Copy
|
||||
+ ClosedMul
|
||||
+ ClosedAdd
|
||||
+ ClosedSub
|
||||
+ Float
|
||||
+ FromPrimitive,
|
||||
{
|
||||
pub fn new(a: Vector3<T>, b: Vector3<T>, c: Vector3<T>) -> Self {
|
||||
let normal = (b - a).cross(&(c - a));
|
||||
@@ -70,15 +78,11 @@ where
|
||||
self.has_vec(other.a) || self.has_vec(other.b) || self.has_vec(other.c)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Vector3<T>> {
|
||||
vec![&self.a, &self.b, &self.c].into_iter()
|
||||
}
|
||||
|
||||
pub fn intersect_z(&self, z: T) -> Option<Line3<T>> {
|
||||
let mut intersection = Vec::with_capacity(3);
|
||||
let mut last = self.c;
|
||||
for point in self.iter() {
|
||||
if point.z == z {
|
||||
for point in [self.a, self.b, self.c].iter() {
|
||||
if relative_eq!(point.z, z) {
|
||||
intersection.push(*point);
|
||||
} else if last.z < z && point.z > z || last.z > z && point.z < z {
|
||||
intersection.push(last.lerp(&point, (z - last.z) / (point.z - last.z)));
|
||||
|
||||
Reference in New Issue
Block a user