diff --git a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp index 5c64c65e0d..da1ddce3f9 100644 --- a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp +++ b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp @@ -5,15 +5,58 @@ #include "libslic3r/MeshBoolean.hpp" -namespace Slic3r { +namespace Slic3r { namespace csg { + +// This method can be overriden when a specific CSGPart type supports caching +// of the voxel grid +template +MeshBoolean::cgal::CGALMeshPtr get_cgalmesh(const CSGPartT &csgpart) +{ + const indexed_triangle_set *its = csg::get_mesh(csgpart); + MeshBoolean::cgal::CGALMeshPtr ret; + + if (its) { + indexed_triangle_set m = *its; + its_transform(m, get_transform(csgpart)); + ret = MeshBoolean::cgal::triangle_mesh_to_cgal(m); + } + + return ret; +} template void perform_csgmesh_booleans(MeshBoolean::cgal::CGALMesh &cgalm, - const Range &csg) + const Range &csgparts) { - + for (auto &csgpart : csgparts) { + auto m = get_cgalmesh(csgpart); + if (m) { + switch (get_operation(csgpart)) { + case CSGType::Union: + MeshBoolean::cgal::plus(cgalm, *m); + break; + case CSGType::Difference: + MeshBoolean::cgal::minus(cgalm, *m); + break; + case CSGType::Intersection: + MeshBoolean::cgal::intersect(cgalm, *m); + break; + } + } + } } +template +MeshBoolean::cgal::CGALMeshPtr perform_csgmesh_booleans(const Range &csgparts) +{ + auto ret = MeshBoolean::cgal::triangle_mesh_to_cgal(indexed_triangle_set{}); + if (ret) + perform_csgmesh_booleans(*ret, csgparts); + + return ret; +} + +} // namespace csg } // namespace Slic3r #endif // PERFORMCSGMESHBOOLEANS_HPP diff --git a/src/libslic3r/CSGMesh/SliceCSGMesh.hpp b/src/libslic3r/CSGMesh/SliceCSGMesh.hpp index 32f7905465..f8a7354204 100644 --- a/src/libslic3r/CSGMesh/SliceCSGMesh.hpp +++ b/src/libslic3r/CSGMesh/SliceCSGMesh.hpp @@ -52,6 +52,8 @@ std::vector slice_csgmesh_ex( return p.area() < double(SCALED_EPSILON) * double(SCALED_EPSILON); }); + // Hopefully, ExPolygons are moved, not copied to new positions + // and that is cheap for expolygons slice.erase(it, slice.end()); } } diff --git a/src/libslic3r/MeshBoolean.hpp b/src/libslic3r/MeshBoolean.hpp index 140c969310..441fc78c11 100644 --- a/src/libslic3r/MeshBoolean.hpp +++ b/src/libslic3r/MeshBoolean.hpp @@ -26,16 +26,17 @@ namespace cgal { struct CGALMesh; struct CGALMeshDeleter { void operator()(CGALMesh *ptr); }; +using CGALMeshPtr = std::unique_ptr; -std::unique_ptr -triangle_mesh_to_cgal(const std::vector &V, - const std::vector &F); +CGALMeshPtr triangle_mesh_to_cgal( + const std::vector &V, + const std::vector &F); -inline std::unique_ptr triangle_mesh_to_cgal(const indexed_triangle_set &M) +inline CGALMeshPtr triangle_mesh_to_cgal(const indexed_triangle_set &M) { return triangle_mesh_to_cgal(M.vertices, M.indices); } -inline std::unique_ptr triangle_mesh_to_cgal(const TriangleMesh &M) +inline CGALMeshPtr triangle_mesh_to_cgal(const TriangleMesh &M) { return triangle_mesh_to_cgal(M.its); } diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 52915a0281..a5873155c4 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -18,11 +18,13 @@ #include #include #include +#include > +#include #include #include #include -#include +//#include #include @@ -128,48 +130,50 @@ void SLAPrint::Steps::apply_printer_corrections(SLAPrintObject &po, SliceOrigin } } - -void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep step) +indexed_triangle_set SLAPrint::Steps::generate_preview_vdb( + SLAPrintObject &po, SLAPrintObjectStep step) { Benchmark bench; bench.start(); + // update preview mesh double vscale = 1. / (2. * po.m_config.layer_height.getFloat()); auto voxparams = csg::VoxelizeParams{} .voxel_scale(vscale) .exterior_bandwidth(1.f) .interior_bandwidth(1.f); + auto grid = csg::voxelize_csgmesh(range(po.m_mesh_to_slice), voxparams); indexed_triangle_set m = grid_to_mesh(*grid); -// if (!m.empty()) { -// // simplify mesh lossless + bench.stop(); -// std::cout << "simplify started" << std::endl; -// int expected_cnt = m.indices.size() * 0.8; //std::pow(po.m_transformed_rmesh.volume() / std::pow(1./vscale, 3), 2./3.); -// std::cout << "expected triangles " << expected_cnt << std::endl; -// float err = std::pow(vscale, 3); -// its_quadric_edge_collapse(m, 0U, &err); -// std::cout << "simplify ended " << m.indices.size() << " triangles" << std::endl; + std::cout << "Preview gen took: " << bench.getElapsedSec() << std::endl; -// std::cout << "cleanup started" << std::endl; -// its_compactify_vertices(m); -// its_merge_vertices(m); -// std::cout << "cleanup ended" << std::endl; -// } + return m; +} - po.m_preview_meshes[step] = TriangleMesh{std::move(m)}; + +void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep step) +{ + MeshBoolean::cgal::CGALMeshPtr cgalptr; + + try { + cgalptr = csg::perform_csgmesh_booleans(range(po.m_mesh_to_slice)); + } catch(...) {} + + if (cgalptr) { + po.m_preview_meshes[step] = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalptr); + } else + po.m_preview_meshes[step] = TriangleMesh{generate_preview_vdb(po, step)}; for (size_t i = size_t(step) + 1; i < slaposCount; ++i) { po.m_preview_meshes[i] = {}; } - bench.stop(); - - std::cout << "Preview gen took: " << bench.getElapsedSec() << std::endl; using namespace std::string_literals; report_status(-2, "Reload preview from step "s + std::to_string(int(step)), SlicingStatus::RELOAD_SLA_PREVIEW); diff --git a/src/libslic3r/SLAPrintSteps.hpp b/src/libslic3r/SLAPrintSteps.hpp index 30dff8628e..3d63cbbadb 100644 --- a/src/libslic3r/SLAPrintSteps.hpp +++ b/src/libslic3r/SLAPrintSteps.hpp @@ -46,7 +46,8 @@ private: void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o); void generate_preview(SLAPrintObject &po, SLAPrintObjectStep step); - + indexed_triangle_set generate_preview_vdb(SLAPrintObject &po, SLAPrintObjectStep step); + public: explicit Steps(SLAPrint *print);