Skip to content

Commit

Permalink
refactor: splits project up into multiple crates
Browse files Browse the repository at this point in the history
feat: adds manifold boolean operation and transformation functions
  • Loading branch information
NickUfer committed Nov 23, 2024
1 parent 01c73e1 commit 9dfd7ec
Show file tree
Hide file tree
Showing 32 changed files with 1,352 additions and 369 deletions.
23 changes: 17 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@ name = "manifold3d"
description = "Bindings for Manifold - a Geometry library for topological robustness"
homepage = "https://github.com/NickUfer/manifold3d-rs"
license = "Apache-2.0"
version = "0.0.2"
version = "0.0.3"
edition = "2021"

[lib]
test = false
crate-type = ["cdylib", "rlib", "staticlib"]

[dependencies]
thiserror = "2.0"
num-traits = "0.2.19"
manifold3d-types = { path = "crates/types", version = "0.0.1" }
manifold3d-macros = { path = "crates/macros", version = "0.0.1" }
manifold3d-sys = { version = "0.0.3" }
nalgebra = { version = "0.33.0", optional = true }
thiserror = "2.0.3"

[features]
nalgebra_interop = ["nalgebra"]
nalgebra_interop = ["manifold3d-types/nalgebra_interop"]
export = ["manifold3d-sys/export"]
parallel = ["manifold3d-sys/parallel"]
parallel = ["manifold3d-sys/parallel"]

[workspace]
members = [
"crates/macros",
"crates/tests",
"crates/types"
]
10 changes: 10 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use std::env;

fn main() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();

if target_arch == "wasm32" && target_os == "emscripten" {
println!("cargo:rustc-link-arg=--no-entry");
}
}
17 changes: 17 additions & 0 deletions crates/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "manifold3d-macros"
description = "Macros for the manifold3d crate. An internal dependency"
homepage = "https://github.com/NickUfer/manifold3d-rs"
repository = "https://github.com/NickUfer/manifold3d-rs/tree/master/crates/macros"
license = "Apache-2.0"
version = "0.0.1"
edition = "2021"
include = ["/src", "/LICENSE"]

[lib]
proc-macro = true

[dependencies]
syn = "2.0.89"
quote = "1.0.37"
proc-macro2 = "1.0.92"
1 change: 1 addition & 0 deletions crates/macros/LICENSE
66 changes: 66 additions & 0 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use proc_macro::TokenStream;
use quote::quote;
use std::sync::atomic::AtomicU64;
use std::sync::Mutex;
use syn::ItemStruct;

static UNIQUE_COUNTER: Mutex<AtomicU64> = Mutex::new(AtomicU64::new(0));

#[proc_macro_attribute]
pub fn manifold_warp(_attr: TokenStream, input: TokenStream) -> TokenStream {
let structt = syn::parse_macro_input!(input as ItemStruct);
let struct_ident = structt.ident.clone();
let struct_name = struct_ident.to_string();

let unique_id = match UNIQUE_COUNTER.lock() {
Ok(guard) => guard.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
Err(e) => panic!("Could not lock unique counter: {}", e),
};

let extern_c_fn_ident = proc_macro2::Ident::new(
format!(
"manifold3d_manifold_extern_c_warp_fn_{}_{}",
struct_name.to_ascii_lowercase(),
unique_id
)
.as_str(),
proc_macro2::Span::call_site(),
);

let output = quote!(
#structt

const _: () = {
use manifold3d::types::manifold::vertex::WarpImpl;

#[no_mangle]
#[doc(hidden)]
pub unsafe extern "C" fn #extern_c_fn_ident(
x: f64,
y: f64,
z: f64,
ctx: *mut ::std::os::raw::c_void
) -> manifold3d::sys::ManifoldVec3 {
let warp = &*(ctx as *mut #struct_ident);
let result = warp.warp_vertex(manifold3d::types::math::Point3::new(x, y, z));
result.into()
}

#[automatically_derived]
impl manifold3d::types::manifold::vertex::ExternCWarpFn for #struct_ident {
fn extern_c_warp_fn(&self) -> unsafe extern "C" fn(
f64,
f64,
f64,
*mut std::os::raw::c_void
) -> manifold3d::sys::ManifoldVec3 {
#extern_c_fn_ident
}
}
};

#[automatically_derived]
impl manifold3d::types::manifold::vertex::Warp for #struct_ident {}
);
output.into()
}
12 changes: 12 additions & 0 deletions crates/tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "manifold3d-tests"
description = "Tests for the manifold3d crate. An internal dependency"
homepage = "https://github.com/NickUfer/manifold3d-rs"
repository = "https://github.com/NickUfer/manifold3d-rs/tree/master/crates/tests"
license = "Apache-2.0"
version = "0.0.1"
edition = "2021"
include = ["/src", "/LICENSE"]

