VoxelizeCSGMesh.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. ///|/ Copyright (c) Prusa Research 2022 - 2023 Tomáš Mészáros @tamasmeszaros
  2. ///|/
  3. ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
  4. ///|/
  5. #ifndef VOXELIZECSGMESH_HPP
  6. #define VOXELIZECSGMESH_HPP
  7. #include <functional>
  8. #include <stack>
  9. #include "CSGMesh.hpp"
  10. #include "libslic3r/OpenVDBUtils.hpp"
  11. #include "libslic3r/Execution/ExecutionTBB.hpp"
  12. namespace Slic3r { namespace csg {
  13. using VoxelizeParams = MeshToGridParams;
  14. // This method can be overriden when a specific CSGPart type supports caching
  15. // of the voxel grid
  16. template<class CSGPartT>
  17. VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, VoxelizeParams params)
  18. {
  19. const indexed_triangle_set *its = csg::get_mesh(csgpart);
  20. VoxelGridPtr ret;
  21. params.trafo(params.trafo() * csg::get_transform(csgpart));
  22. if (its)
  23. ret = mesh_to_grid(*its, params);
  24. return ret;
  25. }
  26. namespace detail {
  27. inline void perform_csg(CSGType op, VoxelGridPtr &dst, VoxelGridPtr &src)
  28. {
  29. if (!dst || !src)
  30. return;
  31. switch (op) {
  32. case CSGType::Union:
  33. if (is_grid_empty(*dst) && !is_grid_empty(*src))
  34. dst = clone(*src);
  35. else
  36. grid_union(*dst, *src);
  37. break;
  38. case CSGType::Difference:
  39. grid_difference(*dst, *src);
  40. break;
  41. case CSGType::Intersection:
  42. grid_intersection(*dst, *src);
  43. break;
  44. }
  45. }
  46. } // namespace detail
  47. // Convert the input csgrange to a voxel grid performing the boolean operations in the voxel realm.
  48. template<class It>
  49. VoxelGridPtr voxelize_csgmesh(const Range<It> &csgrange,
  50. const VoxelizeParams &params = {})
  51. {
  52. using namespace detail;
  53. VoxelGridPtr ret;
  54. std::vector<VoxelGridPtr> grids (csgrange.size());
  55. execution::for_each(ex_tbb, size_t(0), csgrange.size(), [&](size_t csgidx) {
  56. if (params.statusfn() && params.statusfn()(-1))
  57. return;
  58. auto it = csgrange.begin();
  59. std::advance(it, csgidx);
  60. auto &csgpart = *it;
  61. grids[csgidx] = get_voxelgrid(csgpart, params);
  62. }, execution::max_concurrency(ex_tbb));
  63. size_t csgidx = 0;
  64. struct Frame { CSGType op = CSGType::Union; VoxelGridPtr grid; };
  65. std::stack opstack{std::vector<Frame>{}};
  66. opstack.push({CSGType::Union, mesh_to_grid({}, params)});
  67. for (auto &csgpart : csgrange) {
  68. if (params.statusfn() && params.statusfn()(-1))
  69. break;
  70. auto &partgrid = grids[csgidx++];
  71. auto op = get_operation(csgpart);
  72. if (get_stack_operation(csgpart) == CSGStackOp::Push) {
  73. opstack.push({op, mesh_to_grid({}, params)});
  74. op = CSGType::Union;
  75. }
  76. Frame *top = &opstack.top();
  77. perform_csg(get_operation(csgpart), top->grid, partgrid);
  78. if (get_stack_operation(csgpart) == CSGStackOp::Pop) {
  79. VoxelGridPtr popgrid = std::move(top->grid);
  80. auto popop = opstack.top().op;
  81. opstack.pop();
  82. VoxelGridPtr &grid = opstack.top().grid;
  83. perform_csg(popop, grid, popgrid);
  84. }
  85. }
  86. ret = std::move(opstack.top().grid);
  87. return ret;
  88. }
  89. }} // namespace Slic3r::csg
  90. #endif // VOXELIZECSGMESH_HPP