mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Fix of "Variable layer height feature breaks after rotating part #2073"
There was an approximate bounding box used at the GUI, while a snug bounding box was used at the back end, causing invalidation of the variable layer height editing profile on rotated objects. A snug bounding box around the first instance is now cached.
This commit is contained in:
		
							parent
							
								
									b0c33a1fe9
								
							
						
					
					
						commit
						1e455bc065
					
				
					 5 changed files with 54 additions and 38 deletions
				
			
		|  | @ -593,6 +593,8 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) | |||
|     this->origin_translation          = rhs.origin_translation; | ||||
|     m_bounding_box                    = rhs.m_bounding_box; | ||||
|     m_bounding_box_valid              = rhs.m_bounding_box_valid; | ||||
|     m_raw_bounding_box                = rhs.m_raw_bounding_box; | ||||
|     m_raw_bounding_box_valid          = rhs.m_raw_bounding_box_valid; | ||||
|     m_raw_mesh_bounding_box           = rhs.m_raw_mesh_bounding_box; | ||||
|     m_raw_mesh_bounding_box_valid     = rhs.m_raw_mesh_bounding_box_valid; | ||||
| 
 | ||||
|  | @ -627,6 +629,8 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) | |||
|     this->origin_translation          = std::move(rhs.origin_translation); | ||||
|     m_bounding_box                    = std::move(rhs.m_bounding_box); | ||||
|     m_bounding_box_valid              = std::move(rhs.m_bounding_box_valid); | ||||
|     m_raw_bounding_box                = rhs.m_raw_bounding_box; | ||||
|     m_raw_bounding_box_valid          = rhs.m_raw_bounding_box_valid; | ||||
|     m_raw_mesh_bounding_box           = rhs.m_raw_mesh_bounding_box; | ||||
|     m_raw_mesh_bounding_box_valid     = rhs.m_raw_mesh_bounding_box_valid; | ||||
| 
 | ||||
|  | @ -859,7 +863,7 @@ TriangleMesh ModelObject::full_raw_mesh() const | |||
|     return mesh; | ||||
| } | ||||
| 
 | ||||
| BoundingBoxf3 ModelObject::raw_mesh_bounding_box() const | ||||
| const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const | ||||
| { | ||||
|     if (! m_raw_mesh_bounding_box_valid) { | ||||
|         m_raw_mesh_bounding_box_valid = true; | ||||
|  | @ -880,33 +884,36 @@ BoundingBoxf3 ModelObject::full_raw_mesh_bounding_box() const | |||
| } | ||||
| 
 | ||||
| // A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
 | ||||
| // This bounding box is only used for the actual slicing.
 | ||||
| BoundingBoxf3 ModelObject::raw_bounding_box() const | ||||
| // This bounding box is only used for the actual slicing and for layer editing UI to calculate the layers.
 | ||||
| const BoundingBoxf3& ModelObject::raw_bounding_box() const | ||||
| { | ||||
|     BoundingBoxf3 bb; | ||||
| #if ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
|     if (this->instances.empty()) | ||||
|         throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); | ||||
|     if (! m_raw_bounding_box_valid) { | ||||
|         m_raw_bounding_box_valid = true; | ||||
|         m_raw_bounding_box.reset(); | ||||
|     #if ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
|         if (this->instances.empty()) | ||||
|             throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); | ||||
| 
 | ||||
|     const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); | ||||
| #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
|     for (const ModelVolume *v : this->volumes) | ||||
|         if (v->is_model_part()) { | ||||
| #if !ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
|             if (this->instances.empty()) | ||||
|                 throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); | ||||
| #endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
|         const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); | ||||
|     #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
|         for (const ModelVolume *v : this->volumes) | ||||
|             if (v->is_model_part()) { | ||||
|     #if !ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
|                 if (this->instances.empty()) | ||||
|                     throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); | ||||
|     #endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
| 
 | ||||
| #if ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
|             bb.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix())); | ||||
| #else | ||||
|             // unmaintaned
 | ||||
|             assert(false); | ||||
|             // vol_mesh.transform(v->get_matrix());
 | ||||
|             // bb.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true));
 | ||||
| #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
|         } | ||||
|     return bb; | ||||
|     #if ENABLE_GENERIC_SUBPARTS_PLACEMENT | ||||
| 				m_raw_bounding_box.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix())); | ||||
|     #else | ||||
|                 // unmaintaned
 | ||||
|                 assert(false); | ||||
|                 // vol_mesh.transform(v->get_matrix());
 | ||||
|                 // m_raw_bounding_box_valid.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true));
 | ||||
|     #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
 | ||||
|             } | ||||
|     } | ||||
| 	return m_raw_bounding_box; | ||||
| } | ||||
| 
 | ||||
| // This returns an accurate snug bounding box of the transformed object instance, without the translation applied.
 | ||||
|  |  | |||
|  | @ -212,7 +212,7 @@ public: | |||
|     // This bounding box is approximate and not snug.
 | ||||
|     // This bounding box is being cached.
 | ||||
|     const BoundingBoxf3& bounding_box() const; | ||||
|     void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } | ||||
|     void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } | ||||
| 
 | ||||
|     // A mesh containing all transformed instances of this object.
 | ||||
|     TriangleMesh mesh() const; | ||||
|  | @ -223,11 +223,11 @@ public: | |||
|     TriangleMesh full_raw_mesh() const; | ||||
|     // A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
 | ||||
|     // This bounding box is only used for the actual slicing.
 | ||||
|     BoundingBoxf3 raw_bounding_box() const; | ||||
|     const BoundingBoxf3& raw_bounding_box() const; | ||||
|     // A snug bounding box around the transformed non-modifier object volumes.
 | ||||
|     BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; | ||||
| 	// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
 | ||||
| 	BoundingBoxf3 raw_mesh_bounding_box() const; | ||||
| 	const BoundingBoxf3& raw_mesh_bounding_box() const; | ||||
| 	// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
 | ||||
|     BoundingBoxf3 full_raw_mesh_bounding_box() const; | ||||
| 
 | ||||
|  | @ -285,7 +285,7 @@ protected: | |||
| 
 | ||||
| private: | ||||
|     ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()),  | ||||
|         m_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} | ||||
|         m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} | ||||
|     ~ModelObject(); | ||||
| 
 | ||||
|     /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ | ||||
|  | @ -304,6 +304,8 @@ private: | |||
|     // Bounding box, cached.
 | ||||
|     mutable BoundingBoxf3 m_bounding_box; | ||||
|     mutable bool          m_bounding_box_valid; | ||||
|     mutable BoundingBoxf3 m_raw_bounding_box; | ||||
|     mutable bool          m_raw_bounding_box_valid; | ||||
|     mutable BoundingBoxf3 m_raw_mesh_bounding_box; | ||||
|     mutable bool          m_raw_mesh_bounding_box_valid;     | ||||
| }; | ||||
|  |  | |||
|  | @ -132,7 +132,7 @@ public: | |||
|     // The slicing parameters are dependent on various configuration values
 | ||||
|     // (layer height, first layer height, raft settings, print nozzle diameter etc).
 | ||||
|     const SlicingParameters&    slicing_parameters() const { return m_slicing_params; } | ||||
|     static SlicingParameters    slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object); | ||||
|     static SlicingParameters    slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z); | ||||
| 
 | ||||
|     // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
 | ||||
|     std::vector<unsigned int>   object_extruders() const; | ||||
|  |  | |||
|  | @ -1370,7 +1370,7 @@ void PrintObject::update_slicing_parameters() | |||
|             this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders()); | ||||
| } | ||||
| 
 | ||||
| SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object) | ||||
| SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z) | ||||
| { | ||||
|     PrintConfig         print_config; | ||||
|     PrintObjectConfig   object_config; | ||||
|  | @ -1390,7 +1390,9 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full | |||
|                 object_extruders); | ||||
|     sort_remove_duplicates(object_extruders); | ||||
| 
 | ||||
|     return SlicingParameters::create_from_config(print_config, object_config, model_object.bounding_box().max.z(), object_extruders); | ||||
|     if (object_max_z <= 0.f) | ||||
|         object_max_z = model_object.raw_bounding_box().size().z(); | ||||
| 	return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); | ||||
| } | ||||
| 
 | ||||
| // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
 | ||||
|  |  | |||
|  | @ -255,16 +255,21 @@ void GLCanvas3D::LayersEditing::set_config(const DynamicPrintConfig* config) | |||
| void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id) | ||||
| { | ||||
|     const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr; | ||||
|     if (model_object_new == nullptr || this->last_object_id != object_id || m_model_object != model_object_new || m_model_object->id() != model_object_new->id()) { | ||||
|     // Maximum height of an object changes when the object gets rotated or scaled.
 | ||||
|     // Changing maximum height of an object will invalidate the layer heigth editing profile.
 | ||||
|     // m_model_object->raw_bounding_box() is cached, therefore it is cheap even if this method is called frequently.
 | ||||
|     float new_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->raw_bounding_box().size().z(); | ||||
| 	if (m_model_object != model_object_new || this->last_object_id != object_id || m_object_max_z != new_max_z || | ||||
|         (model_object_new != nullptr && m_model_object->id() != model_object_new->id())) { | ||||
|         m_layer_height_profile.clear(); | ||||
|         m_layer_height_profile_modified = false; | ||||
|         delete m_slicing_parameters; | ||||
|         m_slicing_parameters = nullptr; | ||||
|         m_slicing_parameters   = nullptr; | ||||
|         m_layers_texture.valid = false; | ||||
|         this->last_object_id   = object_id; | ||||
|         m_model_object         = model_object_new; | ||||
|         m_object_max_z         = new_max_z; | ||||
|     } | ||||
|     this->last_object_id = object_id; | ||||
|     m_model_object       = model_object_new; | ||||
|     m_object_max_z       = (m_model_object == nullptr) ? 0.f : m_model_object->bounding_box().max.z(); | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::LayersEditing::is_allowed() const | ||||
|  | @ -623,7 +628,7 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters() | |||
| { | ||||
| 	if (m_slicing_parameters == nullptr) { | ||||
| 		m_slicing_parameters = new SlicingParameters(); | ||||
|     	*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object); | ||||
|     	*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv