mirror of
https://github.com/Theaninova/Bampy.git
synced 2025-12-11 03:56:17 +00:00
feat: rust stuff
This commit is contained in:
6
bampy/.gitignore
vendored
Normal file
6
bampy/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
bin/
|
||||
pkg/
|
||||
wasm-pack.log
|
||||
33
bampy/Cargo.toml
Normal file
33
bampy/Cargo.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "bampy"
|
||||
version = "0.1.0"
|
||||
authors = ["Thea Schöbl <dev@theaninova.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.84"
|
||||
|
||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||
# logging them with `console.error`. This is great for development, but requires
|
||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||
# code size when deploying.
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
bvh = "0.8.0"
|
||||
nalgebra = "0.32.4"
|
||||
num = "0.4.1"
|
||||
|
||||
[dependencies.getrandom]
|
||||
features = ["js"]
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
46
bampy/src/lib.rs
Normal file
46
bampy/src/lib.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use bvh::{aabb::Bounded, bvh::Bvh};
|
||||
use nalgebra::Point;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
use crate::slicer::{base_slices, SlicerOptions, Triangle};
|
||||
|
||||
mod slicer;
|
||||
mod util;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn slice(positions: &[f32], face_normals: &[f32], layer_height: f32) {
|
||||
debug_assert_eq!(positions.len() % 9, 0);
|
||||
debug_assert_eq!(face_normals.len() % 3, 0);
|
||||
debug_assert_eq!(positions.len() / 9, face_normals.len() / 3);
|
||||
|
||||
let mut triangles = Vec::with_capacity(positions.len() / 9);
|
||||
for i in (0..positions.len()).step_by(9) {
|
||||
let triangle = Triangle {
|
||||
a: Point::<f32, 3>::new(positions[i], positions[i + 1], positions[i + 2]),
|
||||
b: Point::<f32, 3>::new(positions[i + 3], positions[i + 4], positions[i + 5]),
|
||||
c: Point::<f32, 3>::new(positions[i + 6], positions[i + 7], positions[i + 8]),
|
||||
normal: Point::<f32, 3>::new(
|
||||
face_normals[i / 9],
|
||||
face_normals[i / 9 + 1],
|
||||
face_normals[i / 9 + 2],
|
||||
),
|
||||
node_index: 0,
|
||||
};
|
||||
triangles.push(triangle);
|
||||
}
|
||||
|
||||
let mut aabb = triangles[0].aabb();
|
||||
for triangle in &triangles {
|
||||
aabb.grow_mut(&triangle.a);
|
||||
aabb.grow_mut(&triangle.b);
|
||||
aabb.grow_mut(&triangle.c);
|
||||
}
|
||||
|
||||
let slicer_options = SlicerOptions {
|
||||
aabb,
|
||||
bvh: Bvh::build(&mut triangles),
|
||||
triangles,
|
||||
layer_height,
|
||||
};
|
||||
let base_slices = base_slices::create_base_slices(&slicer_options, &vec![]);
|
||||
}
|
||||
60
bampy/src/slicer/base_slices.rs
Normal file
60
bampy/src/slicer/base_slices.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use bvh::bvh::BvhNode;
|
||||
use nalgebra::Point;
|
||||
|
||||
use super::{Line, SlicerOptions};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BaseSlice {
|
||||
z: f32,
|
||||
lines: Vec<Line<f32, 3>>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates base slices from the geometry, excluding surfaces.
|
||||
*
|
||||
* The slicse are not sorted or separated into rings.
|
||||
*/
|
||||
pub fn create_base_slices(options: &SlicerOptions, surface_triangles: &[bool]) -> Vec<BaseSlice> {
|
||||
let layer_count = f32::floor(options.aabb.max.z / options.layer_height) as usize;
|
||||
let mut base_slices = Vec::<BaseSlice>::with_capacity(layer_count);
|
||||
|
||||
for i in 0..layer_count {
|
||||
let layer = i as f32 * options.layer_height;
|
||||
let base_slice = BaseSlice {
|
||||
z: layer,
|
||||
lines: vec![],
|
||||
};
|
||||
|
||||
let mut stack = Vec::<usize>::with_capacity(options.bvh.nodes.len());
|
||||
stack.push(0);
|
||||
while let Some(i) = stack.pop() {
|
||||
match options.bvh.nodes[i] {
|
||||
BvhNode::Node {
|
||||
parent_index: _,
|
||||
child_l_index,
|
||||
child_l_aabb,
|
||||
child_r_index,
|
||||
child_r_aabb,
|
||||
} => {
|
||||
if layer >= child_l_aabb.min.z && layer <= child_l_aabb.max.z {
|
||||
stack.push(child_r_index);
|
||||
}
|
||||
if layer >= child_r_aabb.min.z && layer <= child_r_aabb.max.z {
|
||||
stack.push(child_l_index);
|
||||
}
|
||||
}
|
||||
BvhNode::Leaf {
|
||||
parent_index: _,
|
||||
shape_index,
|
||||
} => {
|
||||
let triangle = options.triangles[shape_index];
|
||||
let a = Point::<f32, 3>::new(triangle.a.x, triangle.a.y, layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base_slices.push(base_slice);
|
||||
}
|
||||
|
||||
base_slices
|
||||
}
|
||||
52
bampy/src/slicer/mod.rs
Normal file
52
bampy/src/slicer/mod.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use bvh::{
|
||||
aabb::{Aabb, Bounded},
|
||||
bounding_hierarchy::BHShape,
|
||||
bvh::Bvh,
|
||||
};
|
||||
use nalgebra::{Point, Scalar, SimdPartialOrd};
|
||||
|
||||
pub mod base_slices;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub struct Triangle<T: Scalar, const D: usize> {
|
||||
pub a: Point<T, D>,
|
||||
pub b: Point<T, D>,
|
||||
pub c: Point<T, D>,
|
||||
pub normal: Point<T, D>,
|
||||
pub node_index: usize,
|
||||
}
|
||||
|
||||
impl<T: SimdPartialOrd + Scalar + Copy, const D: usize> Bounded<T, D> for Triangle<T, D> {
|
||||
fn aabb(&self) -> Aabb<T, D> {
|
||||
let mut aabb = self.a.aabb();
|
||||
aabb.grow_mut(&self.b);
|
||||
aabb.grow_mut(&self.c);
|
||||
aabb
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimdPartialOrd + Scalar + Copy, const D: usize> BHShape<T, D> for Triangle<T, D> {
|
||||
fn set_bh_node_index(&mut self, node_index: usize) {
|
||||
self.node_index = node_index;
|
||||
}
|
||||
|
||||
fn bh_node_index(&self) -> usize {
|
||||
self.node_index
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub struct Line<T: Scalar, const D: usize> {
|
||||
pub start: Point<T, D>,
|
||||
pub end: Point<T, D>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SlicerOptions {
|
||||
pub aabb: bvh::aabb::Aabb<f32, 3>,
|
||||
pub bvh: Bvh<f32, 3>,
|
||||
pub triangles: Vec<Triangle<f32, 3>>,
|
||||
pub layer_height: f32,
|
||||
}
|
||||
18
bampy/src/util.rs
Normal file
18
bampy/src/util.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
pub fn log(s: &str);
|
||||
|
||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||||
pub fn log_u32(a: u32);
|
||||
|
||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
||||
pub fn log_many(a: &str, b: &str);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! console_log {
|
||||
($($t:tt)*) => (crate::util::log(&format_args!($($t)*).to_string()))
|
||||
}
|
||||
13
bampy/tests/web.rs
Normal file
13
bampy/tests/web.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
//! Test suite for the Web and headless browsers.
|
||||
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
extern crate wasm_bindgen_test;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn pass() {
|
||||
assert_eq!(1 + 1, 2);
|
||||
}
|
||||
Reference in New Issue
Block a user