mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge branch 'lm_drilling_backend_rebased'
This commit is contained in:
		
						commit
						6a2604cfe0
					
				
					 14 changed files with 342 additions and 300 deletions
				
			
		|  | @ -150,8 +150,17 @@ void minus(TriangleMesh &A, const TriangleMesh &B) | |||
|     triangle_mesh_to_cgal(B, meshB.m); | ||||
|      | ||||
|     CGALMesh meshResult; | ||||
|     CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m); | ||||
|      | ||||
|     bool success = false; | ||||
|     try { | ||||
|         success = CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m, | ||||
|             CGALParams::throw_on_self_intersection(true), CGALParams::throw_on_self_intersection(true)); | ||||
|     } | ||||
|     catch (const CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception&) { | ||||
|         success = false; | ||||
|     } | ||||
|     if (! success) | ||||
|         throw std::runtime_error("CGAL corefine_and_compute_difference failed"); | ||||
| 
 | ||||
|     A = cgal_to_triangle_mesh(meshResult.m); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -122,10 +122,10 @@ void SLAPrint::clear() | |||
| } | ||||
| 
 | ||||
| // Transformation without rotation around Z and without a shift by X and Y.
 | ||||
| static Transform3d sla_trafo(const SLAPrint& p, const ModelObject &model_object) | ||||
| Transform3d SLAPrint::sla_trafo(const ModelObject &model_object) const | ||||
| { | ||||
| 
 | ||||
|     Vec3d corr = p.relative_correction(); | ||||
|     Vec3d corr = this->relative_correction(); | ||||
| 
 | ||||
|     ModelInstance &model_instance = *model_object.instances.front(); | ||||
|     Vec3d          offset         = model_instance.get_offset(); | ||||
|  | @ -376,7 +376,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con | |||
|             bool sla_trafo_differs  = | ||||
|                 model_object.instances.empty() != model_object_new.instances.empty() || | ||||
|                 (! model_object.instances.empty() && | ||||
|                   (! sla_trafo(*this, model_object).isApprox(sla_trafo(*this, model_object_new)) || | ||||
|                   (! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)) || | ||||
|                     model_object.instances.front()->is_left_handed() != model_object_new.instances.front()->is_left_handed())); | ||||
|             if (model_parts_differ || sla_trafo_differs) { | ||||
|                 // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
 | ||||
|  | @ -419,7 +419,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con | |||
|                 if (model_object.sla_drain_holes != model_object_new.sla_drain_holes) | ||||
|                 { | ||||
|                     model_object.sla_drain_holes = model_object_new.sla_drain_holes; | ||||
|                     update_apply_status(it_print_object_status->print_object->invalidate_step(slaposHollowing)); | ||||
|                     update_apply_status(it_print_object_status->print_object->invalidate_step(slaposDrillHoles)); | ||||
|                 } | ||||
| 
 | ||||
|                 // Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
 | ||||
|  | @ -453,7 +453,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con | |||
| 
 | ||||
|             // FIXME: this invalidates the transformed mesh in SLAPrintObject
 | ||||
|             // which is expensive to calculate (especially the raw_mesh() call)
 | ||||
|             print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed()); | ||||
|             print_object->set_trafo(sla_trafo(model_object), model_object.instances.front()->is_left_handed()); | ||||
| 
 | ||||
|             print_object->set_instances(std::move(new_instances)); | ||||
| 
 | ||||
|  | @ -1101,6 +1101,8 @@ const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const | |||
| bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const | ||||
| { | ||||
|     switch (step) { | ||||
|     case slaposDrillHoles: | ||||
|         return m_hollowing_data && !m_hollowing_data->hollow_mesh_with_holes.empty(); | ||||
|     case slaposSupportTree: | ||||
|         return ! this->support_mesh().empty(); | ||||
|     case slaposPad: | ||||
|  | @ -1117,7 +1119,7 @@ TriangleMesh SLAPrintObject::get_mesh(SLAPrintObjectStep step) const | |||
|         return this->support_mesh(); | ||||
|     case slaposPad: | ||||
|         return this->pad_mesh(); | ||||
|     case slaposHollowing: | ||||
|     case slaposDrillHoles: | ||||
|         if (m_hollowing_data) | ||||
|             return m_hollowing_data->hollow_mesh_with_holes; | ||||
|         [[fallthrough]]; | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ public: | |||
|     // Support mesh is only valid if this->is_step_done(slaposPad) is true.
 | ||||
|     const TriangleMesh&     pad_mesh() const; | ||||
|      | ||||
|     // Ready after this->is_step_done(slaposHollowing) is true
 | ||||
|     // Ready after this->is_step_done(slaposDrillHoles) is true
 | ||||
|     const TriangleMesh&     hollowed_interior_mesh() const; | ||||
|      | ||||
|     // Get the mesh that is going to be printed with all the modifications
 | ||||
|  | @ -421,6 +421,9 @@ public: | |||
|     // Extracted value from the configuration objects
 | ||||
|     Vec3d                       relative_correction() const; | ||||
| 
 | ||||
|     // Return sla tansformation for a given model_object
 | ||||
|     Transform3d sla_trafo(const ModelObject &model_object) const; | ||||
| 
 | ||||
| 	std::string                 output_filename(const std::string &filename_base = std::string()) const override; | ||||
| 
 | ||||
|     const SLAPrintStatistics&   print_statistics() const { return m_print_statistics; } | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ namespace { | |||
| 
 | ||||
| const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS = { | ||||
|     10, // slaposHollowing,
 | ||||
|     10, // slaposDrillHolesIfHollowed
 | ||||
|     10, // slaposDrillHoles
 | ||||
|     10, // slaposObjectSlice,
 | ||||
|     20, // slaposSupportPoints,
 | ||||
|     10, // slaposSupportTree,
 | ||||
|  | @ -39,7 +39,7 @@ std::string OBJ_STEP_LABELS(size_t idx) | |||
| { | ||||
|     switch (idx) { | ||||
|     case slaposHollowing:            return L("Hollowing model"); | ||||
|     case slaposDrillHoles:           return L("Drilling holes into hollowed model."); | ||||
|     case slaposDrillHoles:           return L("Drilling holes into model."); | ||||
|     case slaposObjectSlice:          return L("Slicing model"); | ||||
|     case slaposSupportPoints:        return L("Generating support points"); | ||||
|     case slaposSupportTree:          return L("Generating support tree"); | ||||
|  | @ -80,6 +80,7 @@ SLAPrint::Steps::Steps(SLAPrint *print) | |||
| void SLAPrint::Steps::hollow_model(SLAPrintObject &po) | ||||
| { | ||||
|     po.m_hollowing_data.reset(); | ||||
| 
 | ||||
|     if (! po.m_config.hollowing_enable.getBool()) { | ||||
|         BOOST_LOG_TRIVIAL(info) << "Skipping hollowing step!"; | ||||
|         return; | ||||
|  |  | |||
|  | @ -313,33 +313,38 @@ public: | |||
|     // Valid geometry_id should always be positive.
 | ||||
|     std::pair<size_t, size_t> geometry_id; | ||||
|     // An ID containing the extruder ID (used to select color).
 | ||||
|     int                 extruder_id; | ||||
|     // Is this object selected?
 | ||||
|     bool                selected; | ||||
|     // Is this object disabled from selection?
 | ||||
|     bool                disabled; | ||||
|     // Is this object printable?
 | ||||
|     bool                printable; | ||||
|     // Whether or not this volume is active for rendering
 | ||||
|     bool                is_active; | ||||
|     // Whether or not to use this volume when applying zoom_to_volumes()
 | ||||
|     bool                zoom_to_volumes; | ||||
|     // Wheter or not this volume is enabled for outside print volume detection in shader.
 | ||||
|     bool                shader_outside_printer_detection_enabled; | ||||
|     // Wheter or not this volume is outside print volume.
 | ||||
|     bool                is_outside; | ||||
|     int                 	extruder_id; | ||||
| 
 | ||||
|     // Various boolean flags.
 | ||||
|     struct { | ||||
| 	    // Is this object selected?
 | ||||
| 	    bool                selected : 1; | ||||
| 	    // Is this object disabled from selection?
 | ||||
| 	    bool                disabled : 1; | ||||
| 	    // Is this object printable?
 | ||||
| 	    bool                printable : 1; | ||||
| 	    // Whether or not this volume is active for rendering
 | ||||
| 	    bool                is_active : 1; | ||||
| 	    // Whether or not to use this volume when applying zoom_to_volumes()
 | ||||
| 	    bool                zoom_to_volumes : 1; | ||||
| 	    // Wheter or not this volume is enabled for outside print volume detection in shader.
 | ||||
| 	    bool                shader_outside_printer_detection_enabled : 1; | ||||
| 	    // Wheter or not this volume is outside print volume.
 | ||||
| 	    bool                is_outside : 1; | ||||
| 	    // Wheter or not this volume has been generated from a modifier
 | ||||
| 	    bool                is_modifier : 1; | ||||
| 	    // Wheter or not this volume has been generated from the wipe tower
 | ||||
| 	    bool                is_wipe_tower : 1; | ||||
| 	    // Wheter or not this volume has been generated from an extrusion path
 | ||||
| 	    bool                is_extrusion_path : 1; | ||||
| 	    // Wheter or not to always render this volume using its own alpha 
 | ||||
| 	    bool                force_transparent : 1; | ||||
| 	    // Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE)
 | ||||
| 	    bool                force_native_color : 1; | ||||
| 	}; | ||||
| 
 | ||||
|     // Is mouse or rectangle selection over this object to select/deselect it ?
 | ||||
|     EHoverState         hover; | ||||
|     // Wheter or not this volume has been generated from a modifier
 | ||||
|     bool                is_modifier; | ||||
|     // Wheter or not this volume has been generated from the wipe tower
 | ||||
|     bool                is_wipe_tower; | ||||
|     // Wheter or not this volume has been generated from an extrusion path
 | ||||
|     bool                is_extrusion_path; | ||||
|     // Wheter or not to always render this volume using its own alpha 
 | ||||
|     bool                force_transparent; | ||||
|     // Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE)
 | ||||
|     bool                force_native_color; | ||||
|     EHoverState         	hover; | ||||
| 
 | ||||
|     // Interleaved triangles & normals with indexed triangles & quads.
 | ||||
|     GLIndexedVertexArray        indexed_vertex_array; | ||||
|  |  | |||
|  | @ -1977,8 +1977,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|     }; | ||||
| 
 | ||||
|     // SLA steps to pull the preview meshes for.
 | ||||
| 	typedef std::array<SLAPrintObjectStep, 2> SLASteps; | ||||
| 	SLASteps sla_steps = { slaposSupportTree, slaposPad }; | ||||
| 	typedef std::array<SLAPrintObjectStep, 3> SLASteps; | ||||
|     SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad }; | ||||
|     struct SLASupportState { | ||||
|         std::array<PrintStateBase::StateWithTimeStamp, std::tuple_size<SLASteps>::value> step; | ||||
|     }; | ||||
|  | @ -2025,7 +2025,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|                         // Consider the DONE step without a valid mesh as invalid for the purpose
 | ||||
|                         // of mesh visualization.
 | ||||
|                         state.step[istep].state = PrintStateBase::INVALID; | ||||
|                     else | ||||
|                     else if (sla_steps[istep] != slaposDrillHoles) | ||||
|                         for (const ModelInstance* model_instance : print_object->model_object()->instances) | ||||
|                             // Only the instances, which are currently printable, will have the SLA support structures kept.
 | ||||
|                             // The instances outside the print bed will have the GLVolumes of their support structures released.
 | ||||
|  | @ -2038,7 +2038,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|     } | ||||
|     std::sort(model_volume_state.begin(), model_volume_state.end(), model_volume_state_lower); | ||||
|     std::sort(aux_volume_state.begin(), aux_volume_state.end(), model_volume_state_lower); | ||||
|     // Release all ModelVolume based GLVolumes not found in the current Model.
 | ||||
|     // Release all ModelVolume based GLVolumes not found in the current Model. Find the GLVolume of a hollowed mesh.
 | ||||
|     for (size_t volume_id = 0; volume_id < m_volumes.volumes.size(); ++volume_id) { | ||||
|         GLVolume* volume = m_volumes.volumes[volume_id]; | ||||
|         ModelVolumeState  key(volume); | ||||
|  | @ -2120,6 +2120,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|                     if (it_old_volume != deleted_volumes.end() && it_old_volume->composite_id == it->composite_id) | ||||
|                         // If a volume changed its ObjectID, but it reuses a GLVolume's CompositeID, maintain its selection.
 | ||||
|                         map_glvolume_old_to_new[it_old_volume->volume_idx] = m_volumes.volumes.size(); | ||||
|                     // Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
 | ||||
|                     // later in this function.
 | ||||
|                     it->volume_idx = m_volumes.volumes.size(); | ||||
|                     m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized); | ||||
|                     m_volumes.volumes.back()->geometry_id = key.geometry_id; | ||||
|                     update_object_list = true; | ||||
|  | @ -2148,8 +2151,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|             const ModelObject *model_object = print_object->model_object(); | ||||
|             // Find an index of the ModelObject
 | ||||
|             int object_idx; | ||||
| 			if (std::all_of(state.step.begin(), state.step.end(), [](const PrintStateBase::StateWithTimeStamp &state){ return state.state != PrintStateBase::DONE; })) | ||||
| 				continue; | ||||
|             // There may be new SLA volumes added to the scene for this print_object.
 | ||||
|             // Find the object index of this print_object in the Model::objects list.
 | ||||
|             auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object); | ||||
|  | @ -2168,29 +2169,53 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|                 assert(it != model_object->instances.end()); | ||||
|                 int instance_idx = it - model_object->instances.begin(); | ||||
|                 for (size_t istep = 0; istep < sla_steps.size(); ++ istep) | ||||
|                     if (state.step[istep].state == PrintStateBase::DONE) { | ||||
|                         ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); | ||||
|                         auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); | ||||
|                         assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); | ||||
|                         if (it->new_geometry()) { | ||||
|                     if (sla_steps[istep] == slaposDrillHoles) { | ||||
|                     	// Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance,
 | ||||
|                     	// not into its own GLVolume.
 | ||||
|                         // There shall always be such a GLVolume allocated.
 | ||||
|                         ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id); | ||||
|                         auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower); | ||||
|                         assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id); | ||||
|                         assert(!it->new_geometry()); | ||||
|                         GLVolume &volume = *m_volumes.volumes[it->volume_idx]; | ||||
|                         if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) { | ||||
|                         	// The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
 | ||||
|                             volume.indexed_vertex_array.release_geometry(); | ||||
|                         	if (state.step[istep].state == PrintStateBase::DONE) { | ||||
|                                 TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles); | ||||
| 	                            assert(! mesh.empty()); | ||||
|                                 mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse()); | ||||
|                                 volume.indexed_vertex_array.load_mesh(mesh); | ||||
| 	                        } else { | ||||
| 	                        	// Reload the original volume.
 | ||||
|                                 volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh()); | ||||
| 	                        } | ||||
|                             volume.finalize_geometry(true); | ||||
| 	                    } | ||||
|                     	//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
 | ||||
|                     	// to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
 | ||||
|                     	// of various concenrs (model vs. 3D print path).
 | ||||
