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
18 changes: 16 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ fn test() {
///from the same run and share the same faceID. These faces will be planar
///within the output tolerance.
///
///The halfedgeTangent vector is used to specify the weighted tangent vectors of
///The halfedge_tangent vector is used to specify the weighted tangent vectors of
///each halfedge for the purpose of using the Refine methods to create a
///smoothly-interpolated surface. They can also be output when calculated
///automatically by the Smooth functions.
Expand Down Expand Up @@ -155,6 +155,11 @@ pub struct MeshGL {
/// none are given, they will be filled in with Manifold's coplanar face
/// calculation based on mesh tolerance.
pub face_id: Vec<u32>,
/// Optional: The X-Y-Z-W weighted tangent vectors for smooth Refine(). If
/// non-empty, must be exactly four times as long as Mesh.triVerts. Indexed
/// as 4 * (3 * tri + i) + j, i < 3, j < 4, representing the tangent value
/// Mesh.triVerts[tri][i] along the CCW edge. If empty, mesh is faceted.
pub halfedge_tangent: Vec<f32>,
/// Tolerance for mesh simplification. When creating a Manifold, the tolerance
/// used will be the maximum of this and a baseline tolerance from the size of
/// the bounding box. Any edge shorter than tolerance may be collapsed.
Expand All @@ -175,6 +180,7 @@ impl Default for MeshGL {
run_original_id: Vec::default(),
run_transform: Vec::default(),
face_id: Vec::default(),
halfedge_tangent: Vec::default(),
}
}
}
Expand All @@ -189,7 +195,7 @@ impl MeshGL {
}
}

#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
pub struct MeshBool {
meshbool_impl: MeshBoolImpl,
}
Expand Down Expand Up @@ -327,6 +333,12 @@ impl MeshBool {

let mut tri_verts: Vec<u32> = vec![0; 3 * num_tri];

let out_halfedge_tangent = meshbool_impl
.halfedge_tangent
.iter()
.flat_map(|t| [t.x as f32, t.y as f32, t.z as f32, t.w as f32])
.collect::<Vec<f32>>();

// Sort the triangles into runs
let mut face_id: Vec<u32> = vec![0; num_tri];
let mut tri_new2old: Vec<_> = (0..num_tri).map(|i| i as i32).collect();
Expand Down Expand Up @@ -403,6 +415,7 @@ impl MeshBool {

return MeshGL {
num_prop: out_num_prop,
halfedge_tangent: out_halfedge_tangent,
vert_properties,
tri_verts,
merge_from_vert: Vec::default(),
Expand Down Expand Up @@ -483,6 +496,7 @@ impl MeshBool {

MeshGL {
num_prop: out_num_prop,
halfedge_tangent: out_halfedge_tangent,
vert_properties,
tri_verts,
merge_from_vert,
Expand Down
24 changes: 23 additions & 1 deletion src/mesh_fixes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::shared::Halfedge;
use nalgebra::{Matrix3, Vector3};
use nalgebra::{Matrix3, Vector3, Vector4};
use std::mem;

#[inline]
Expand All @@ -18,6 +18,28 @@ pub fn transform_normal(transform: Matrix3<f64>, mut normal: Vector3<f64>) -> Ve
normal
}

pub struct TransformTangents<'a> {
pub tangent: &'a mut [Vector4<f64>],
pub edge_offset: i32,
pub transform: Matrix3<f64>,
pub invert: bool,
pub old_tangents: &'a [Vector4<f64>],
pub halfedge: &'a [Halfedge],
}

impl<'a> TransformTangents<'a> {
pub fn call(&mut self, edge_out: i32) {
let edge_in = if self.invert {
self.halfedge[flip_halfedge(edge_out) as usize].paired_halfedge
} else {
edge_out
};
self.tangent[(edge_out + self.edge_offset) as usize] = (self.transform
* self.old_tangents[edge_in as usize].xyz())
.push(self.old_tangents[edge_in as usize].w);
}
}

pub struct FlipTris<'a> {
pub halfedge: &'a mut [Halfedge],
}
Expand Down
44 changes: 31 additions & 13 deletions src/meshboolimpl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::collider::Collider;
use crate::common::{AABB, sun_acos};
use crate::disjoint_sets::DisjointSets;
use crate::mesh_fixes::{FlipTris, transform_normal};
use crate::mesh_fixes::{FlipTris, TransformTangents, transform_normal};
use crate::parallel::exclusive_scan_in_place;
use crate::shared::{Halfedge, TriRef, max_epsilon, next_halfedge, normal_transform};
use crate::utils::{atomic_add_i32, mat3, mat4, next3_i32, next3_usize};
Expand Down Expand Up @@ -59,6 +59,7 @@ pub struct MeshBoolImpl {
// function
pub vert_normal: Vec<Vector3<f64>>,
pub face_normal: Vec<Vector3<f64>>,
pub halfedge_tangent: Vec<Vector4<f64>>,
pub mesh_relation: MeshRelationD,
pub collider: Collider,
}
Expand Down Expand Up @@ -231,12 +232,10 @@ impl MeshBoolImpl {
return manifold;
}

// if (!manifold::all_of(meshGL.halfedgeTangent.begin(),
// meshGL.halfedgeTangent.end(),
// [](Precision x) { return std::isfinite(x); })) {
// MakeEmpty(Error::InvalidConstruction);
// return;
// }
if mesh_gl.halfedge_tangent.iter().any(|x| !x.is_finite()) {
manifold.make_empty(ManifoldError::InvalidConstruction);
return manifold;
}

let mut prop2vert: Vec<i32>;
if !mesh_gl.merge_from_vert.is_empty() {
Expand Down Expand Up @@ -278,12 +277,11 @@ impl MeshBoolImpl {
}
}

// halfedgeTangent_.resize_nofill(meshGL.halfedgeTangent.len() / 4);
// for i in 0..halfedgeTangent_.len() {
// for j in [0, 1, 2, 3] {
// halfedgeTangent_[i][j] = meshGL.halfedgeTangent[4 * i + j];
// }
// }
manifold.halfedge_tangent = mesh_gl
.halfedge_tangent
.chunks(4)
.map(|t| [t[0] as f64, t[1] as f64, t[2] as f64, t[3] as f64].into())
.collect::<Vec<nalgebra::Vector4<f64>>>();

let mut tri_ref: Vec<TriRef> = unsafe { vec_uninit(mesh_gl.num_tri()) };

Expand Down Expand Up @@ -852,6 +850,7 @@ impl MeshBoolImpl {
self.halfedge = Vec::default();
self.vert_normal = Vec::default();
self.face_normal = Vec::default();
self.halfedge_tangent = Vec::default();
self.mesh_relation = MeshRelationD::default();
self.status = status;
}
Expand Down Expand Up @@ -883,6 +882,9 @@ impl MeshBoolImpl {
result.properties = self.properties.clone();
result.bbox = self.bbox;
result.halfedge = self.halfedge.clone();
result
.halfedge_tangent
.resize(self.halfedge_tangent.len(), Default::default());

result.mesh_relation.original_id = -1;
for m in &mut result.mesh_relation.mesh_id_transform {
Expand All @@ -906,6 +908,21 @@ impl MeshBoolImpl {
}

let invert = mat3(transform).determinant() < 0.0;

if self.halfedge_tangent.len() > 0 {
let mut t = TransformTangents {
tangent: &mut result.halfedge_tangent,
edge_offset: 0,
transform: mat3(transform),
invert,
old_tangents: &self.halfedge_tangent,
halfedge: &self.halfedge,
};
for i in 0..self.halfedge_tangent.len() {
t.call(i as i32);
}
}

if invert {
for tri in 0..result.num_tri() {
FlipTris {
Expand Down Expand Up @@ -1185,6 +1202,7 @@ impl Default for MeshBoolImpl {
properties: Vec::default(),
vert_normal: Vec::default(),
face_normal: Vec::default(),
halfedge_tangent: Vec::default(),
mesh_relation: MeshRelationD::default(),
collider: Collider::default(),
}
Expand Down