mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/Slic3r into et_copy_and_paste
This commit is contained in:
		
						commit
						c4978817f3
					
				
					 10 changed files with 121 additions and 24 deletions
				
			
		|  | @ -1189,6 +1189,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b | |||
|             volume->mesh.transform(instance_matrix * volume_matrix, true); | ||||
| 
 | ||||
|             // Perform cut
 | ||||
|             volume->mesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|             TriangleMeshSlicer tms(&volume->mesh); | ||||
|             tms.cut(float(z), &upper_mesh, &lower_mesh); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1813,6 +1813,7 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z, | |||
|             TriangleMeshSlicer mslicer; | ||||
|             const Print *print = this->print(); | ||||
|             auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();}); | ||||
|             mesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|             mslicer.init(&mesh, callback); | ||||
| 			mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback); | ||||
|             m_print->throw_if_canceled(); | ||||
|  | @ -1840,6 +1841,7 @@ std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z, | |||
|         TriangleMeshSlicer mslicer; | ||||
|         const Print *print = this->print(); | ||||
|         auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();}); | ||||
|         mesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|         mslicer.init(&mesh, callback); | ||||
|         mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback); | ||||
|         m_print->throw_if_canceled(); | ||||
|  |  | |||
|  | @ -552,6 +552,7 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h, | |||
|                 float layerh, ThrowOnCancel thrfn) | ||||
| { | ||||
|     TriangleMesh m = mesh; | ||||
|     m.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|     TriangleMeshSlicer slicer(&m); | ||||
| 
 | ||||
|     auto bb = mesh.bounding_box(); | ||||
|  |  | |||
|  | @ -817,6 +817,10 @@ public: | |||
| 
 | ||||
|         meshcache = mesh(merged); | ||||
| 
 | ||||
|         // The mesh will be passed by const-pointer to TriangleMeshSlicer,
 | ||||
|         // which will need this.
 | ||||
|         meshcache.require_shared_vertices(); | ||||
| 
 | ||||
|         // TODO: Is this necessary?
 | ||||
|         //meshcache.repair();
 | ||||
| 
 | ||||
|  | @ -2231,6 +2235,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const | |||
| 
 | ||||
|     TriangleMesh fullmesh = m_impl->merged_mesh(); | ||||
|     fullmesh.merge(get_pad()); | ||||
|     fullmesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|     TriangleMeshSlicer slicer(&fullmesh); | ||||
|     SlicedSupports ret; | ||||
|     slicer.slice(heights, 0.f, &ret, get().ctl().cancelfn); | ||||
|  | @ -2243,6 +2248,7 @@ SlicedSupports SLASupportTree::slice(const std::vector<float> &heights, | |||
| { | ||||
|     TriangleMesh fullmesh = m_impl->merged_mesh(); | ||||
|     fullmesh.merge(get_pad()); | ||||
|     fullmesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|     TriangleMeshSlicer slicer(&fullmesh); | ||||
|     SlicedSupports ret; | ||||
|     slicer.slice(heights, cr, &ret, get().ctl().cancelfn); | ||||
|  |  | |||
|  | @ -706,6 +706,7 @@ void SLAPrint::process() | |||
|             po.m_model_height_levels.emplace_back(it->slice_level()); | ||||
|         } | ||||
| 
 | ||||
|         mesh.require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|         TriangleMeshSlicer slicer(&mesh); | ||||
| 
 | ||||
|         po.m_model_slices.clear(); | ||||
|  |  | |||
|  | @ -607,10 +607,12 @@ void TriangleMesh::require_shared_vertices() | |||
|     BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - end"; | ||||
| } | ||||
| 
 | ||||
| void TriangleMeshSlicer::init(TriangleMesh *_mesh, throw_on_cancel_callback_type throw_on_cancel) | ||||
| void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callback_type throw_on_cancel) | ||||
| { | ||||
|     mesh = _mesh; | ||||
|     _mesh->require_shared_vertices(); | ||||
|     if (! mesh->has_shared_vertices()) | ||||
|         throw std::invalid_argument("TriangleMeshSlicer was passed a mesh without shared vertices."); | ||||
| 
 | ||||
|     throw_on_cancel(); | ||||
|     facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1); | ||||
|     v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices); | ||||
|  |  | |||
|  | @ -67,18 +67,17 @@ public: | |||
|     TriangleMesh convex_hull_3d() const; | ||||
|     void reset_repair_stats(); | ||||
|     bool needed_repair() const; | ||||
|     void require_shared_vertices(); | ||||
|     bool   has_shared_vertices() const { return stl.v_shared != NULL; } | ||||
|     size_t facets_count() const { return this->stl.stats.number_of_facets; } | ||||
|     bool   empty() const { return this->facets_count() == 0; } | ||||
| 
 | ||||
|     bool is_splittable() const; | ||||
| 
 | ||||
|     stl_file stl; | ||||
|     bool repaired; | ||||
|      | ||||
| 
 | ||||
| private: | ||||
|     void require_shared_vertices(); | ||||
|     std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const; | ||||
|     friend class TriangleMeshSlicer; | ||||
| }; | ||||
| 
 | ||||
| enum FacetEdgeType {  | ||||
|  | @ -159,9 +158,8 @@ class TriangleMeshSlicer | |||
| public: | ||||
|     typedef std::function<void()> throw_on_cancel_callback_type; | ||||
|     TriangleMeshSlicer() : mesh(nullptr) {} | ||||
|     // Not quite nice, but the constructor and init() methods require non-const mesh pointer to be able to call mesh->require_shared_vertices()
 | ||||
| 	TriangleMeshSlicer(TriangleMesh* mesh) { this->init(mesh, [](){}); } | ||||
|     void init(TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel); | ||||
| 	TriangleMeshSlicer(const TriangleMesh* mesh) { this->init(mesh, [](){}); } | ||||
|     void init(const TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel); | ||||
|     void slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const; | ||||
|     void slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const; | ||||
|     enum FacetSliceType { | ||||
|  |  | |||
|  | @ -3681,7 +3681,7 @@ void GLCanvas3D::_render_objects() const | |||
|         m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); | ||||
| 
 | ||||
|         m_shader.start_using(); | ||||
|         if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) { | ||||
|         if (m_picking_enabled && !m_gizmos.is_dragging() && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) { | ||||
|             int object_id = m_layers_editing.last_object_id; | ||||
|             m_volumes.render_VBOs(GLVolumeCollection::Opaque, false, m_camera.get_view_matrix(), [object_id](const GLVolume &volume) { | ||||
|                 // Which volume to paint without the layer height profile shader?
 | ||||
|  |  | |||
|  | @ -51,6 +51,9 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (m_model_object != model_object) | ||||
|         m_print_object_idx = -1; | ||||
| 
 | ||||
|     m_model_object = model_object; | ||||
|     m_active_instance = selection.get_instance_idx(); | ||||
| 
 | ||||
|  | @ -111,32 +114,92 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection, const | |||
|     if (m_clipping_plane_distance == 0.f) | ||||
|         return; | ||||
| 
 | ||||
|     // First cache instance transformation to be used later.
 | ||||
|     const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); | ||||
|     Transform3f instance_matrix = vol->get_instance_transformation().get_matrix().cast<float>(); | ||||
|     Transform3f instance_matrix_no_translation_no_scaling = vol->get_instance_transformation().get_matrix(true,false,true).cast<float>(); | ||||
|     Vec3f scaling = vol->get_instance_scaling_factor().cast<float>(); | ||||
|     Vec3d instance_offset = vol->get_instance_offset(); | ||||
| 
 | ||||
|     // Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
 | ||||
|     Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * direction_to_camera.cast<float>(); | ||||
|     Vec3f up = Vec3f(up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2)); | ||||
|     float height_mesh = (m_active_instance_bb_radius - m_clipping_plane_distance * 2*m_active_instance_bb_radius) * (up_noscale.norm()/up.norm()); | ||||
| 
 | ||||
|     // Get transformation of the supports and calculate how far from its origin the clipping plane is.
 | ||||
|     Transform3d supports_trafo = Transform3d::Identity(); | ||||
|     supports_trafo = supports_trafo.rotate(Eigen::AngleAxisd(vol->get_instance_rotation()(2), Vec3d::UnitZ())); | ||||
|     Vec3f up_supports = (supports_trafo.inverse() * direction_to_camera).cast<float>(); | ||||
|     supports_trafo = supports_trafo.pretranslate(Vec3d(instance_offset(0), instance_offset(1), vol->get_sla_shift_z())); | ||||
|     // Instance and supports origin do not coincide, so the following is quite messy:
 | ||||
|     float height_supports = height_mesh * (up.norm() / up_supports.norm()) + instance_offset(2) * (direction_to_camera(2) / direction_to_camera.norm()); | ||||
| 
 | ||||
|     // In case either of these was recently changed, the cached triangulated ExPolygons are invalid now.
 | ||||
|     // We are gonna recalculate them both for the object and for the support structures.
 | ||||
|     if (m_clipping_plane_distance != m_old_clipping_plane_distance | ||||
|      || m_old_direction_to_camera != direction_to_camera) { | ||||
| 
 | ||||
|         std::vector<ExPolygons> list_of_expolys; | ||||
|         m_old_direction_to_camera = direction_to_camera; | ||||
|         m_old_clipping_plane_distance = m_clipping_plane_distance; | ||||
| 
 | ||||
|         // Now initialize the TMS for the object, perform the cut and save the result.
 | ||||
|         if (! m_tms) { | ||||
|             m_tms.reset(new TriangleMeshSlicer); | ||||
|             m_tms->init(const_cast<TriangleMesh*>(&m_mesh), [](){}); | ||||
|             m_tms->init(m_mesh, [](){}); | ||||
|         } | ||||
| 
 | ||||
|         std::vector<ExPolygons> list_of_expolys; | ||||
|         m_tms->set_up_direction(up); | ||||
|         m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){}); | ||||
|         m_triangles = triangulate_expolygons_2f(list_of_expolys[0]); | ||||
| 
 | ||||
|         m_old_direction_to_camera = direction_to_camera; | ||||
|         m_old_clipping_plane_distance = m_clipping_plane_distance; | ||||
| 
 | ||||
| 
 | ||||
|         // 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_print_object_idx < 0 || (int)m_parent.sla_print()->objects().size() != m_print_objects_count) { | ||||
|             m_print_objects_count = m_parent.sla_print()->objects().size(); | ||||
|             m_print_object_idx = -1; | ||||
|             for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { | ||||
|                 ++m_print_object_idx; | ||||
|                 if (po->model_object()->id() == m_model_object->id()) | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         if (m_print_object_idx >= 0) { | ||||
|             const SLAPrintObject* print_object = m_parent.sla_print()->objects()[m_print_object_idx]; | ||||
| 
 | ||||
|             if (print_object->is_step_done(slaposSupportTree)) { | ||||
|                 // If the supports are already calculated, save the timestamp of the respective step
 | ||||
|                 // so we can later tell they were recalculated.
 | ||||
|                 size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp; | ||||
| 
 | ||||
|                 if (!m_supports_tms || (int)timestamp != m_old_timestamp) { | ||||
|                     // The timestamp has changed - stash the mesh and initialize the TMS.
 | ||||
|                     m_supports_mesh = &print_object->support_mesh(); | ||||
|                     m_supports_tms.reset(new TriangleMeshSlicer); | ||||
|                     // The mesh should already have the shared vertices calculated.
 | ||||
|                     m_supports_tms->init(m_supports_mesh, [](){}); | ||||
|                     m_old_timestamp = timestamp; | ||||
|                 } | ||||
| 
 | ||||
|                 // The TMS is initialized - let's do the cutting:
 | ||||
|                 list_of_expolys.clear(); | ||||
|                 m_supports_tms->set_up_direction(up_supports); | ||||
|                 m_supports_tms->slice(std::vector<float>{height_supports}, 0.f, &list_of_expolys, [](){}); | ||||
|                 m_supports_triangles = triangulate_expolygons_2f(list_of_expolys[0]); | ||||
|             } | ||||
|             else { | ||||
|                 // The supports are not valid. We better dump the cached data.
 | ||||
|                 m_supports_tms.reset(); | ||||
|                 m_supports_triangles.clear(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // At this point we have the triangulated cuts for both the object and supports - let's render.
 | ||||
|     ::glColor3f(1.0f, 0.37f, 0.0f); | ||||
| 
 | ||||
| 	if (! m_triangles.empty()) { | ||||
| 		::glPushMatrix(); | ||||
| 		::glTranslated(0.0, 0.0, m_z_shift); | ||||
|  | @ -146,11 +209,26 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection, const | |||
| 		Eigen::AngleAxisf aa(q); | ||||
| 		::glRotatef(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)); | ||||
| 		::glTranslatef(0.f, 0.f, -0.001f); // to make sure the cut is safely beyond the near clipping plane
 | ||||
| 		::glColor3f(1.0f, 0.37f, 0.0f); | ||||
|         ::glBegin(GL_TRIANGLES); | ||||
|         ::glColor3f(1.0f, 0.37f, 0.0f); | ||||
|         for (const Vec2f& point : m_triangles) | ||||
|             ::glVertex3f(point(0), point(1), height_mesh); | ||||
| 
 | ||||
|         ::glEnd(); | ||||
| 		::glPopMatrix(); | ||||
| 	} | ||||
| 
 | ||||
|     if (! m_supports_triangles.empty()) { | ||||
| 		::glPushMatrix(); | ||||
|         ::glMultMatrixd(supports_trafo.data()); | ||||
|         Eigen::Quaternionf q; | ||||
| 		q.setFromTwoVectors(Vec3f::UnitZ(), up_supports); | ||||
| 		Eigen::AngleAxisf aa(q); | ||||
| 		::glRotatef(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)); | ||||
| 		::glTranslatef(0.f, 0.f, -0.001f); // to make sure the cut is safely beyond the near clipping plane
 | ||||
|         ::glBegin(GL_TRIANGLES); | ||||
|         for (const Vec2f& point : m_supports_triangles) | ||||
|             ::glVertex3f(point(0), point(1), height_supports); | ||||
| 
 | ||||
|         ::glEnd(); | ||||
| 		::glPopMatrix(); | ||||
| 	} | ||||
|  | @ -332,9 +410,12 @@ void GLGizmoSlaSupports::update_mesh() | |||
|     wxBusyCursor wait; | ||||
|     Eigen::MatrixXf& V = m_V; | ||||
|     Eigen::MatrixXi& F = m_F; | ||||
|     // We rely on SLA model object having a single volume,
 | ||||
|     // this way we can use that mesh directly.
 | ||||
|     // This mesh does not account for the possible Z up SLA offset.
 | ||||
|     m_mesh = m_model_object->raw_mesh(); | ||||
|     const stl_file& stl = m_mesh.stl; | ||||
|     m_mesh = &m_model_object->volumes.front()->mesh; | ||||
|     const_cast<TriangleMesh*>(m_mesh)->require_shared_vertices(); // TriangleMeshSlicer needs this
 | ||||
|     const stl_file& stl = m_mesh->stl; | ||||
|     V.resize(3 * stl.stats.number_of_facets, 3); | ||||
|     F.resize(stl.stats.number_of_facets, 3); | ||||
|     for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) { | ||||
|  | @ -972,12 +1053,12 @@ void GLGizmoSlaSupports::on_set_state() | |||
|                 m_editing_mode = false; // so it is not active next time the gizmo opens
 | ||||
|                 m_editing_mode_cache.clear(); | ||||
|                 m_clipping_plane_distance = 0.f; | ||||
|                 // Release copy of the mesh, triangle slicer and the AABB spatial search structure.
 | ||||
| 				m_mesh.clear(); | ||||
|                 // Release triangle mesh slicer and the AABB spatial search structure.
 | ||||
|                 m_AABB.deinit(); | ||||
| 				m_V = Eigen::MatrixXf(); | ||||
| 				m_F = Eigen::MatrixXi(); | ||||
|                 m_tms.reset(nullptr); | ||||
|                 m_tms.reset(); | ||||
|                 m_supports_tms.reset(); | ||||
|             }); | ||||
|         } | ||||
|         m_old_state = m_state; | ||||
|  |  | |||
|  | @ -36,8 +36,13 @@ private: | |||
|     Eigen::MatrixXf m_V; // vertices
 | ||||