|                     	volume.offsets = { state.step[istep].timestamp }; | ||||
|                     } else if (state.step[istep].state == PrintStateBase::DONE) { | ||||
|                         // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
 | ||||
| 						ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); | ||||
| 						auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); | ||||
| 						assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); | ||||
|                     	if (it->new_geometry()) { | ||||
|                             // This can be an SLA support structure that should not be rendered (in case someone used undo
 | ||||
|                             // to revert to before it was generated). If that's the case, we should not generate anything.
 | ||||
|                             if (model_object->sla_points_status != sla::PointsStatus::NoPoints) | ||||
|                                 instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx)); | ||||
|                             else | ||||
|                                 shift_zs[object_idx] = 0.; | ||||
|                         } else { | ||||
|                             // Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
 | ||||
|                             m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); | ||||
|                             m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); | ||||
|                         } | ||||
| 						else { | ||||
| 							// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
 | ||||
| 							m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); | ||||
| 							m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); | ||||
| 						} | ||||
|                     } | ||||
|             } | ||||
| 
 | ||||
| //            // stores the current volumes count
 | ||||
| //            size_t volumes_count = m_volumes.volumes.size();
 | ||||
| 
 | ||||
|             for (size_t istep = 0; istep < sla_steps.size(); ++istep) | ||||
|                 if (!instances[istep].empty()) | ||||
|                     m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized); | ||||
|  | @ -6081,8 +6106,6 @@ void GLCanvas3D::_load_sla_shells() | |||
|             unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size(); | ||||
|             for (const SLAPrintObject::Instance& instance : obj->instances()) { | ||||
|                 add_volume(*obj, 0, instance, obj->get_mesh_to_print(), GLVolume::MODEL_COLOR[0], true); | ||||
| //                if (! obj->hollowed_interior_mesh().empty())
 | ||||
| //                    add_volume(*obj, -int(slaposHollowing), instance, obj->hollowed_interior_mesh(), GLVolume::MODEL_COLOR[0], false);
 | ||||
|                 // Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
 | ||||
|                 // through the update_volumes_colors_by_extruder() call.
 | ||||
|                 m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id(); | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ | |||
| #include <GL/glew.h> | ||||
| 
 | ||||
| #include "slic3r/GUI/GUI_App.hpp" | ||||
| #include "slic3r/GUI/GLCanvas3D.hpp" | ||||
| #include "libslic3r/SLAPrint.hpp" | ||||
| #include "slic3r/GUI/MeshUtils.hpp" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -302,5 +305,87 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr | |||
| 	return b; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* model_object) | ||||
| { | ||||
|     recent_update = false; | ||||
| 
 | ||||
|     if (m_model_object != model_object | ||||
|     || (model_object && m_model_object_id != model_object->id())) { | ||||
|         m_model_object = model_object; | ||||
|         m_print_object_idx = -1; | ||||
|         m_mesh_raycaster.reset(); | ||||
|         m_object_clipper.reset(); | ||||
|         m_supports_clipper.reset(); | ||||
|         m_old_mesh = nullptr; | ||||
|         m_mesh = nullptr; | ||||
|         m_backend_mesh_transformed.clear(); | ||||
|         if (m_model_object) { | ||||
|             m_active_instance = canvas.get_selection().get_instance_idx(); | ||||
|             m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius(); | ||||
|         } | ||||
| 
 | ||||
|         recent_update = true; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     if (! m_model_object || ! canvas.get_selection().is_from_single_instance()) | ||||
|         return false; | ||||
| 
 | ||||
|     int old_po_idx = m_print_object_idx; | ||||
| 
 | ||||
|     // First we need a pointer to the respective SLAPrintObject. The index into objects vector is
 | ||||
|     // cached so we don't have todo it on each render. We only search for the po if needed:
 | ||||
|     if (m_print_object_idx < 0 || (int)canvas.sla_print()->objects().size() != m_print_objects_count) { | ||||
|         m_print_objects_count = canvas.sla_print()->objects().size(); | ||||
|         m_print_object_idx = -1; | ||||
|         for (const SLAPrintObject* po : canvas.sla_print()->objects()) { | ||||
|             ++m_print_object_idx; | ||||
|             if (po->model_object()->id() == m_model_object->id()) | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     m_mesh = nullptr; | ||||
|     // Load either the model_object mesh, or one provided by the backend
 | ||||
|     // This mesh does not account for the possible Z up SLA offset.
 | ||||
|     // The backend mesh needs to be transformed and because a pointer to it is
 | ||||
|     // saved, a copy is stored as a member (FIXME)
 | ||||
|     if (m_print_object_idx >=0) { | ||||
|         const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx]; | ||||
|         if (po->is_step_done(slaposDrillHoles)) { | ||||
|             m_backend_mesh_transformed = po->get_mesh_to_print(); | ||||
|             m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse()); | ||||
|             m_mesh = &m_backend_mesh_transformed; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (! m_mesh) { | ||||
|         m_mesh = &m_model_object->volumes.front()->mesh(); | ||||
|         m_backend_mesh_transformed.clear(); | ||||
|     } | ||||
| 
 | ||||
|     m_model_object_id = m_model_object->id(); | ||||
| 
 | ||||
|     if (m_mesh != m_old_mesh) { | ||||
|         wxBusyCursor wait; | ||||
|         m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh)); | ||||
|         m_object_clipper.reset(); | ||||
|         m_supports_clipper.reset(); | ||||
|         m_old_mesh = m_mesh; | ||||
|         m_clipping_plane_distance = 0.f; | ||||
|         m_clipping_plane_distance_stash = 0.f; | ||||
|         recent_update = true; | ||||
|         return true; | ||||
|     } | ||||
|     if (! recent_update) | ||||
|         recent_update = m_print_object_idx < 0 && old_po_idx >= 0; | ||||
| 
 | ||||
|     return m_print_object_idx < 0 ? old_po_idx >=0 : false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -31,6 +31,8 @@ static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; | |||
| 
 | ||||
| class ImGuiWrapper; | ||||
| class CommonGizmosData; | ||||
| class GLCanvas3D; | ||||
| class ClippingPlane; | ||||
| 
 | ||||
| class GLGizmoBase | ||||
| { | ||||
|  | @ -189,9 +191,13 @@ class MeshClipper; | |||
| class CommonGizmosData { | ||||
| public: | ||||
|     const TriangleMesh* mesh() const { | ||||
|         return (! m_mesh ? nullptr : (m_cavity_mesh ? m_cavity_mesh.get() : m_mesh)); | ||||
|         return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh));
 | ||||
|     } | ||||
| 
 | ||||
|     bool update_from_backend(GLCanvas3D& canvas, ModelObject* model_object); | ||||
| 
 | ||||
|     bool recent_update = false; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     ModelObject* m_model_object = nullptr; | ||||
|  | @ -200,8 +206,8 @@ public: | |||
|     std::unique_ptr<MeshClipper> m_object_clipper; | ||||
|     std::unique_ptr<MeshClipper> m_supports_clipper; | ||||
| 
 | ||||
|     std::unique_ptr<TriangleMesh> m_cavity_mesh; | ||||
|     std::unique_ptr<GLVolume> m_volume_with_cavity; | ||||
|     //std::unique_ptr<TriangleMesh> m_cavity_mesh;
 | ||||
|     //std::unique_ptr<GLVolume> m_volume_with_cavity;
 | ||||
| 
 | ||||
|     int m_active_instance = -1; | ||||
|     float m_active_instance_bb_radius = 0; | ||||
|  | @ -209,6 +215,22 @@ public: | |||
|     int m_print_object_idx = -1; | ||||
|     int m_print_objects_count = -1; | ||||
|     int m_old_timestamp = -1; | ||||
| 
 | ||||
|     float m_clipping_plane_distance = 0.f; | ||||
|     std::unique_ptr<ClippingPlane> m_clipping_plane; | ||||
| 
 | ||||
|     void stash_clipping_plane() { | ||||
|         m_clipping_plane_distance_stash = m_clipping_plane_distance; | ||||
|     } | ||||
| 
 | ||||
|     void unstash_clipping_plane() { | ||||
|         m_clipping_plane_distance = m_clipping_plane_distance_stash; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const TriangleMesh* m_old_mesh; | ||||
|     TriangleMesh m_backend_mesh_transformed; | ||||
|     float m_clipping_plane_distance_stash = 0.f; | ||||
| }; | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filenam | |||
|     : GLGizmoBase(parent, icon_filename, sprite_id, cd) | ||||
|     , m_quadric(nullptr) | ||||
| { | ||||
|     m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); | ||||
|     m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); | ||||
|     m_quadric = ::gluNewQuadric(); | ||||
|     if (m_quadric != nullptr) | ||||
|         // using GLU_FILL does not work when the instance's transformation
 | ||||
|  | @ -40,7 +40,7 @@ bool GLGizmoHollow::on_init() | |||
| { | ||||
|     m_shortcut_key = WXK_CONTROL_H; | ||||
|     m_desc["enable"]           = _(L("Hollow this object")); | ||||
|     m_desc["preview"]          = _(L("Preview")); | ||||
|     m_desc["preview"]          = _(L("Preview hollowed and drilled model")); | ||||
|     m_desc["offset"]           = _(L("Offset")) + ": "; | ||||
|     m_desc["quality"]          = _(L("Quality")) + ": "; | ||||
|     m_desc["closing_distance"] = _(L("Closing distance")) + ": "; | ||||
|  | @ -55,38 +55,16 @@ bool GLGizmoHollow::on_init() | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void GLGizmoHollow::set_sla_support_data(ModelObject* model_object, const Selection& selection) | ||||
| void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&) | ||||
| { | ||||
|     if (! model_object || selection.is_empty()) { | ||||
|         m_c->m_model_object = nullptr; | ||||
|         return; | ||||
|     } | ||||
|     if (m_c->recent_update) { | ||||
| 
 | ||||
|     bool something_changed = false; | ||||
| 
 | ||||
|     if (m_c->m_model_object != model_object | ||||
|      || m_c->m_model_object_id != model_object->id() | ||||
|      || m_c->m_active_instance != selection.get_instance_idx()) { | ||||
|         m_c->m_model_object = model_object; | ||||
|         m_c->m_print_object_idx = -1; | ||||
|         m_c->m_active_instance = selection.get_instance_idx(); | ||||
|         something_changed = true; | ||||
|     } | ||||
| 
 | ||||
|     if (model_object && something_changed && selection.is_from_single_instance()) | ||||
|     { | ||||
|         // Cache the bb - it's needed for dealing with the clipping plane quite often
 | ||||
|         // It could be done inside update_mesh but one has to account for scaling of the instance.
 | ||||
|         m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); | ||||
| 
 | ||||
|         if (is_mesh_update_necessary()) { | ||||
|             update_mesh(); | ||||
|         if (m_c->m_model_object) | ||||
|             reload_cache(); | ||||
|         } | ||||
| 
 | ||||
|         if (m_state == On) { | ||||
|             m_parent.toggle_model_objects_visibility(false); | ||||
|             m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); | ||||
|             m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); | ||||
|             m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); | ||||
|         } | ||||
|         else | ||||
|  | @ -109,8 +87,8 @@ void GLGizmoHollow::on_render() const | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (! m_c->m_mesh) | ||||
|         const_cast<GLGizmoHollow*>(this)->update_mesh(); | ||||
|     // !!! is it necessary?
 | ||||