[dependencies]
manifold3d = { path = "../..", version = "0.0.3" }
1 change: 1 addition & 0 deletions crates/tests/LICENSE
1 change: 1 addition & 0 deletions crates/tests/src/manifold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

96 changes: 96 additions & 0 deletions crates/tests/src/manifold3d/manifold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use manifold3d::macros::manifold_warp;
use manifold3d::types::manifold::vertex;
use manifold3d::{types, BooleanOperation, Manifold};
use std::pin::Pin;

#[test]
fn test_translation() {
let original = Manifold::new_cuboid(1u8, 1u8, 1u8, true);
let translated = original.translate(types::math::Vec3::new(1.0, -1.0, 3.0));

assert_eq!(
translated.bounding_box().min_point(),
types::math::Point3::new(0.5, -1.5, 2.5)
);
assert_eq!(
translated.bounding_box().max_point(),
types::math::Point3::new(1.5, -0.5, 3.5)
);
}

#[test]
fn test_boolean_subtraction() {
let manifold = Manifold::new_cuboid(1u8, 1u8, 1u8, true);
let expected_bounding_box = manifold.bounding_box();

let other =
Manifold::new_cuboid(1u8, 1u8, 1u8, true).translate(types::math::Vec3::new(0.0, 0.5, 0.0));
let result = manifold.boolean(&other, BooleanOperation::Subtract);
let result_bounding_box = result.bounding_box();

assert_eq!(
result_bounding_box.min_point(),
expected_bounding_box.min_point()
);
assert_eq!(result_bounding_box.max_point().x, 0.5);
assert_eq!(result_bounding_box.max_point().y, 0.0);
assert_eq!(result_bounding_box.max_point().z, 0.5);
}

#[test]
fn test_batch_boolean_subtraction() {
let manifold = Manifold::new_cuboid(1u8, 1u8, 1u8, true);

// Removes all edges to form a cross
let others = vec![
Manifold::new_cuboid(1u8, 1u8, 1u8, true)
.translate(types::math::Vec3::new(0.75, 0.75, 0.0)),
Manifold::new_cuboid(1u8, 1u8, 1u8, true)
.translate(types::math::Vec3::new(-0.75, -0.75, 0.0)),
Manifold::new_cuboid(1u8, 1u8, 1u8, true)
.translate(types::math::Vec3::new(0.75, -0.75, 0.0)),
Manifold::new_cuboid(1u8, 1u8, 1u8, true)
.translate(types::math::Vec3::new(-0.75, 0.75, 0.0)),
];
let result = manifold.batch_boolean(&others, BooleanOperation::Subtract);

assert_eq!(result.vertex_count(), 24);
}

#[test]
fn test_linear_warping() {
#[manifold_warp]
pub struct TranslationWarp {
translation: types::math::Vec3,
}

impl vertex::WarpImpl for TranslationWarp {
fn warp_vertex(&self, vertex: types::math::Point3) -> types::math::Point3 {
let result = types::math::Point3::new(
vertex.x + self.translation.x,
vertex.y + self.translation.y,
vertex.z + self.translation.z,
);
result
}
}

let manifold = Manifold::new_cuboid(1u8, 1u8, 1u8, true);
let expected_bounding_box = manifold.bounding_box();

let translation_warp = TranslationWarp {
translation: types::math::Vec3::new(1.0, 1.0, 1.0),
};

let translation_warp = Pin::new(&translation_warp);
let result = manifold.warp(translation_warp);
let result_bounding_box = result.bounding_box();
assert_eq!(
result_bounding_box.min_point(),
expected_bounding_box.min_point() + 1.0
);
assert_eq!(
result_bounding_box.max_point(),
expected_bounding_box.max_point() + 1.0
);
}
1 change: 1 addition & 0 deletions crates/tests/src/manifold3d/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod manifold;
18 changes: 18 additions & 0 deletions crates/types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "manifold3d-types"
description = "Types for the manifold3d crate. An internal dependency"
homepage = "https://github.com/NickUfer/manifold3d-rs"
repository = "https://github.com/NickUfer/manifold3d-rs/tree/master/crates/types"
license = "Apache-2.0"
version = "0.0.1"
edition = "2021"
include = ["/src", "/LICENSE"]

[dependencies]
thiserror = "2.0.3"
num-traits = "0.2.19"
nalgebra = { version = "0.33.0", optional = true }
manifold3d-sys = "0.0.3"

[features]
nalgebra_interop = ["nalgebra"]
1 change: 1 addition & 0 deletions crates/types/LICENSE
2 changes: 2 additions & 0 deletions crates/types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod manifold;
pub mod math;
1 change: 1 addition & 0 deletions crates/types/src/manifold/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod vertex;
19 changes: 19 additions & 0 deletions crates/types/src/manifold/vertex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::math;
use manifold3d_sys::ManifoldVec3;

pub trait Warp: WarpImpl + ExternCWarpFn {}

pub trait WarpImpl {
fn warp_vertex(&self, vertex: math::Point3) -> math::Point3;
}

pub trait ExternCWarpFn {
fn extern_c_warp_fn(
&self,
) -> unsafe extern "C" fn(
arg1: f64,
arg2: f64,
arg3: f64,
arg4: *mut ::std::os::raw::c_void,
) -> ManifoldVec3;
}
42 changes: 42 additions & 0 deletions crates/types/src/math/matrix4x3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::math;

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Matrix4x3 {
pub rows: [math::Vec3; 4],
}

impl Matrix4x3 {
pub fn new(rows: [math::Vec3; 4]) -> Self {
Self { rows }
}
}

#[cfg(feature = "nalgebra_interop")]
impl From<nalgebra::Matrix4x3<f64>> for Matrix4x3 {
fn from(matrix: nalgebra::Matrix4x3<f64>) -> Self {
Matrix4x3 {
rows: [
math::Vec3 {
x: matrix.m11,
y: matrix.m12,
z: matrix.m13,
},
math::Vec3 {
x: matrix.m21,
y: matrix.m22,
z: matrix.m23,
},
math::Vec3 {
x: matrix.m31,
y: matrix.m32,
z: matrix.m33,
},
math::Vec3 {
x: matrix.m41,
y: matrix.m42,
z: matrix.m43,
},
],
}
}
}
17 changes: 17 additions & 0 deletions crates/types/src/math/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
mod matrix4x3;
mod non_negative_num;
mod normalized_angle;
mod point2;
mod point3;
mod positive_num;
mod vec2;
mod vec3;

pub use matrix4x3::*;
pub use non_negative_num::*;
pub use normalized_angle::*;
pub use point2::*;
pub use point3::*;
pub use positive_num::*;
pub use vec2::*;
pub use vec3::*;
Loading

0 comments on commit 9dfd7ec

Please sign in to comment.