123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- ///|/ Copyright (c) Prusa Research 2022 - 2023 Tomáš Mészáros @tamasmeszaros
- ///|/
- ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
- ///|/
- #ifndef VOXELIZECSGMESH_HPP
- #define VOXELIZECSGMESH_HPP
- #include <functional>
- #include <stack>
- #include "CSGMesh.hpp"
- #include "libslic3r/OpenVDBUtils.hpp"
- #include "libslic3r/Execution/ExecutionTBB.hpp"
- namespace Slic3r { namespace csg {
- using VoxelizeParams = MeshToGridParams;
- // This method can be overriden when a specific CSGPart type supports caching
- // of the voxel grid
- template<class CSGPartT>
- VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, VoxelizeParams params)
- {
- const indexed_triangle_set *its = csg::get_mesh(csgpart);
- VoxelGridPtr ret;
- params.trafo(params.trafo() * csg::get_transform(csgpart));
- if (its)
- ret = mesh_to_grid(*its, params);
- return ret;
- }
- namespace detail {
- inline void perform_csg(CSGType op, VoxelGridPtr &dst, VoxelGridPtr &src)
- {
- if (!dst || !src)
- return;
- switch (op) {
- case CSGType::Union:
- if (is_grid_empty(*dst) && !is_grid_empty(*src))
- dst = clone(*src);
- else
- grid_union(*dst, *src);
- break;
- case CSGType::Difference:
- grid_difference(*dst, *src);
- break;
- case CSGType::Intersection:
- grid_intersection(*dst, *src);
- break;
- }
- }
- } // namespace detail
- // Convert the input csgrange to a voxel grid performing the boolean operations in the voxel realm.
- template<class It>
- VoxelGridPtr voxelize_csgmesh(const Range<It> &csgrange,
- const VoxelizeParams ¶ms = {})
- {
- using namespace detail;
- VoxelGridPtr ret;
- std::vector<VoxelGridPtr> grids (csgrange.size());
- execution::for_each(ex_tbb, size_t(0), csgrange.size(), [&](size_t csgidx) {
- if (params.statusfn() && params.statusfn()(-1))
- return;
- auto it = csgrange.begin();
- std::advance(it, csgidx);
- auto &csgpart = *it;
- grids[csgidx] = get_voxelgrid(csgpart, params);
- }, execution::max_concurrency(ex_tbb));
- size_t csgidx = 0;
- struct Frame { CSGType op = CSGType::Union; VoxelGridPtr grid; };
- std::stack opstack{std::vector<Frame>{}};
- opstack.push({CSGType::Union, mesh_to_grid({}, params)});
- for (auto &csgpart : csgrange) {
- if (params.statusfn() && params.statusfn()(-1))
- break;
- auto &partgrid = grids[csgidx++];
- auto op = get_operation(csgpart);
- if (get_stack_operation(csgpart) == CSGStackOp::Push) {
- opstack.push({op, mesh_to_grid({}, params)});
- op = CSGType::Union;
- }
- Frame *top = &opstack.top();
- perform_csg(get_operation(csgpart), top->grid, partgrid);
- if (get_stack_operation(csgpart) == CSGStackOp::Pop) {
- VoxelGridPtr popgrid = std::move(top->grid);
- auto popop = opstack.top().op;
- opstack.pop();
- VoxelGridPtr &grid = opstack.top().grid;
- perform_csg(popop, grid, popgrid);
- }
- }
- ret = std::move(opstack.top().grid);
- return ret;
- }
- }} // namespace Slic3r::csg
- #endif // VOXELIZECSGMESH_HPP
|