mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Group hollowing result (including grid) into one struct
This commit is contained in:
		
							parent
							
								
									e57eca0289
								
							
						
					
					
						commit
						82954ba715
					
				
					 7 changed files with 133 additions and 67 deletions
				
			
		| 
						 | 
				
			
			@ -26,11 +26,36 @@ inline void _scale(S s, TriangleMesh &m) { m.scale(float(s)); }
 | 
			
		|||
template<class S, class = FloatingOnly<S>>
 | 
			
		||||
inline void _scale(S s, Contour3D &m) { for (auto &p : m.points) p *= s; }
 | 
			
		||||
 | 
			
		||||
static TriangleMesh _generate_interior(const TriangleMesh  &mesh,
 | 
			
		||||
                                       const JobController &ctl,
 | 
			
		||||
                                       double               min_thickness,
 | 
			
		||||
                                       double               voxel_scale,
 | 
			
		||||
                                       double               closing_dist)
 | 
			
		||||
struct Interior {
 | 
			
		||||
    TriangleMesh mesh;
 | 
			
		||||
    openvdb::FloatGrid::Ptr gridptr;
 | 
			
		||||
    double closing_distance = 0.;
 | 
			
		||||
    double thickness = 0.;
 | 
			
		||||
    double voxel_scale = 1.;
 | 
			
		||||
    double nb_in = 3.;
 | 
			
		||||
    double nb_out = 3.;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void InteriorDeleter::operator()(Interior *p)
 | 
			
		||||
{
 | 
			
		||||
    delete p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TriangleMesh &get_mesh(Interior &interior)
 | 
			
		||||
{
 | 
			
		||||
    return interior.mesh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TriangleMesh &get_mesh(const Interior &interior)
 | 
			
		||||
{
 | 
			
		||||
    return interior.mesh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
 | 
			
		||||
                                             const JobController &ctl,
 | 
			
		||||
                                             double min_thickness,
 | 
			
		||||
                                             double voxel_scale,
 | 
			
		||||
                                             double closing_dist)
 | 
			
		||||
{
 | 
			
		||||
    double offset = voxel_scale * min_thickness;
 | 
			
		||||
    double D = voxel_scale * closing_dist;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,22 +89,30 @@ static TriangleMesh _generate_interior(const TriangleMesh  &mesh,
 | 
			
		|||
    else ctl.statuscb(70, L("Hollowing"));
 | 
			
		||||
 | 
			
		||||
    double adaptivity = 0.;
 | 
			
		||||
    InteriorPtr interior = InteriorPtr{new Interior{}};
 | 
			
		||||
 | 
			
		||||
    auto omesh = grid_to_mesh(*gridptr, iso_surface, adaptivity);
 | 
			
		||||
    interior->mesh = grid_to_mesh(*gridptr, iso_surface, adaptivity);
 | 
			
		||||
    interior->gridptr = gridptr;
 | 
			
		||||
 | 
			
		||||
    if (ctl.stopcondition()) return {};
 | 
			
		||||
    else ctl.statuscb(100, L("Hollowing"));
 | 
			
		||||
 | 
			
		||||
    return omesh;
 | 
			
		||||
    interior->closing_distance = D;
 | 
			
		||||
    interior->thickness = offset;
 | 
			
		||||
    interior->voxel_scale = voxel_scale;
 | 
			
		||||
    interior->nb_in = narrowb;
 | 
			
		||||
    interior->nb_out = narrowb;
 | 
			
		||||
 | 
			
		||||
    return interior;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &   mesh,
 | 
			
		||||
                                                const HollowingConfig &hc,
 | 
			
		||||
                                                const JobController &  ctl)
 | 
			
		||||
InteriorPtr generate_interior(const TriangleMesh &   mesh,
 | 
			
		||||
                              const HollowingConfig &hc,
 | 
			
		||||
                              const JobController &  ctl)
 | 
			
		||||
{
 | 
			
		||||
    static const double MIN_OVERSAMPL = 3.;
 | 
			
		||||
    static const double MAX_OVERSAMPL = 8.;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    // I can't figure out how to increase the grid resolution through openvdb
 | 
			
		||||
    // API so the model will be scaled up before conversion and the result
 | 
			
		||||
    // scaled down. Voxels have a unit size. If I set voxelSize smaller, it
 | 
			
		||||
| 
						 | 
				
			
			@ -88,26 +121,29 @@ std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &   mesh,
 | 
			
		|||
    //
 | 
			
		||||
    // max 8x upscale, min is native voxel size
 | 
			
		||||
    auto voxel_scale = MIN_OVERSAMPL + (MAX_OVERSAMPL - MIN_OVERSAMPL) * hc.quality;
 | 
			
		||||
    auto meshptr = std::make_unique<TriangleMesh>(
 | 
			
		||||
        _generate_interior(mesh, ctl, hc.min_thickness, voxel_scale,
 | 
			
		||||
                           hc.closing_distance));
 | 
			
		||||
    
 | 
			
		||||
    if (meshptr && !meshptr->empty()) {
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    InteriorPtr interior =
 | 
			
		||||
        generate_interior_verbose(mesh, ctl, hc.min_thickness, voxel_scale,
 | 
			
		||||
                                  hc.closing_distance);
 | 
			
		||||
 | 
			
		||||
    if (interior && !interior->mesh.empty()) {
 | 
			
		||||
 | 
			
		||||
        // This flips the normals to be outward facing...
 | 
			
		||||
        meshptr->require_shared_vertices();
 | 
			
		||||
        indexed_triangle_set its = std::move(meshptr->its);
 | 
			
		||||
        
 | 
			
		||||
        interior->mesh.require_shared_vertices();
 | 
			
		||||
        indexed_triangle_set its = std::move(interior->mesh.its);
 | 
			
		||||
 | 
			
		||||
        Slic3r::simplify_mesh(its);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // flip normals back...
 | 
			
		||||
        for (stl_triangle_vertex_indices &ind : its.indices)
 | 
			
		||||
            std::swap(ind(0), ind(2));
 | 
			
		||||
        
 | 
			
		||||
        *meshptr = Slic3r::TriangleMesh{its};
 | 
			
		||||
 | 
			
		||||
        interior->mesh = Slic3r::TriangleMesh{its};
 | 
			
		||||
        interior->mesh.repaired = true;
 | 
			
		||||
        interior->mesh.require_shared_vertices();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return meshptr;
 | 
			
		||||
 | 
			
		||||
    return interior;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Contour3D DrainHole::to_mesh() const
 | 
			
		||||
| 
						 | 
				
			
			@ -269,12 +305,22 @@ void cut_drainholes(std::vector<ExPolygons> & obj_slices,
 | 
			
		|||
        obj_slices[i] = diff_ex(obj_slices[i], hole_slices[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const HollowingConfig &cfg)
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const HollowingConfig &cfg, int flags)
 | 
			
		||||
{
 | 
			
		||||
    std::unique_ptr<Slic3r::TriangleMesh> inter_ptr =
 | 
			
		||||
            Slic3r::sla::generate_interior(mesh);
 | 
			
		||||
    InteriorPtr interior = generate_interior(mesh, cfg, JobController{});
 | 
			
		||||
    if (!interior) return;
 | 
			
		||||
 | 
			
		||||
    if (inter_ptr) mesh.merge(*inter_ptr);
 | 
			
		||||
    hollow_mesh(mesh, *interior, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const Interior &interior, int flags)
 | 
			
		||||
{
 | 
			
		||||
    if (mesh.empty() || interior.mesh.empty()) return;
 | 
			
		||||
 | 
			
		||||
//    if (flags & hfRemoveInsideTriangles && interior.gridptr)
 | 
			
		||||
//        erase_inside_triangles_2(mesh, interior);
 | 
			
		||||
 | 
			
		||||
    mesh.merge(interior.mesh);
 | 
			
		||||
    mesh.require_shared_vertices();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,17 @@ struct HollowingConfig
 | 
			
		|||
    bool enabled = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum HollowingFlags { hfRemoveInsideTriangles = 0x1 };
 | 
			
		||||
 | 
			
		||||
// All data related to a generated mesh interior. Includes the 3D grid and mesh
 | 
			
		||||
// and various metadata. No need to manipulate from outside.
 | 
			
		||||
struct Interior;
 | 
			
		||||
struct InteriorDeleter { void operator()(Interior *p); };
 | 
			
		||||
using  InteriorPtr = std::unique_ptr<Interior, InteriorDeleter>;
 | 
			
		||||
 | 
			
		||||
TriangleMesh &      get_mesh(Interior &interior);
 | 
			
		||||
const TriangleMesh &get_mesh(const Interior &interior);
 | 
			
		||||
 | 
			
		||||
struct DrainHole
 | 
			
		||||
{
 | 
			
		||||
    Vec3f pos;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,11 +71,15 @@ using DrainHoles = std::vector<DrainHole>;
 | 
			
		|||
 | 
			
		||||
constexpr float HoleStickOutLength = 1.f;
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &mesh,
 | 
			
		||||
                                                const HollowingConfig &  = {},
 | 
			
		||||
                                                const JobController &ctl = {});
 | 
			
		||||
InteriorPtr generate_interior(const TriangleMesh &mesh,
 | 
			
		||||
                              const HollowingConfig &  = {},
 | 
			
		||||
                              const JobController &ctl = {});
 | 
			
		||||
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const HollowingConfig &cfg);
 | 
			
		||||
// Will do the hollowing
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const HollowingConfig &cfg, int flags = 0);
 | 
			
		||||
 | 
			
		||||
// Hollowing prepared in "interior", merge with original mesh
 | 
			
		||||
void hollow_mesh(TriangleMesh &mesh, const Interior &interior, int flags = 0);
 | 
			
		||||
 | 
			
		||||
void cut_drainholes(std::vector<ExPolygons> & obj_slices,
 | 
			
		||||
                    const std::vector<float> &slicegrid,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1149,8 +1149,9 @@ const TriangleMesh& SLAPrintObject::pad_mesh() const
 | 
			
		|||
 | 
			
		||||
const TriangleMesh &SLAPrintObject::hollowed_interior_mesh() const
 | 
			
		||||
{
 | 
			
		||||
    if (m_hollowing_data && m_config.hollowing_enable.getBool())
 | 
			
		||||
        return m_hollowing_data->interior;
 | 
			
		||||
    if (m_hollowing_data && m_hollowing_data->interior &&
 | 
			
		||||
        m_config.hollowing_enable.getBool())
 | 
			
		||||
        return sla::get_mesh(*m_hollowing_data->interior);
 | 
			
		||||
    
 | 
			
		||||
    return EMPTY_MESH;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -327,8 +327,8 @@ private:
 | 
			
		|||
    class HollowingData
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        
 | 
			
		||||
        TriangleMesh interior;
 | 
			
		||||
 | 
			
		||||
        sla::InteriorPtr interior;
 | 
			
		||||
        mutable TriangleMesh hollow_mesh_with_holes; // caching the complete hollowed mesh
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -131,13 +131,14 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
 | 
			
		|||
    double quality  = po.m_config.hollowing_quality.getFloat();
 | 
			
		||||
    double closing_d = po.m_config.hollowing_closing_distance.getFloat();
 | 
			
		||||
    sla::HollowingConfig hlwcfg{thickness, quality, closing_d};
 | 
			
		||||
    auto meshptr = generate_interior(po.transformed_mesh(), hlwcfg);
 | 
			
		||||
 | 
			
		||||
    if (meshptr->empty())
 | 
			
		||||
    sla::InteriorPtr interior = generate_interior(po.transformed_mesh(), hlwcfg);
 | 
			
		||||
 | 
			
		||||
    if (!interior || sla::get_mesh(*interior).empty())
 | 
			
		||||
        BOOST_LOG_TRIVIAL(warning) << "Hollowed interior is empty!";
 | 
			
		||||
    else {
 | 
			
		||||
        po.m_hollowing_data.reset(new SLAPrintObject::HollowingData());
 | 
			
		||||
        po.m_hollowing_data->interior = *meshptr;
 | 
			
		||||
        po.m_hollowing_data->interior = std::move(interior);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +146,9 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
 | 
			
		|||
void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
 | 
			
		||||
{
 | 
			
		||||
    bool needs_drilling = ! po.m_model_object->sla_drain_holes.empty();
 | 
			
		||||
    bool is_hollowed = (po.m_hollowing_data && ! po.m_hollowing_data->interior.empty());
 | 
			
		||||
    bool is_hollowed =
 | 
			
		||||
        (po.m_hollowing_data && po.m_hollowing_data->interior &&
 | 
			
		||||
         !sla::get_mesh(*po.m_hollowing_data->interior).empty());
 | 
			
		||||
 | 
			
		||||
    if (! is_hollowed && ! needs_drilling) {
 | 
			
		||||
        // In this case we can dump any data that might have been
 | 
			
		||||
| 
						 | 
				
			
			@ -163,10 +166,7 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
 | 
			
		|||
    // holes that are no longer on the frontend.
 | 
			
		||||
    TriangleMesh &hollowed_mesh = po.m_hollowing_data->hollow_mesh_with_holes;
 | 
			
		||||
    hollowed_mesh = po.transformed_mesh();
 | 
			
		||||
    if (! po.m_hollowing_data->interior.empty()) {
 | 
			
		||||
        hollowed_mesh.merge(po.m_hollowing_data->interior);
 | 
			
		||||
        hollowed_mesh.require_shared_vertices();
 | 
			
		||||
    }
 | 
			
		||||
    sla::hollow_mesh(hollowed_mesh, *po.m_hollowing_data->interior/*, sla::hfRemoveInsideTriangles*/);
 | 
			
		||||
 | 
			
		||||
    if (! needs_drilling) {
 | 
			
		||||
        BOOST_LOG_TRIVIAL(info) << "Drilling skipped (no holes).";
 | 
			
		||||
| 
						 | 
				
			
			@ -260,9 +260,15 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
 | 
			
		|||
    auto &slice_grid = po.m_model_height_levels;
 | 
			
		||||
    slicer.slice(slice_grid, SlicingMode::Regular, closing_r, &po.m_model_slices, thr);
 | 
			
		||||
    
 | 
			
		||||
    if (po.m_hollowing_data && ! po.m_hollowing_data->interior.empty()) {
 | 
			
		||||
        po.m_hollowing_data->interior.repair(true);
 | 
			
		||||
        TriangleMeshSlicer interior_slicer(&po.m_hollowing_data->interior);
 | 
			
		||||
    sla::Interior *interior = po.m_hollowing_data ?
 | 
			
		||||
                                  po.m_hollowing_data->interior.get() :
 | 
			
		||||
                                  nullptr;
 | 
			
		||||
 | 
			
		||||
    if (interior && ! sla::get_mesh(*interior).empty()) {
 | 
			
		||||
        TriangleMesh interiormesh = sla::get_mesh(*interior);
 | 
			
		||||
        interiormesh.repaired = false;
 | 
			
		||||
        interiormesh.repair(true);
 | 
			
		||||
        TriangleMeshSlicer interior_slicer(&interiormesh);
 | 
			
		||||
        std::vector<ExPolygons> interior_slices;
 | 
			
		||||
        interior_slicer.slice(slice_grid, SlicingMode::Regular, closing_r, &interior_slices, thr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue