mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
Fix some rotation-related issues (#3890)
* Fix issue with max_z after rotation * Don't use `object.bounding_box()`, use `bounding_box_exact()` instead. * Fix auto-orient --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
d1eea4c677
commit
73ab032e82
12 changed files with 186 additions and 137 deletions
|
@ -380,7 +380,7 @@ public:
|
|||
// The pairs of <z, layer_height> are packed into a 1D array.
|
||||
LayerHeightProfile layer_height_profile;
|
||||
// Whether or not this object is printable
|
||||
bool printable;
|
||||
bool printable { true };
|
||||
|
||||
// This vector holds position of selected support points for SLA. The data are
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
|
@ -444,11 +444,22 @@ public:
|
|||
void delete_last_instance();
|
||||
void clear_instances();
|
||||
|
||||
// Returns the bounding box of the transformed instances.
|
||||
// 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_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; }
|
||||
// Returns the bounding box of the transformed instances. This bounding box is approximate and not snug, it is being cached.
|
||||
const BoundingBoxf3& bounding_box_approx() const;
|
||||
// Returns an exact bounding box of the transformed instances. The result it is being cached.
|
||||
const BoundingBoxf3& bounding_box_exact() const;
|
||||
// Return minimum / maximum of a printable object transformed into the world coordinate system.
|
||||
// All instances share the same min / max Z.
|
||||
double min_z() const;
|
||||
double max_z() const;
|
||||
|
||||
void invalidate_bounding_box() {
|
||||
m_bounding_box_approx_valid = false;
|
||||
m_bounding_box_exact_valid = false;
|
||||
m_min_max_z_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;
|
||||
|
@ -521,8 +532,6 @@ public:
|
|||
// Rotation and mirroring is being baked in. In case the instance scaling was non-uniform, it is baked in as well.
|
||||
void bake_xy_rotation_into_meshes(size_t instance_idx);
|
||||
|
||||
double get_min_z() const;
|
||||
double get_max_z() const;
|
||||
double get_instance_min_z(size_t instance_idx) const;
|
||||
double get_instance_max_z(size_t instance_idx) const;
|
||||
|
||||
|
@ -543,14 +552,13 @@ public:
|
|||
private:
|
||||
friend class Model;
|
||||
// This constructor assigns new ID to this ModelObject and its config.
|
||||
explicit ModelObject(Model* model) : m_model(model), printable(true), origin_translation(Vec3d::Zero()),
|
||||
m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false)
|
||||
explicit ModelObject(Model* model) : m_model(model), origin_translation(Vec3d::Zero())
|
||||
{
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->layer_height_profile.id().valid());
|
||||
}
|
||||
explicit ModelObject(int) : ObjectBase(-1), config(-1), layer_height_profile(-1), m_model(nullptr), printable(true), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false)
|
||||
explicit ModelObject(int) : ObjectBase(-1), config(-1), layer_height_profile(-1), origin_translation(Vec3d::Zero())
|
||||
{
|
||||
assert(this->id().invalid());
|
||||
assert(this->config.id().invalid());
|
||||
|
@ -628,15 +636,31 @@ private:
|
|||
OBJECTBASE_DERIVED_COPY_MOVE_CLONE(ModelObject)
|
||||
|
||||
// Parent object, owning this ModelObject. Set to nullptr here, so the macros above will have it initialized.
|
||||
Model *m_model = nullptr;
|
||||
Model *m_model { nullptr };
|
||||
|
||||
// Bounding box, cached.
|
||||
mutable BoundingBoxf3 m_bounding_box;
|
||||
mutable bool m_bounding_box_valid;
|
||||
mutable BoundingBoxf3 m_bounding_box_approx;
|
||||
mutable bool m_bounding_box_approx_valid { false };
|
||||
mutable BoundingBoxf3 m_bounding_box_exact;
|
||||
mutable bool m_bounding_box_exact_valid { false };
|
||||
mutable bool m_min_max_z_valid { false };
|
||||
mutable BoundingBoxf3 m_raw_bounding_box;
|
||||
mutable bool m_raw_bounding_box_valid;
|
||||
mutable bool m_raw_bounding_box_valid { false };
|
||||
mutable BoundingBoxf3 m_raw_mesh_bounding_box;
|
||||
mutable bool m_raw_mesh_bounding_box_valid;
|
||||
mutable bool m_raw_mesh_bounding_box_valid { false };
|
||||
|
||||
// Only use this method if now the source and dest ModelObjects are equal, for example they were synchronized by Print::apply().
|
||||
void copy_transformation_caches(const ModelObject &src) {
|
||||
m_bounding_box_approx = src.m_bounding_box_approx;
|
||||
m_bounding_box_approx_valid = src.m_bounding_box_approx_valid;
|
||||
m_bounding_box_exact = src.m_bounding_box_exact;
|
||||
m_bounding_box_exact_valid = src.m_bounding_box_exact_valid;
|
||||
m_min_max_z_valid = src.m_min_max_z_valid;
|
||||
m_raw_bounding_box = src.m_raw_bounding_box;
|
||||
m_raw_bounding_box_valid = src.m_raw_bounding_box_valid;
|
||||
m_raw_mesh_bounding_box = src.m_raw_mesh_bounding_box;
|
||||
m_raw_mesh_bounding_box_valid = src.m_raw_mesh_bounding_box_valid;
|
||||
}
|
||||
|
||||
// Called by Print::apply() to set the model pointer after making a copy.
|
||||
friend class Print;
|
||||
|
@ -648,8 +672,7 @@ private:
|
|||
friend class UndoRedo::StackImpl;
|
||||
// Used for deserialization -> Don't allocate any IDs for the ModelObject or its config.
|
||||
ModelObject() :
|
||||
ObjectBase(-1), config(-1), layer_height_profile(-1),
|
||||
m_model(nullptr), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {
|
||||
ObjectBase(-1), config(-1), layer_height_profile(-1) {
|
||||
assert(this->id().invalid());
|
||||
assert(this->config.id().invalid());
|
||||
assert(this->layer_height_profile.id().invalid());
|
||||
|
@ -660,7 +683,9 @@ private:
|
|||
Internal::StaticSerializationWrapper<LayerHeightProfile const> layer_heigth_profile_wrapper(layer_height_profile);
|
||||
ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation,
|
||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
m_bounding_box_approx, m_bounding_box_approx_valid,
|
||||
m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid,
|
||||
m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
cut_connectors, cut_id);
|
||||
}
|
||||
template<class Archive> void load(Archive& ar) {
|
||||
|
@ -671,7 +696,9 @@ private:
|
|||
SaveObjectGaurd gaurd(*this);
|
||||
ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation,
|
||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
m_bounding_box_approx, m_bounding_box_approx_valid,
|
||||
m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid,
|
||||
m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
cut_connectors, cut_id);
|
||||
std::vector<ObjectID> volume_ids2;
|
||||
std::transform(volumes.begin(), volumes.end(), std::back_inserter(volume_ids2), std::mem_fn(&ObjectBase::id));
|
||||
|
@ -682,6 +709,9 @@ private:
|
|||
|
||||
// Called by Print::validate() from the UI thread.
|
||||
unsigned int update_instances_print_volume_state(const BuildVolume &build_volume);
|
||||
|
||||
// Called by min_z(), max_z()
|
||||
void update_min_max_z();
|
||||
};
|
||||
|
||||
enum class EnforcerBlockerType : int8_t {
|
||||
|
@ -1268,10 +1298,8 @@ public:
|
|||
|
||||
// BBS
|
||||
void rotate(Matrix3d rotation_matrix) {
|
||||
auto R = m_transformation.get_rotation_matrix().matrix().block<3, 3>(0, 0);
|
||||
auto R_new = rotation_matrix * R;
|
||||
auto euler_angles = Geometry::extract_euler_angles(R_new);
|
||||
set_rotation(euler_angles);
|
||||
const Geometry::Transformation& old_inst_trafo = get_transformation();
|
||||
set_transformation(Geometry::Transformation{old_inst_trafo.get_offset_matrix() * rotation_matrix * old_inst_trafo.get_matrix_no_offset()});
|
||||
}
|
||||
|
||||
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
||||
|
@ -1574,8 +1602,12 @@ public:
|
|||
void delete_material(t_model_material_id material_id);
|
||||
void clear_materials();
|
||||
bool add_default_instances();
|
||||
// Returns approximate axis aligned bounding box of this model
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
// Returns approximate axis aligned bounding box of this model.
|
||||
BoundingBoxf3 bounding_box_approx() const;
|
||||
// Returns exact axis aligned bounding box of this model.
|
||||
BoundingBoxf3 bounding_box_exact() const;
|
||||
// Return maximum height of all printable objects.
|
||||
double max_z() const;
|
||||
// Set the print_volume_state of PrintObject::instances,
|
||||
// return total number of printable objects.
|
||||
unsigned int update_print_volume_state(const BuildVolume &build_volume);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue