Skip to content

Commit

Permalink
ENH: revert boolean tool to mcut
Browse files Browse the repository at this point in the history
Change-Id: I1aca763869e107a996519cb74e025043407005f2
(cherry picked from commit f7865828cf4b7b3ab8987bf0fc3d45efad2f08fe)
  • Loading branch information
ArthurBambulab authored and lanewei120 committed Jul 7, 2023
1 parent b55a5b7 commit c7ed4e7
Show file tree
Hide file tree
Showing 38 changed files with 39,957 additions and 5 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,6 @@ function(bambustudio_copy_dlls target config postfix output_dlls)
${_out_dir}/TKXSBase.dll

${_out_dir}/freetype.dll

PARENT_SCOPE
)

Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_subdirectory(Shiny)
add_subdirectory(semver)
add_subdirectory(libigl)
add_subdirectory(hints)
add_subdirectory(mcut)

# Adding libnest2d project for bin packing...
add_subdirectory(libnest2d)
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ if (_opts)
target_compile_options(libslic3r_cgal PRIVATE "${_opts_bad}")
endif()

target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} libigl)
target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} libigl mcut)

if (MSVC AND "${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") # 32 bit MSVC workaround
target_compile_definitions(libslic3r_cgal PRIVATE CGAL_DO_NOT_USE_MPZF)
Expand Down Expand Up @@ -492,6 +492,7 @@ target_link_libraries(libslic3r
ZLIB::ZLIB
${OCCT_LIBS}
Clipper2
mcut
)

if(NOT WIN32)
Expand Down
176 changes: 173 additions & 3 deletions src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ MeshBoolean::cgal::CGALMeshPtr get_cgalmesh(const CSGPartT &csgpart)
return ret;
}

// This method can be overriden when a specific CSGPart type supports caching
// of the voxel grid
template<class CSGPartT>
MeshBoolean::mcut::McutMeshPtr get_mcutmesh(const CSGPartT& csgpart)
{
const indexed_triangle_set* its = csg::get_mesh(csgpart);
indexed_triangle_set dummy;

if (!its)
its = &dummy;

MeshBoolean::mcut::McutMeshPtr ret;

indexed_triangle_set m = *its;
its_transform(m, get_transform(csgpart), true);

try {
ret = MeshBoolean::mcut::triangle_mesh_to_mcut(m);
}
catch (...) {
// errors are ignored, simply return null
ret = nullptr;
}

return ret;
}

namespace detail_cgal {

Expand Down Expand Up @@ -83,6 +109,50 @@ std::vector<CGALMeshPtr> get_cgalptrs(Ex policy, const Range<It> &csgrange)

} // namespace detail

namespace detail_mcut {

using MeshBoolean::mcut::McutMeshPtr;

inline void perform_csg(CSGType op, McutMeshPtr& dst, McutMeshPtr& src)
{
if (!dst && op == CSGType::Union && src) {
dst = std::move(src);
return;
}

if (!dst || !src)
return;

switch (op) {
case CSGType::Union:
MeshBoolean::mcut::do_boolean(*dst, *src,"UNION");
break;
case CSGType::Difference:
MeshBoolean::mcut::do_boolean(*dst, *src,"A_NOT_B");
break;
case CSGType::Intersection:
MeshBoolean::mcut::do_boolean(*dst, *src,"INTERSECTION");
break;
}
}

template<class Ex, class It>
std::vector<McutMeshPtr> get_mcutptrs(Ex policy, const Range<It>& csgrange)
{
std::vector<McutMeshPtr> ret(csgrange.size());
execution::for_each(policy, size_t(0), csgrange.size(),
[&csgrange, &ret](size_t i) {
auto it = csgrange.begin();
std::advance(it, i);
auto& csgpart = *it;
ret[i] = get_mcutmesh(csgpart);
});

return ret;
}

} // namespace mcut_detail

// Process the sequence of CSG parts with CGAL.
template<class It>
void perform_csgmesh_booleans_cgal(MeshBoolean::cgal::CGALMeshPtr &cgalm,
Expand Down Expand Up @@ -133,6 +203,58 @@ void perform_csgmesh_booleans_cgal(MeshBoolean::cgal::CGALMeshPtr &cgalm,
cgalm = std::move(opstack.top().cgalptr);
}

// Process the sequence of CSG parts with mcut.
template<class It>
void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm,
const Range<It>& csgrange)
{
using MeshBoolean::mcut::McutMesh;
using MeshBoolean::mcut::McutMeshPtr;
using namespace detail_mcut;

struct Frame {
CSGType op; McutMeshPtr mcutptr;
explicit Frame(CSGType csgop = CSGType::Union)
: op{ csgop }
, mcutptr{ MeshBoolean::mcut::triangle_mesh_to_mcut(indexed_triangle_set{}) }
{}
};

std::stack opstack{ std::vector<Frame>{} };

opstack.push(Frame{});

std::vector<McutMeshPtr> McutMeshes = get_mcutptrs(ex_tbb, csgrange);

size_t csgidx = 0;
for (auto& csgpart : csgrange) {

auto op = get_operation(csgpart);
McutMeshPtr& mcutptr = McutMeshes[csgidx++];

if (get_stack_operation(csgpart) == CSGStackOp::Push) {
opstack.push(Frame{ op });
op = CSGType::Union;
}

Frame* top = &opstack.top();

perform_csg(get_operation(csgpart), top->mcutptr, mcutptr);

if (get_stack_operation(csgpart) == CSGStackOp::Pop) {
McutMeshPtr src = std::move(top->mcutptr);
auto popop = opstack.top().op;
opstack.pop();
McutMeshPtr& dst = opstack.top().mcutptr;
perform_csg(popop, dst, src);
}
}

mcutm = std::move(opstack.top().mcutptr);

}


template<class It, class Visitor>
It check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn)
{
Expand Down Expand Up @@ -184,18 +306,66 @@ It check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn)
}

template<class It>
It check_csgmesh_booleans(const Range<It> &csgrange)
It check_csgmesh_booleans(const Range<It> &csgrange, bool use_mcut=false)
{
if(!use_mcut)
return check_csgmesh_booleans(csgrange, [](auto &) {});
else {
using namespace detail_mcut;

std::vector<McutMeshPtr> McutMeshes(csgrange.size());
auto check_part = [&csgrange, &McutMeshes](size_t i) {
auto it = csgrange.begin();
std::advance(it, i);
auto& csgpart = *it;
auto m = get_mcutmesh(csgpart);

// mesh can be nullptr if this is a stack push or pull
if (!get_mesh(csgpart) && get_stack_operation(csgpart) != CSGStackOp::Continue) {
McutMeshes[i] = MeshBoolean::mcut::triangle_mesh_to_mcut(indexed_triangle_set{});
return;
}

try {
if (!m || MeshBoolean::mcut::empty(*m))
return;
}
catch (...) { return; }

McutMeshes[i] = std::move(m);
};
execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part);

It ret = csgrange.end();
for (size_t i = 0; i < csgrange.size(); ++i) {
if (!McutMeshes[i]) {
auto it = csgrange.begin();
std::advance(it, i);

if (ret == csgrange.end())
ret = it;
}
}

return ret;
}
}

template<class It>
MeshBoolean::cgal::CGALMeshPtr perform_csgmesh_booleans(const Range<It> &csgparts)
{
auto ret = MeshBoolean::cgal::triangle_mesh_to_cgal(indexed_triangle_set{});
if (ret) {
if (ret)
perform_csgmesh_booleans_cgal(ret, csgparts);
}
return ret;
}

template<class It>
MeshBoolean::mcut::McutMeshPtr perform_csgmesh_booleans_mcut(const Range<It>& csgparts)
{
auto ret = MeshBoolean::mcut::triangle_mesh_to_mcut(indexed_triangle_set{});
if (ret)
perform_csgmesh_booleans_mcut(ret, csgparts);
return ret;
}

Expand Down
Loading

0 comments on commit c7ed4e7

Please sign in to comment.