Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ edition = "2024"
[features]

[dependencies]
rayon = "1.11.0"
nalgebra = { version = "0.34", default-features = false, features = ["std"] }
9 changes: 6 additions & 3 deletions src/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::common::{AABB, AABBOverlap};
use crate::utils::atomic_add_i32;
use crate::vec::vec_uninit;
use nalgebra::{Matrix3x4, Point3, Vector3};
use rayon::prelude::*;
use std::fmt::Debug;
use std::mem;

Expand Down Expand Up @@ -313,9 +314,11 @@ impl Collider {
);

// copy in leaf node Boxes
for i in 0..leaf_bb.len() {
self.node_bbox[i * 2] = leaf_bb[i];
}
self.node_bbox
.par_iter_mut()
.step_by(2)
.enumerate()
.for_each(|(i, b)| *b = leaf_bb[i]);

// create global counters
let mut counter = vec![0; self.num_internal()];
Expand Down
65 changes: 38 additions & 27 deletions src/meshboolimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::utils::{atomic_add_i32, mat3, mat4, next3_i32, next3_usize};
use crate::vec::{vec_resize, vec_resize_nofill, vec_uninit};
use crate::{ManifoldError, MeshGL};
use nalgebra::{Matrix3x4, Point3, Vector3, Vector4};
use rayon::prelude::*;
use std::cmp::Ordering as CmpOrdering;
use std::collections::{BTreeMap, HashMap};
use std::f64;
Expand Down Expand Up @@ -160,7 +161,7 @@ impl<'a, const USE_PROP: bool, F: FnMut(i32, i32, i32)> PrepHalfedges<'a, USE_PR
} else {
self.tri_vert[tri as usize][j as usize]
};
debug_assert!(v0 != v1, "topological degeneracy");
debug_assert_ne!(v0, v1, "topological degeneracy");
self.halfedges[e as usize] = Halfedge {
start_vert: v0,
end_vert: v1,
Expand Down Expand Up @@ -556,26 +557,32 @@ impl MeshBoolImpl {
tri: i32,
}
let mut tri_priority = unsafe { vec_uninit(num_tri) };
for tri in 0..num_tri {
self.mesh_relation.tri_ref[tri].coplanar_id = -1;
if self.halfedge[3 * tri].start_vert < 0 {
tri_priority[tri] = TriPriority {
area2: 0.0,
tri: tri as i32,
};
continue;
}

let v = self.vert_pos[self.halfedge[3 * tri].start_vert as usize];
tri_priority[tri] = TriPriority {
area2: (self.vert_pos[self.halfedge[3 * tri].end_vert as usize] - v)
.cross(&(self.vert_pos[self.halfedge[3 * tri + 1].end_vert as usize] - v))
.magnitude_squared(),
tri: tri as i32,
};
}
self.mesh_relation.tri_ref[0..num_tri]
.par_iter_mut()
.enumerate()
.map(|(tri, mesh_relation_tri_ref)| {
mesh_relation_tri_ref.coplanar_id = -1;
if self.halfedge[3 * tri].start_vert < 0 {
TriPriority {
area2: 0.0,
tri: tri as i32,
}
} else {
let v = self.vert_pos[self.halfedge[3 * tri].start_vert as usize];
TriPriority {
area2: (self.vert_pos[self.halfedge[3 * tri].end_vert as usize] - v)
.cross(
&(self.vert_pos[self.halfedge[3 * tri + 1].end_vert as usize] - v),
)
.magnitude_squared(),
tri: tri as i32,
}
}
})
.collect_into_vec(&mut tri_priority);

tri_priority.sort_by(|a, b| b.area2.partial_cmp(&a.area2).unwrap_or(CmpOrdering::Equal));
tri_priority
.par_sort_by(|a, b| b.area2.partial_cmp(&a.area2).unwrap_or(CmpOrdering::Equal));

let mut interior_halfedges: Vec<i32> = Vec::default();
for tp in &tri_priority {
Expand Down Expand Up @@ -675,8 +682,8 @@ impl MeshBoolImpl {
}
}

let mut ids: Vec<i32> = (0..num_halfedge).collect();
ids.sort_by_key(|&i| edge[i as usize]);
let mut ids: Vec<i32> = (0..num_halfedge).into_par_iter().collect();
ids.par_sort_by_key(|&i| edge[i as usize]);
ids
} else {
// For larger vertex count, we separate the ids into slices for halfedges
Expand Down Expand Up @@ -748,7 +755,7 @@ impl MeshBoolImpl {
ids[i as usize] = i;
}

ids.sort_unstable_by_key(|&i| {
ids[start as usize..end as usize].sort_unstable_by_key(|&i| {
let entry = &entries[i as usize];
(entry.large_vert, entry.tri)
});
Expand Down Expand Up @@ -952,6 +959,7 @@ impl MeshBoolImpl {
vec_resize(&mut self.vert_normal, num_vert);

let vert_halfedge_map: Vec<AtomicI32> = (0..self.num_vert())
.into_par_iter()
.map(|_| AtomicI32::new(i32::MAX))
.collect();

Expand Down Expand Up @@ -1005,10 +1013,13 @@ impl MeshBoolImpl {
}
}
} else {
for i in 0..self.halfedge.len() {
let i = i as i32;
atomic_min(i, self.halfedge[i as usize].start_vert);
}
self.halfedge
.par_iter_mut()
.enumerate()
.for_each(|(i, halfedge)| {
let i = i as i32;
atomic_min(i, halfedge.start_vert);
});
}

for vert in 0..self.num_vert() {
Expand Down
17 changes: 11 additions & 6 deletions src/parallel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{common::LossyInto, vec::vec_uninit};
use rayon::prelude::*;
use std::ops::{Add, AddAssign};

///Compute the inclusive prefix sum for the range `[first, last)`
Expand Down Expand Up @@ -66,7 +67,7 @@ where
///must be equal or non-overlapping.
pub fn exclusive_scan_in_place<IO>(io: &mut [IO], init: IO)
where
IO: Copy + AddAssign,
IO: Copy + AddAssign + Send + Sync,
{
let mut acc = init;
for i in 0..io.len() {
Expand Down Expand Up @@ -128,12 +129,16 @@ where
///The map range, input range and the output range must not overlap.
pub fn gather<IO, Map>(map: &[Map], input: &[IO], output: &mut [IO])
where
IO: Copy,
Map: Copy + LossyInto<usize>,
IO: Copy + Send + Sync,
Map: Copy + LossyInto<usize> + Send + Sync,
{
for i in 0..map.len() {
output[i] = input[map[i].lossy_into()];
}
output
.par_iter_mut()
.zip(map.par_iter())
.for_each(|(o, m)| {
let i: usize = (*m).lossy_into();
*o = input[i];
});
}

///`gather` copies elements from a source array into a destination range
Expand Down
Loading