|     //const_cast<GLGizmoHollow*>(this)->m_c->update_from_backend(m_parent, m_c->m_model_object);
 | ||||
| 
 | ||||
|     glsafe(::glEnable(GL_BLEND)); | ||||
|     glsafe(::glEnable(GL_DEPTH_TEST)); | ||||
|  | @ -132,7 +110,7 @@ void GLGizmoHollow::on_render() const | |||
| 
 | ||||
| void GLGizmoHollow::render_hollowed_mesh() const | ||||
| { | ||||
|     if (m_c->m_volume_with_cavity) { | ||||
|     /*if (m_c->m_volume_with_cavity) {
 | ||||
|         m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift); | ||||
|         m_parent.get_shader().start_using(); | ||||
| 
 | ||||
|  | @ -148,14 +126,13 @@ void GLGizmoHollow::render_hollowed_mesh() const | |||
|         m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation()); | ||||
|         m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id); | ||||
|         m_parent.get_shader().stop_using(); | ||||
|     } | ||||
|     }*/ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void GLGizmoHollow::render_clipping_plane(const Selection& selection) const | ||||
| { | ||||
|     if (m_clipping_plane_distance == 0.f || m_c->mesh()->empty()) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) | ||||
|         return; | ||||
| 
 | ||||
|     // Get transformation of the instance
 | ||||
|  | @ -177,22 +154,14 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const | |||
|         m_c->m_object_clipper.reset(new MeshClipper); | ||||
|         m_c->m_object_clipper->set_mesh(*m_c->mesh()); | ||||
|     } | ||||
|     m_c->m_object_clipper->set_plane(*m_clipping_plane); | ||||
|     m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane); | ||||
|     m_c->m_object_clipper->set_transformation(trafo); | ||||
| 
 | ||||
| 
 | ||||
|     // Next, ask the backend if supports are already calculated. If so, we are gonna cut them too.
 | ||||
|     // First we need a pointer to the respective SLAPrintObject. The index into objects vector is
 | ||||
|     // cached so we don't have todo it on each render. We only search for the po if needed:
 | ||||
|     if (m_c->m_print_object_idx < 0 || (int)m_parent.sla_print()->objects().size() != m_c->m_print_objects_count) { | ||||
|         m_c->m_print_objects_count = m_parent.sla_print()->objects().size(); | ||||
|         m_c->m_print_object_idx = -1; | ||||
|         for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { | ||||
|             ++m_c->m_print_object_idx; | ||||
|             if (po->model_object()->id() == m_c->m_model_object->id()) | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|     //if (m_c->m_print_object_idx < 0)
 | ||||
|     //    m_c->update_from_backend(m_parent, m_c->m_model_object);
 | ||||
| 
 | ||||
|     if (m_c->m_print_object_idx >= 0) { | ||||
|         const SLAPrintObject* print_object = m_parent.sla_print()->objects()[m_c->m_print_object_idx]; | ||||
| 
 | ||||
|  | @ -208,7 +177,7 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const | |||
|                 m_c->m_supports_clipper->set_mesh(print_object->support_mesh()); | ||||
|                 m_c->m_old_timestamp = timestamp; | ||||
|             } | ||||
|             m_c->m_supports_clipper->set_plane(*m_clipping_plane); | ||||
|             m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane); | ||||
|             m_c->m_supports_clipper->set_transformation(supports_trafo); | ||||
|         } | ||||
|         else | ||||
|  | @ -345,46 +314,12 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons | |||
| 
 | ||||
| bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const | ||||
| { | ||||
|     if (m_clipping_plane_distance == 0.f) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) | ||||
|         return false; | ||||
| 
 | ||||
|     Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point; | ||||
|     transformed_point(2) += m_z_shift; | ||||
|     return m_clipping_plane->is_point_clipped(transformed_point); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| bool GLGizmoHollow::is_mesh_update_necessary() const | ||||
| { | ||||
|     return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty()) | ||||
|         && ((m_c->m_model_object->id() != m_c->m_model_object_id) || ! m_c->m_mesh); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void GLGizmoHollow::update_mesh() | ||||
| { | ||||
|     if (! m_c->m_model_object) | ||||
|         return; | ||||
| 
 | ||||
|     wxBusyCursor wait; | ||||
|     // this way we can use that mesh directly.
 | ||||
|     // This mesh does not account for the possible Z up SLA offset.
 | ||||
|     m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh(); | ||||
| 
 | ||||
|     // If this is different mesh than last time
 | ||||
|     if (m_c->m_model_object_id != m_c->m_model_object->id()) { | ||||
|         m_c->m_cavity_mesh.reset(); // dump the cavity
 | ||||
|         m_c->m_volume_with_cavity.reset(); | ||||
|         m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); | ||||
|         m_c->m_mesh_raycaster.reset(); | ||||
|     } | ||||
| 
 | ||||
|     if (! m_c->m_mesh_raycaster) | ||||
|         m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); | ||||
| 
 | ||||
|     m_c->m_model_object_id = m_c->m_model_object->id(); | ||||
|     return m_c->m_clipping_plane->is_point_clipped(transformed_point); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -393,9 +328,11 @@ void GLGizmoHollow::update_mesh() | |||
| // Return false if no intersection was found, true otherwise.
 | ||||
| bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal) | ||||
| { | ||||
|     // if the gizmo doesn't have the V, F structures for igl, calculate them first:
 | ||||
|     if (! m_c->m_mesh_raycaster) | ||||
|         update_mesh(); | ||||
|         return false; | ||||
|     // if the gizmo doesn't have the V, F structures for igl, calculate them first:
 | ||||
|     // !!! is it really necessary?
 | ||||
|     //m_c->update_from_backend(m_parent, m_c->m_model_object);
 | ||||
| 
 | ||||
|     const Camera& camera = m_parent.get_camera(); | ||||
|     const Selection& selection = m_parent.get_selection(); | ||||
|  | @ -406,7 +343,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V | |||
|     // The raycaster query
 | ||||
|     Vec3f hit; | ||||
|     Vec3f normal; | ||||
|     if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) { | ||||
|     if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) { | ||||
|         // Return both the point and the facet normal.
 | ||||
|         pos_and_normal = std::make_pair(hit, normal); | ||||
|         return true; | ||||
|  | @ -492,7 +429,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos | |||
|             points_inside.push_back(points[idx].cast<float>()); | ||||
| 
 | ||||
|         // Only select/deselect points that are actually visible
 | ||||
|         for (size_t idx :  m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get())) | ||||
|         for (size_t idx :  m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) | ||||
|         { | ||||
|             if (rectangle_status == GLSelectionRectangle::Deselect) | ||||
|                 unselect_point(points_idxs[idx]); | ||||
|  | @ -546,13 +483,13 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos | |||
|     } | ||||
| 
 | ||||
|     if (action == SLAGizmoEventType::MouseWheelUp && control_down) { | ||||
|         m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f); | ||||
|         m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f); | ||||
|         update_clipping_plane(true); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     if (action == SLAGizmoEventType::MouseWheelDown && control_down) { | ||||
|         m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f); | ||||
|         m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f); | ||||
|         update_clipping_plane(true); | ||||
|         return true; | ||||
|     } | ||||
|  | @ -605,7 +542,7 @@ void GLGizmoHollow::update_mesh_raycaster(std::unique_ptr<MeshRaycaster> &&rc) | |||
| { | ||||
|     m_c->m_mesh_raycaster = std::move(rc); | ||||
|     m_c->m_object_clipper.reset(); | ||||
|     m_c->m_volume_with_cavity.reset(); | ||||
|     //m_c->m_volume_with_cavity.reset();
 | ||||
| } | ||||
| 
 | ||||
| void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) | ||||
|  | @ -622,8 +559,8 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) | |||
| void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr<TriangleMesh> &&mesh) | ||||
| { | ||||
|     // Called from Plater when the UI job finishes
 | ||||
|     m_c->m_cavity_mesh = std::move(mesh); | ||||
|      | ||||
|     /*m_c->m_cavity_mesh = std::move(mesh);
 | ||||
| 
 | ||||
|     if(m_c->m_cavity_mesh) { | ||||
|         // First subtract the holes:
 | ||||
|         if (! m_c->m_model_object->sla_drain_holes.empty()) { | ||||
|  | @ -665,10 +602,10 @@ void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr<TriangleMesh> &&mesh) | |||
|         m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); | ||||
|     } | ||||
| 
 | ||||
|     if (m_clipping_plane_distance == 0.f) { | ||||
|         m_clipping_plane_distance = 0.5f; | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) { | ||||
|         m_c->m_clipping_plane_distance = 0.5f; | ||||
|         update_clipping_plane(); | ||||
|     } | ||||
|     }*/ | ||||
| } | ||||
| 
 | ||||
| std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>> GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const | ||||
|  | @ -701,10 +638,10 @@ std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>> GLGizmoHollo | |||
| 
 | ||||
| ClippingPlane GLGizmoHollow::get_sla_clipping_plane() const | ||||
| { | ||||
|     if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f) | ||||
|     if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f) | ||||
|         return ClippingPlane::ClipsNothing(); | ||||
|     else | ||||
|         return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]); | ||||
|         return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -724,18 +661,24 @@ RENDER_AGAIN: | |||
| 
 | ||||
|     // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
 | ||||
|     const float settings_sliders_left = | ||||
|       std::max(std::max(m_imgui->calc_text_size(m_desc.at("offset")).x, | ||||
|                         m_imgui->calc_text_size(m_desc.at("quality")).x), | ||||
|                         m_imgui->calc_text_size(m_desc.at("closing_distance")).x) | ||||
|                         + m_imgui->scaled(1.f); | ||||
|       std::max({m_imgui->calc_text_size(m_desc.at("offset")).x, | ||||
|                m_imgui->calc_text_size(m_desc.at("quality")).x, | ||||
|                m_imgui->calc_text_size(m_desc.at("closing_distance")).x, | ||||
|                m_imgui->calc_text_size(m_desc.at("hole_diameter")).x, | ||||
|                m_imgui->calc_text_size(m_desc.at("hole_depth")).x}) | ||||
|            + m_imgui->scaled(1.f); | ||||
| 
 | ||||
|     const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); | ||||
|     const float diameter_slider_left = m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f); | ||||
|     const float diameter_slider_left = settings_sliders_left; //m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f);
 | ||||
|     const float minimal_slider_width = m_imgui->scaled(4.f); | ||||
|     //const float buttons_width_approx = m_imgui->calc_text_size(m_desc.at("apply_changes")).x + m_imgui->calc_text_size(m_desc.at("discard_changes")).x + m_imgui->scaled(1.5f);
 | ||||
| 
 | ||||
|     float window_width = minimal_slider_width + std::max(std::max(settings_sliders_left, clipping_slider_left), diameter_slider_left); | ||||
|     window_width = std::max(std::max(window_width, /*buttons_width_approx*/0.f), 0.f); | ||||
|     float window_width = minimal_slider_width + std::max({settings_sliders_left, clipping_slider_left, diameter_slider_left}); | ||||
|     window_width = std::max(window_width, m_imgui->calc_text_size(m_desc.at("preview")).x); | ||||
| 
 | ||||
|     if (m_imgui->button(m_desc["preview"])) | ||||
|         hollow_mesh(); | ||||
| 
 | ||||
|     ImGui::Separator(); | ||||
| 
 | ||||
|     { | ||||
|         auto opts = get_config_options({"hollowing_enable"}); | ||||
|  | @ -745,11 +688,8 @@ RENDER_AGAIN: | |||
|             wxGetApp().obj_list()->update_and_show_object_settings_item(); | ||||
|         } | ||||
|     } | ||||
|     m_imgui->disabled_begin(! m_enable_hollowing); | ||||
| 
 | ||||
|     ImGui::SameLine(); | ||||
|     if (m_imgui->button(m_desc["preview"])) | ||||
|         hollow_mesh(); | ||||
|     m_imgui->disabled_begin(! m_enable_hollowing); | ||||
| 
 | ||||
|     std::vector<std::string> opts_keys = {"hollowing_min_thickness", "hollowing_quality", "hollowing_closing_distance"}; | ||||
|     auto opts = get_config_options(opts_keys); | ||||
|  | @ -834,7 +774,7 @@ RENDER_AGAIN: | |||
|    // m_imgui->text(" "); // vertical gap
 | ||||
|     ImGui::Separator(); | ||||
| 
 | ||||
|     float diameter_upper_cap = 5.f; | ||||
|     float diameter_upper_cap = 15.; | ||||
|     if (m_new_hole_radius > diameter_upper_cap) | ||||
|         m_new_hole_radius = diameter_upper_cap; | ||||
|     m_imgui->text(m_desc.at("hole_diameter")); | ||||
|  | @ -904,7 +844,7 @@ RENDER_AGAIN: | |||
|     // Following is rendered in both editing and non-editing mode:
 | ||||
|    // m_imgui->text("");
 | ||||
|     ImGui::Separator(); | ||||
|     if (m_clipping_plane_distance == 0.f) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) | ||||
|         m_imgui->text(m_desc.at("clipping_of_view")); | ||||
|     else { | ||||
|         if (m_imgui->button(m_desc.at("reset_direction"))) { | ||||
|  | @ -916,7 +856,7 @@ RENDER_AGAIN: | |||
| 
 | ||||
|     ImGui::SameLine(clipping_slider_left); | ||||
|     ImGui::PushItemWidth(window_width - clipping_slider_left); | ||||
|     if (ImGui::SliderFloat("     ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f")) | ||||
|     if (ImGui::SliderFloat("     ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) | ||||
|         update_clipping_plane(true); | ||||
| 
 | ||||
|     // make sure supports are shown/hidden as appropriate
 | ||||
|  | @ -973,7 +913,7 @@ bool GLGizmoHollow::on_is_selectable() const | |||
| 
 | ||||
| std::string GLGizmoHollow::on_get_name() const | ||||
| { | ||||
|     return (_(L("Hollowing")) + " [H]").ToUTF8().data(); | ||||
|     return (_(L("Hollowing and drilling")) + " [H]").ToUTF8().data(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -995,17 +935,19 @@ void GLGizmoHollow::on_set_state() | |||
| 
 | ||||
|     if (m_state == On && m_old_state != On) { // the gizmo was just turned on
 | ||||
|         //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
 | ||||
|         if (is_mesh_update_necessary()) | ||||
|             update_mesh(); | ||||
|         //m_c->update_from_backend(m_parent, m_c->m_model_object);
 | ||||
|         m_c->unstash_clipping_plane(); | ||||
|         update_clipping_plane(m_c->m_clipping_plane_distance != 0.f); | ||||
| 
 | ||||
|         // we'll now reload support points:
 | ||||
|         if (m_c->m_model_object) | ||||
|             reload_cache(); | ||||
| 
 | ||||
|         m_parent.toggle_model_objects_visibility(false); | ||||
|         if (m_c->m_model_object) | ||||
|             m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); | ||||
|         m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); | ||||
|         if (m_c->m_model_object) { | ||||
|             m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); | ||||
|             m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); | ||||
|         } | ||||
| 
 | ||||
|         // Set default head diameter from config.
 | ||||
|         //const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
 | ||||
|  | @ -1014,8 +956,9 @@ void GLGizmoHollow::on_set_state() | |||
|     if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
 | ||||
|         //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
 | ||||
|         m_parent.toggle_model_objects_visibility(true); | ||||
|         m_clipping_plane_distance = 0.f; | ||||
|         update_clipping_plane(); | ||||
|         m_c->stash_clipping_plane(); | ||||
|         m_c->m_clipping_plane_distance = 0.f; | ||||
|         update_clipping_plane(true); | ||||
|         // Release clippers and the AABB raycaster.
 | ||||
|         m_c->m_object_clipper.reset(); | ||||
|         m_c->m_supports_clipper.reset(); | ||||
|  | @ -1060,8 +1003,8 @@ void GLGizmoHollow::on_stop_dragging() | |||
| 
 | ||||
| void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar) | ||||
| { | ||||
|     ar(m_clipping_plane_distance, | ||||
|        *m_clipping_plane, | ||||
|     ar(m_c->m_clipping_plane_distance, | ||||
|        *m_c->m_clipping_plane, | ||||
|        m_c->m_model_object_id, | ||||
|        m_new_hole_radius, | ||||
|        m_new_hole_height, | ||||
|  | @ -1074,8 +1017,8 @@ void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar) | |||
| 
 | ||||
| void GLGizmoHollow::on_save(cereal::BinaryOutputArchive& ar) const | ||||
| { | ||||
|     ar(m_clipping_plane_distance, | ||||
|        *m_clipping_plane, | ||||
|     ar(m_c->m_clipping_plane_distance, | ||||
|        *m_c->m_clipping_plane, | ||||
|        m_c->m_model_object_id, | ||||
|        m_new_hole_radius, | ||||
|        m_new_hole_height, | ||||
|  | @ -1128,12 +1071,14 @@ void GLGizmoHollow::reload_cache() | |||
| 
 | ||||
| void GLGizmoHollow::update_clipping_plane(bool keep_normal) const | ||||
| { | ||||
|     Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ? | ||||
|                         m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); | ||||
|     if (! m_c->m_model_object) | ||||
|         return; | ||||
|     Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? | ||||
|                         m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); | ||||
| 
 | ||||
|     const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); | ||||
|     float dist = normal.dot(center); | ||||
|     *m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); | ||||
|     *m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); | ||||
|     m_parent.set_as_dirty(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -53,14 +53,12 @@ private: | |||
|     void render_points(const Selection& selection, bool picking = false) const; | ||||
|     void render_clipping_plane(const Selection& selection) const; | ||||
|     void render_hollowed_mesh() const; | ||||
|     bool is_mesh_update_necessary() const; | ||||
|     void update_mesh(); | ||||
|     void hollow_mesh(bool postpone_error_messages = false); | ||||
|     bool unsaved_changes() const; | ||||
| 
 | ||||
|     bool  m_show_supports = true; | ||||
|     float m_new_hole_radius = 2.f;        // Size of a new hole.
 | ||||
|     float m_new_hole_height = 5.f; | ||||
|     float m_new_hole_height = 6.f; | ||||
|     mutable std::vector<bool> m_selected; // which holes are currently selected
 | ||||
| 
 | ||||
|     bool m_enable_hollowing = true; | ||||
|  | @ -72,13 +70,9 @@ private: | |||
|     float m_closing_d_stash = 2.f; | ||||
|     Vec3f m_hole_before_drag = Vec3f::Zero(); | ||||
| 
 | ||||
| 
 | ||||
|     sla::DrainHoles m_holes_stash; | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
|     float m_clipping_plane_distance = 0.f; | ||||
|     std::unique_ptr<ClippingPlane> m_clipping_plane; | ||||
|     //std::unique_ptr<ClippingPlane> m_clipping_plane;
 | ||||
|      | ||||
|     // This map holds all translated description texts, so they can be easily referenced during layout calculations
 | ||||
|     // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& ic | |||
|     , m_quadric(nullptr) | ||||
|     , m_its(nullptr) | ||||
| { | ||||
|     m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); | ||||
|     m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); | ||||
|     m_quadric = ::gluNewQuadric(); | ||||
|     if (m_quadric != nullptr) | ||||
|         // using GLU_FILL does not work when the instance's transformation
 | ||||
|  | @ -63,43 +63,22 @@ bool GLGizmoSlaSupports::on_init() | |||
| 
 | ||||
| void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection) | ||||
| { | ||||
|     if (! model_object || selection.is_empty()) { | ||||
|         m_c->m_model_object = nullptr; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     bool something_changed = false; | ||||
| 
 | ||||
|     if (m_c->m_model_object != model_object | ||||
|      || m_c->m_model_object_id != model_object->id() | ||||
|      || m_c->m_active_instance != selection.get_instance_idx()) { | ||||
|         m_c->m_model_object = model_object; | ||||
|         m_c->m_print_object_idx = -1; | ||||
|         m_c->m_active_instance = selection.get_instance_idx(); | ||||
|         something_changed = true; | ||||
|     } | ||||
| 
 | ||||
|     if (model_object && selection.is_from_single_instance()) | ||||
|     { | ||||
|         // Cache the bb - it's needed for dealing with the clipping plane quite often
 | ||||
|         // It could be done inside update_mesh but one has to account for scaling of the instance.
 | ||||
|         if (something_changed) { | ||||
|             m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); | ||||
|             if (m_state == On) { | ||||
|                 m_parent.toggle_model_objects_visibility(false); | ||||
|                 m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); | ||||
|                 m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); | ||||
|             } | ||||
|             else | ||||
|                 m_parent.toggle_model_objects_visibility(true, nullptr, -1); | ||||
|     if (m_c->recent_update) { | ||||
|         if (m_state == On) { | ||||
|             m_parent.toggle_model_objects_visibility(false); | ||||
|             m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance); | ||||
|             m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); | ||||
|         } | ||||
|         else | ||||
|             m_parent.toggle_model_objects_visibility(true, nullptr, -1); | ||||
| 
 | ||||
|         if (is_mesh_update_necessary()) { | ||||
|             update_mesh(); | ||||
|         disable_editing_mode(); | ||||
|         if (m_c->m_model_object) | ||||
|             reload_cache(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         // If we triggered autogeneration before, check backend and fetch results if they are there
 | ||||
|     // If we triggered autogeneration before, check backend and fetch results if they are there
 | ||||
|     if (m_c->m_model_object) { | ||||
|         if (m_c->m_model_object->sla_points_status == sla::PointsStatus::Generating) | ||||
|             get_data_from_backend(); | ||||
|     } | ||||
|  | @ -120,9 +99,6 @@ void GLGizmoSlaSupports::on_render() const | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (! m_its || ! m_c->m_mesh) | ||||
|         const_cast<GLGizmoSlaSupports*>(this)->update_mesh(); | ||||
| 
 | ||||
|     glsafe(::glEnable(GL_BLEND)); | ||||
|     glsafe(::glEnable(GL_DEPTH_TEST)); | ||||
| 
 | ||||
|  | @ -143,7 +119,7 @@ void GLGizmoSlaSupports::on_render() const | |||
| 
 | ||||
| void GLGizmoSlaSupports::render_hollowed_mesh() const | ||||
| { | ||||
|     if (m_c->m_volume_with_cavity) { | ||||
|     /*if (m_c->m_volume_with_cavity) {
 | ||||
|         m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift); | ||||
|         m_parent.get_shader().start_using(); | ||||
| 
 | ||||
|  | @ -159,14 +135,14 @@ void GLGizmoSlaSupports::render_hollowed_mesh() const | |||
|         m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation()); | ||||
|         m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id); | ||||
|         m_parent.get_shader().stop_using(); | ||||
|     } | ||||
|     }*/ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const | ||||
| { | ||||
|     if (m_clipping_plane_distance == 0.f || m_c->m_mesh->empty()) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f || m_c->m_mesh->empty()) | ||||
|         return; | ||||
| 
 | ||||
|     // Get transformation of the instance
 | ||||
|  | @ -188,7 +164,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const | |||
|         m_c->m_object_clipper.reset(new MeshClipper); | ||||
|         m_c->m_object_clipper->set_mesh(*m_c->mesh()); | ||||
|     } | ||||
|     m_c->m_object_clipper->set_plane(*m_clipping_plane); | ||||
|     m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane); | ||||
|     m_c->m_object_clipper->set_transformation(trafo); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -219,7 +195,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const | |||
|                 m_c->m_supports_clipper->set_mesh(print_object->support_mesh()); | ||||
|                 m_c->m_old_timestamp = timestamp; | ||||
|             } | ||||
|             m_c->m_supports_clipper->set_plane(*m_clipping_plane); | ||||
|             m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane); | ||||
|             m_c->m_supports_clipper->set_transformation(supports_trafo); | ||||
|         } | ||||
|         else | ||||
|  | @ -359,7 +335,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) | |||
|     } | ||||
| 
 | ||||
|     // Now render the drain holes:
 | ||||
|     if (! m_c->m_cavity_mesh) { | ||||
|     /*if (! m_c->m_cavity_mesh) {
 | ||||
|         render_color[0] = 0.7f; | ||||
|         render_color[1] = 0.7f; | ||||
|         render_color[2] = 0.7f; | ||||
|  | @ -394,7 +370,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) | |||
|                 glFrontFace(GL_CCW); | ||||
|             glsafe(::glPopMatrix()); | ||||
|         } | ||||
|     } | ||||
|     }*/ | ||||
| 
 | ||||
|     if (!picking) | ||||
|         glsafe(::glDisable(GL_LIGHTING)); | ||||
|  | @ -406,51 +382,22 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) | |||
| 
 | ||||
| bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const | ||||
| { | ||||
|     if (m_clipping_plane_distance == 0.f) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) | ||||
|         return false; | ||||
| 
 | ||||
|     Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point; | ||||
|     transformed_point(2) += m_z_shift; | ||||
|     return m_clipping_plane->is_point_clipped(transformed_point); | ||||
|     return m_c->m_clipping_plane->is_point_clipped(transformed_point); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| bool GLGizmoSlaSupports::is_mesh_update_necessary() const | ||||
| { | ||||
|     return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty()) | ||||
|         && ((m_c->m_model_object->id() != m_c->m_model_object_id) || m_its == nullptr); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void GLGizmoSlaSupports::update_mesh() | ||||
| { | ||||
|     if (! m_c->m_model_object) | ||||
|         return; | ||||
| 
 | ||||
|     wxBusyCursor wait; | ||||
|     // this way we can use that mesh directly.
 | ||||
|     // This mesh does not account for the possible Z up SLA offset.
 | ||||
|     m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh(); | ||||
|     m_its = &m_c->m_mesh->its; | ||||
| 
 | ||||
|     // If this is different mesh than last time or if the AABB tree is uninitialized, recalculate it.
 | ||||
|     if (m_c->m_model_object_id != m_c->m_model_object->id() || ! m_c->m_mesh_raycaster) | ||||
|         m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); | ||||
| 
 | ||||
|     m_c->m_model_object_id = m_c->m_model_object->id(); | ||||
|     disable_editing_mode(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
 | ||||
| // Return false if no intersection was found, true otherwise.
 | ||||
| bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal) | ||||
| { | ||||
|     // if the gizmo doesn't have the V, F structures for igl, calculate them first:
 | ||||
|     if (! m_c->m_mesh_raycaster) | ||||
|         update_mesh(); | ||||
|         return false; | ||||
| 
 | ||||
|     const Camera& camera = m_parent.get_camera(); | ||||
|     const Selection& selection = m_parent.get_selection(); | ||||
|  | @ -461,20 +408,20 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec | |||
|     // The raycaster query
 | ||||
|     Vec3f hit; | ||||
|     Vec3f normal; | ||||
|     if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) { | ||||
|     if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) { | ||||
|         // Check whether the hit is in a hole
 | ||||
|         bool in_hole = false; | ||||
|         // In case the hollowed and drilled mesh is available, we can allow
 | ||||
|         // placing points in holes, because they should never end up
 | ||||
|         // on surface that's been drilled away.
 | ||||
|         if (! m_c->m_cavity_mesh) { | ||||
|         /*if (! m_c->m_cavity_mesh) {
 | ||||
|             for (const sla::DrainHole& hole : m_c->m_model_object->sla_drain_holes) { | ||||
|                 if (hole.is_inside(hit)) { | ||||
|                     in_hole = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         }*/ | ||||
|         if (! in_hole) { | ||||
|             // Return both the point and the facet normal.
 | ||||
|             pos_and_normal = std::make_pair(hit, normal); | ||||
|  | @ -555,7 +502,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous | |||
|                 points_inside.push_back(points[idx].cast<float>()); | ||||
| 
 | ||||
|             // Only select/deselect points that are actually visible
 | ||||
|             for (size_t idx :  m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get())) | ||||
|             for (size_t idx :  m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) | ||||
|             { | ||||
|                 if (rectangle_status == GLSelectionRectangle::Deselect) | ||||
|                     unselect_point(points_idxs[idx]); | ||||
|  | @ -632,13 +579,13 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous | |||
|     } | ||||
| 
 | ||||
|     if (action == SLAGizmoEventType::MouseWheelUp && control_down) { | ||||
|         m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f); | ||||
|         m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f); | ||||
|         update_clipping_plane(true); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     if (action == SLAGizmoEventType::MouseWheelDown && control_down) { | ||||
|         m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f); | ||||
|         m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f); | ||||
|         update_clipping_plane(true); | ||||
|         return true; | ||||
|     } | ||||
|  | @ -719,10 +666,10 @@ std::vector<const ConfigOption*> GLGizmoSlaSupports::get_config_options(const st | |||
| 
 | ||||
| ClippingPlane GLGizmoSlaSupports::get_sla_clipping_plane() const | ||||
| { | ||||
|     if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f) | ||||
|     if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f) | ||||
|         return ClippingPlane::ClipsNothing(); | ||||
|     else | ||||
|         return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]); | ||||
|         return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -944,7 +891,7 @@ RENDER_AGAIN: | |||
| 
 | ||||
|     // Following is rendered in both editing and non-editing mode:
 | ||||
|     ImGui::Separator(); | ||||
|     if (m_clipping_plane_distance == 0.f) | ||||
|     if (m_c->m_clipping_plane_distance == 0.f) | ||||
|     { | ||||
|         ImGui::AlignTextToFramePadding(); | ||||
|         m_imgui->text(m_desc.at("clipping_of_view")); | ||||
|  | @ -959,7 +906,7 @@ RENDER_AGAIN: | |||
| 
 | ||||
|     ImGui::SameLine(clipping_slider_left); | ||||
|     ImGui::PushItemWidth(window_width - clipping_slider_left); | ||||
|     if (ImGui::SliderFloat("  ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f")) | ||||
|     if (ImGui::SliderFloat("  ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) | ||||
|         update_clipping_plane(true); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1043,15 +990,17 @@ void GLGizmoSlaSupports::on_set_state() | |||
| 
 | ||||
|     if (m_state == On && m_old_state != On) { // the gizmo was just turned on
 | ||||
|         Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); | ||||
|         if (is_mesh_update_necessary()) | ||||
|             update_mesh(); | ||||
| 
 | ||||
|         m_c->unstash_clipping_plane(); | ||||
|         update_clipping_plane(m_c->m_clipping_plane_distance != 0.f); | ||||
| 
 | ||||
| 
 | ||||
|         // we'll now reload support points:
 | ||||
|         if (m_c->m_model_object) | ||||
|             reload_cache(); | ||||
| 
 | ||||
|         m_parent.toggle_model_objects_visibility(false); | ||||
|         if (m_c->m_model_object && ! m_c->m_cavity_mesh) | ||||
|         if (m_c->m_model_object /*&& ! m_c->m_cavity_mesh*/) | ||||
|             m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); | ||||
|         m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); | ||||
| 
 | ||||
|  | @ -1081,13 +1030,14 @@ void GLGizmoSlaSupports::on_set_state() | |||
|             Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off"))); | ||||
|             m_parent.toggle_model_objects_visibility(true); | ||||
|             m_normal_cache.clear(); | ||||
|             m_clipping_plane_distance = 0.f; | ||||
|             update_clipping_plane(); | ||||
|             m_c->stash_clipping_plane(); | ||||
|             m_c->m_clipping_plane_distance = 0.f; | ||||
|             update_clipping_plane(true); | ||||
|             // Release clippers and the AABB raycaster.
 | ||||
|             m_its = nullptr; | ||||
|             m_c->m_object_clipper.reset(); | ||||
|             m_c->m_supports_clipper.reset(); | ||||
|             m_c->m_mesh_raycaster.reset(); | ||||
|             //m_c->m_mesh_raycaster.reset();
 | ||||
|         } | ||||
|     } | ||||
|     m_old_state = m_state; | ||||
|  | @ -1127,8 +1077,8 @@ void GLGizmoSlaSupports::on_stop_dragging() | |||
| 
 | ||||
| void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) | ||||
| { | ||||
|     ar(m_clipping_plane_distance, | ||||
|        *m_clipping_plane, | ||||
|     ar(m_c->m_clipping_plane_distance, | ||||
|        *m_c->m_clipping_plane, | ||||
|        m_c->m_model_object_id, | ||||
|        m_new_point_head_diameter, | ||||
|        m_normal_cache, | ||||
|  | @ -1141,8 +1091,8 @@ void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) | |||
| 
 | ||||
| void GLGizmoSlaSupports::on_save(cereal::BinaryOutputArchive& ar) const | ||||
| { | ||||
|     ar(m_clipping_plane_distance, | ||||
|        *m_clipping_plane, | ||||
|     ar(m_c->m_clipping_plane_distance, | ||||
|        *m_c->m_clipping_plane, | ||||
|        m_c->m_model_object_id, | ||||
|        m_new_point_head_diameter, | ||||
|        m_normal_cache, | ||||
|  | @ -1244,6 +1194,9 @@ void GLGizmoSlaSupports::reload_cache() | |||
| 
 | ||||
| bool GLGizmoSlaSupports::has_backend_supports() const | ||||
| { | ||||
|     if (! m_c->m_model_object) | ||||
|         return false; | ||||
| 
 | ||||
|     // find SlaPrintObject with this ID
 | ||||
|     for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { | ||||
|         if (po->model_object()->id() == m_c->m_model_object->id()) | ||||
|  | @ -1338,12 +1291,12 @@ bool GLGizmoSlaSupports::unsaved_changes() const | |||
| 
 | ||||
| void GLGizmoSlaSupports::update_clipping_plane(bool keep_normal) const | ||||
| { | ||||
|     Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ? | ||||
|                         m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); | ||||
|     Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? | ||||
|                         m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); | ||||
| 
 | ||||
|     const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); | ||||
|     float dist = normal.dot(center); | ||||
|     *m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); | ||||
|     *m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); | ||||
|     m_parent.set_as_dirty(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -91,8 +91,6 @@ private: | |||
|     void render_points(const Selection& selection, bool picking = false) const; | ||||
|     void render_clipping_plane(const Selection& selection) const; | ||||
|     void render_hollowed_mesh() const; | ||||
|     bool is_mesh_update_necessary() const; | ||||
|     void update_mesh(); | ||||
|     bool unsaved_changes() const; | ||||
| 
 | ||||
|     bool m_lock_unique_islands = false; | ||||
|  | @ -105,8 +103,7 @@ private: | |||
|     mutable std::vector<CacheEntry> m_editing_cache; // a support point and whether it is currently selected
 | ||||
|     std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
 | ||||
| 
 | ||||
|     float m_clipping_plane_distance = 0.f; | ||||
|     std::unique_ptr<ClippingPlane> m_clipping_plane; | ||||
|     //std::unique_ptr<ClippingPlane> m_clipping_plane;
 | ||||
| 
 | ||||
|     // This map holds all translated description texts, so they can be easily referenced during layout calculations
 | ||||
|     // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
 | ||||
|  |  | |||
|  | @ -348,6 +348,9 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object) | |||
|     if (!m_enabled || m_gizmos.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     // Update common data for hollowing and sla support gizmos.
 | ||||
|     m_common_gizmos_data->update_from_backend(m_parent, model_object); | ||||
| 
 | ||||
|     dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection()); | ||||
|     dynamic_cast<GLGizmoHollow*>(m_gizmos[Hollow].get())->set_sla_support_data(model_object, m_parent.get_selection()); | ||||
| } | ||||
|  |  | |||
|  | @ -5130,7 +5130,7 @@ void Plater::reslice_SLA_supports(const ModelObject &object, bool postpone_error | |||
| 
 | ||||
| void Plater::reslice_SLA_hollowing(const ModelObject &object, bool postpone_error_messages) | ||||
| { | ||||
|     reslice_SLA_until_step(slaposHollowing, object, postpone_error_messages); | ||||
|     reslice_SLA_until_step(slaposDrillHoles, object, postpone_error_messages); | ||||
| } | ||||
| 
 | ||||
| void Plater::reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Matena
						Lukas Matena