|     Eigen::MatrixXi m_F; // facets indices
 | ||||
|     igl::AABB<Eigen::MatrixXf,3> m_AABB; | ||||
|     TriangleMesh m_mesh; | ||||
|     const TriangleMesh* m_mesh; | ||||
|     mutable const TriangleMesh* m_supports_mesh; | ||||
|     mutable std::vector<Vec2f> m_triangles; | ||||
|     mutable std::vector<Vec2f> m_supports_triangles; | ||||
|     mutable int m_old_timestamp = -1; | ||||
|     mutable int m_print_object_idx = -1; | ||||
|     mutable int m_print_objects_count = -1; | ||||
| 
 | ||||
|     class CacheEntry { | ||||
|     public: | ||||
|  | @ -79,7 +84,6 @@ private: | |||
|     bool m_old_editing_state = false;       // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
 | ||||
|     float m_new_point_head_diameter;        // Size of a new point.
 | ||||
|     float m_minimal_point_distance = 20.f; | ||||
|     float m_density = 100.f; | ||||
|     mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
 | ||||
|     float m_clipping_plane_distance = 0.f; | ||||
|     mutable float m_old_clipping_plane_distance = 0.f; | ||||
|  | @ -101,6 +105,7 @@ private: | |||
|     int m_canvas_height; | ||||
| 
 | ||||
|     mutable std::unique_ptr<TriangleMeshSlicer> m_tms; | ||||
|     mutable std::unique_ptr<TriangleMeshSlicer> m_supports_tms; | ||||
| 
 | ||||
|     std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const; | ||||
|     bool is_point_clipped(const Vec3d& point, const Vec3d& direction_to_camera) const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri