mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-18 12:17:54 -06:00
WIP: Refactoring of PrintRegions. It nearly compiles!
This commit is contained in:
parent
68b0d92183
commit
740773db85
8 changed files with 479 additions and 1206 deletions
|
@ -293,6 +293,7 @@ public:
|
|||
};
|
||||
|
||||
LayerRanges() = default;
|
||||
LayerRanges(const t_layer_config_ranges &in) { this->assign(in); }
|
||||
|
||||
// Convert input config ranges into continuous non-overlapping sorted vector of intervals and their configs.
|
||||
void assign(const t_layer_config_ranges &in) {
|
||||
|
@ -310,7 +311,7 @@ public:
|
|||
if (range.first.second > last_z + EPSILON) {
|
||||
const DynamicPrintConfig *cfg = &range.second.get();
|
||||
m_ranges.push_back({ t_layer_height_range(last_z, range.first.second), cfg });
|
||||
last_z = range.layer_height_range.second;
|
||||
last_z = range.first.second;
|
||||
}
|
||||
}
|
||||
if (m_ranges.empty())
|
||||
|
@ -328,13 +329,16 @@ public:
|
|||
// assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON);
|
||||
// assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON);
|
||||
if (it == m_ranges.end() ||
|
||||
std::abs(it->first.first - range.first) > EPSILON ||
|
||||
std::abs(it->first.second - range.second) > EPSILON )
|
||||
std::abs(it->layer_height_range.first - range.first) > EPSILON ||
|
||||
std::abs(it->layer_height_range.second - range.second) > EPSILON )
|
||||
return nullptr; // desired range doesn't found
|
||||
return (it == m_ranges.end()) ? nullptr : it->second;
|
||||
return (it == m_ranges.end()) ? nullptr : it->config;
|
||||
}
|
||||
|
||||
std::vector<LayerRange>::const_iterator begin() const { return m_ranges.cbegin(); }
|
||||
std::vector<LayerRange>::const_iterator end () const { return m_ranges.cend(); }
|
||||
size_t size () const { return m_ranges.size(); }
|
||||
|
||||
private:
|
||||
// Layer ranges with their config overrides and list of volumes with their snug bounding boxes in a given layer range.
|
||||
std::vector<LayerRange> m_ranges;
|
||||
|
@ -358,7 +362,7 @@ struct ModelObjectStatus {
|
|||
};
|
||||
|
||||
ModelObjectStatus(ObjectID id, Status status = Unknown) : id(id), status(status) {}
|
||||
~ModelObjectStatus() { if (print_object_regions) print_object_regions.ref_cnt_dec(); }
|
||||
~ModelObjectStatus() { if (print_object_regions) print_object_regions->ref_cnt_dec(); }
|
||||
|
||||
// Key of the set.
|
||||
ObjectID id;
|
||||
|
@ -377,11 +381,11 @@ struct ModelObjectStatus {
|
|||
|
||||
struct ModelObjectStatusDB
|
||||
{
|
||||
void add(const ModelObject &model_object, const ModelObjectStatus status) {
|
||||
void add(const ModelObject &model_object, const ModelObjectStatus::Status status) {
|
||||
db.emplace(model_object.id(), status);
|
||||
}
|
||||
|
||||
bool add_if_new(const ModelObject &model_object, const ModelObjectStatus status) {
|
||||
bool add_if_new(const ModelObject &model_object, const ModelObjectStatus::Status status) {
|
||||
auto it = db.find(ModelObjectStatus(model_object.id()));
|
||||
assert(it != db.end());
|
||||
if (it == db.end()) {
|
||||
|
@ -404,7 +408,7 @@ struct ModelObjectStatusDB
|
|||
}
|
||||
|
||||
std::set<ModelObjectStatus> db;
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintObjectStatus {
|
||||
enum Status {
|
||||
|
@ -413,36 +417,34 @@ struct PrintObjectStatus {
|
|||
Reused,
|
||||
New
|
||||
};
|
||||
|
||||
PrintObjectStatus(PrintObject *print_object, Status status = Unknown) :
|
||||
id(print_object->model_object()->id()),
|
||||
print_object(print_object),
|
||||
trafo(print_object->trafo()),
|
||||
status(status) {}
|
||||
PrintObjectStatus(ObjectID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {}
|
||||
|
||||
// ID of the ModelObject & PrintObject
|
||||
ObjectID id;
|
||||
ObjectID id;
|
||||
// Pointer to the old PrintObject
|
||||
PrintObject *print_object;
|
||||
// Trafo generated with model_object->world_matrix(true)
|
||||
Transform3d trafo;
|
||||
Status status;
|
||||
|
||||
// Search by id.
|
||||
bool operator<(const PrintObjectStatus &rhs) const { return id < rhs.id; }
|
||||
};
|
||||
|
||||
template <typename I>
|
||||
iter_pair<I> make_range(std::pair<I, I> p) {
|
||||
return iter_pair<I>(p);
|
||||
}
|
||||
|
||||
class PrintObjectStatusDB {
|
||||
public:
|
||||
using iterator = std::multiset<PrintObjectStatus>::iterator;
|
||||
using const_iterator = std::multiset<PrintObjectStatus>::const_iterator;
|
||||
|
||||
PrintObjectStatusDB(const PrintObjects &print_objects) {
|
||||
for (PrintObject *print_object : m_objects)
|
||||
db.emplace(PrintObjectStatus(print_object));
|
||||
PrintObjectStatusDB(const PrintObjectPtrs &print_objects) {
|
||||
for (PrintObject *print_object : print_objects)
|
||||
m_db.emplace(PrintObjectStatus(print_object));
|
||||
}
|
||||
|
||||
struct iterator_range : std::pair<const_iterator, const_iterator>
|
||||
|
@ -454,26 +456,26 @@ public:
|
|||
};
|
||||
|
||||
iterator_range get_range(const ModelObject &model_object) {
|
||||
return print_object_status.equal_range(PrintObjectStatus(model_object.id()));
|
||||
return m_db.equal_range(PrintObjectStatus(model_object.id()));
|
||||
}
|
||||
|
||||
iterator_range get_range(const ModelObjectStatus &model_object_status) {
|
||||
return print_object_status.equal_range(PrintObjectStatus(model_object_status.id));
|
||||
return m_db.equal_range(PrintObjectStatus(model_object_status.id));
|
||||
}
|
||||
|
||||
size_t count(const ModelObject &model_object) {
|
||||
return db.count(PrintObjectStatus(model_object.id()));
|
||||
return m_db.count(PrintObjectStatus(model_object.id()));
|
||||
}
|
||||
|
||||
std::multiset<PrintObjectStatus>::iterator begin() { return m_db.begin(); }
|
||||
std::multiset<PrintObjectStatus>::iterator end() { return m_db.end(); }
|
||||
|
||||
void clear() {
|
||||
db.clear();
|
||||
m_db.clear();
|
||||
}
|
||||
|
||||
const_iterator begin() throw() { return this->first; }
|
||||
const_iterator end() throw() { return this->second; }
|
||||
|
||||
private:
|
||||
std::multiset<PrintObjectStatus> db;
|
||||
std::multiset<PrintObjectStatus> m_db;
|
||||
};
|
||||
|
||||
static inline bool model_volume_needs_bbox(const ModelVolume &mv)
|
||||
|
@ -511,28 +513,33 @@ static inline bool trafos_differ_in_rotation_and_mirroring_by_z_only(const Trans
|
|||
return std::abs(d) > EPSILON;
|
||||
}
|
||||
|
||||
static BoundingBoxf3 transformed_its_bbox2d(const stl_triangle_vertex_indices &its, const Matrix3f &m)
|
||||
static BoundingBoxf3 transformed_its_bbox2d(const indexed_triangle_set &its, const Matrix3f &m, float offset)
|
||||
{
|
||||
BoundingBoxf3 bbox;
|
||||
for (const stl_triangle_vertex_indices &tri : its.indices)
|
||||
for (int i = 0; i < 3; ++ i)
|
||||
bbox.merge(m * its.vertices[tri(i)]);
|
||||
bbox.min.x() -= offset;
|
||||
bbox.min.y() -= offset;
|
||||
bbox.min.x() += offset;
|
||||
bbox.min.y() += offset;
|
||||
return bbox;
|
||||
}
|
||||
|
||||
static void transformed_its_bboxes_in_z_ranges(
|
||||
const stl_triangle_vertex_indices &its,
|
||||
const indexed_triangle_set &its,
|
||||
const Matrix3f &m,
|
||||
const std::vector<t_layer_height_range> &z_ranges,
|
||||
std::vector<BoundingBoxf3> &bboxes)
|
||||
std::vector<BoundingBoxf3> &bboxes,
|
||||
const float offset)
|
||||
{
|
||||
bboxes.assign(z_ranges.size(), BoundingBoxf());
|
||||
bboxes.assign(z_ranges.size(), BoundingBoxf3());
|
||||
for (const stl_triangle_vertex_indices &tri : its.indices) {
|
||||
const Vec3f pts[3] = { m * its.vertices[tri(0)], m * its.vertices[tri(1)], m * its.vertices[tri(2)] };
|
||||
for (size_t irange = 0; irange < z_ranges.size(); ++ irange) {
|
||||
t_layer_height_range &z_range = z_ranges[irange];
|
||||
BoundingBoxf3 &bbox = bboxes[irange];
|
||||
int iprev = 3;
|
||||
const t_layer_height_range &z_range = z_ranges[irange];
|
||||
BoundingBoxf3 &bbox = bboxes[irange];
|
||||
int iprev = 2;
|
||||
for (int iedge = 0; iedge < 3; ++ iedge) {
|
||||
const Vec3f *p1 = &pts[iprev];
|
||||
const Vec3f *p2 = &pts[iedge];
|
||||
|
@ -545,24 +552,24 @@ static void transformed_its_bboxes_in_z_ranges(
|
|||
if (p1->z() > z_range.second) {
|
||||
// Two intersections.
|
||||
float zspan = p2->z() - p1->z();
|
||||
float t1 = z_range.first / zspan;
|
||||
float t2 = z_range.second / zspan;
|
||||
float t1 = (z_range.first - p1->z()) / zspan;
|
||||
float t2 = (z_range.second - p1->z()) / zspan;
|
||||
Vec2f p = to_2d(*p1);
|
||||
Vec2f v(p2->x() - p1->x(), p2->y() - p1->y());
|
||||
bbox.merge(to_3d(p + v * t1, z_range.first));
|
||||
bbox.merge(to_3d(p + v * t2, z_range.second));
|
||||
bbox.merge(to_3d((p + v * t1).eval(), float(z_range.first)));
|
||||
bbox.merge(to_3d((p + v * t2).eval(), float(z_range.second)));
|
||||
} else {
|
||||
// Single intersection with the lower limit.
|
||||
float t = z_range.first / (p2->z() - p1->z());
|
||||
float t = (z_range.first - p1->z()) / (p2->z() - p1->z());
|
||||
Vec2f v(p2->x() - p1->x(), p2->y() - p1->y());
|
||||
bbox.merge(to_3d(to_2d(*p1) + v * t), z_range.first);
|
||||
bbox.merge(to_3d((to_2d(*p1) + v * t).eval(), float(z_range.first)));
|
||||
bbox.merge(*p2);
|
||||
}
|
||||
} else if (p2->z() > z_range.second) {
|
||||
// Single intersection with the upper limit.
|
||||
float t = z_range.second / (p2->z() - p1->z());
|
||||
float t = (z_range.second - p1->z()) / (p2->z() - p1->z());
|
||||
Vec2f v(p2->x() - p1->x(), p2->y() - p1->y());
|
||||
bbox.merge(to_3d(to_2d(*p1) + v * t), z_range.second);
|
||||
bbox.merge(to_3d((to_2d(*p1) + v * t).eval(), float(z_range.second)));
|
||||
bbox.merge(*p1);
|
||||
} else {
|
||||
// Both points are inside.
|
||||
|
@ -573,204 +580,132 @@ static void transformed_its_bboxes_in_z_ranges(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update from scratch.
|
||||
void update_model_object_status_layers_bboxes(
|
||||
const ModelObject &model_object,
|
||||
ModelObjectStatus &model_object_status)
|
||||
{
|
||||
assert(! model_object_status.print_instances.empty());
|
||||
assert(! model_object_status.layer_ranges.m_ranges.empty());
|
||||
|
||||
// Use the trafo of the 1st newly created PrintObject.
|
||||
model_object_status.layer_ranges.m_trafo = model_object_status.print_instances.front().trafo;
|
||||
|
||||
if (model_object_status.layer_ranges.m_ranges.size() == 1) {
|
||||
LayerRange &layer_range = model_object_status.layer_ranges.m_ranges.front();
|
||||
assert(layer_range.volumes.empty());
|
||||
layer_range.reserve(model_object.volumes.size());
|
||||
for (const ModelVolume *model_volume : model_object.volumes)
|
||||
if (model_volume_needs_bbox(*model_volume))
|
||||
layer_range.volumes.emplace_back(model_volume->id(),
|
||||
transformed_its_bbox2d(model_volume.mesh().its, trafo_for_bbox(model_object_status.layer_ranges.m_trafo, model_volume->get_matrix(false))));
|
||||
} else {
|
||||
std::vector<BoundingBoxf> bboxes;
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.reserve(model_object_status.layer_ranges.m_ranges.size());
|
||||
for (const LayerRange &layer_range : model_object_status.layer_ranges.m_ranges) {
|
||||
assert(layer_range.volumes.empty());
|
||||
t_layer_height_range r = layer_range.layer_height_range;
|
||||
r.first -= EPSILON;
|
||||
r.second += EPSILON;
|
||||
ranges.emplace_back(r);
|
||||
}
|
||||
double offset = print_object.config().xy_size_compensation();
|
||||
for (const ModelVolume *model_volume : model_object.volumes)
|
||||
if (model_volume_needs_bbox(*model_volume)) {
|
||||
transformed_its_bbox2ds_in_z_ranges(model_volume.mesh().its, trafo_for_bbox(model_object_status.layer_ranges.m_trafo, model_volume->get_matrix(false)),
|
||||
ranges, bboxes);
|
||||
size_t i = 0;
|
||||
for (LayerRange &layer_range : model_object_status.layer_ranges.m_ranges) {
|
||||
if (bboxes[i].defined) {
|
||||
bboxes.min.x() -= offset;
|
||||
bboxes.min.y() -= offset;
|
||||
bboxes.max.x() += offset;
|
||||
bboxes.max.y() += offset;
|
||||
layer_range.volumes.emplace_back(model_volume->id(), bboxes[i]);
|
||||
}
|
||||
++ i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update by reusing everything.
|
||||
void update_model_object_status_layers_bboxes(
|
||||
const ModelObject &model_object,
|
||||
PrintObject &&print_object,
|
||||
ModelObjectStatus &model_object_status)
|
||||
{
|
||||
assert(! model_object_status.print_instances.empty());
|
||||
assert(! model_object_status.layer_ranges.m_ranges.empty());
|
||||
|
||||
for (print_object.m_volumes_ranges
|
||||
}
|
||||
|
||||
// Try to extract layer ranges and snug bounding boxes from some existing PrintObject.
|
||||
void update_model_object_status_layers_bboxes(
|
||||
const ModelObject &model_object_old,
|
||||
const ModelObject &model_object_new,
|
||||
PrintObject &&print_object,
|
||||
ModelObjectStatus &model_object_status)
|
||||
{
|
||||
assert(! print_object.m_region_volumes.empty());
|
||||
|
||||
// 1) Verify that the trafo is still applicable.
|
||||
if (trafos_differ_in_rotation_and_mirroring_by_z_only(model_object_status.layer_ranges.m_trafo, model_object_status.print_instances.front().trafo)) {
|
||||
update_model_object_status_layers_bboxes(model_object_new, model_object_status);
|
||||
return;
|
||||
for (BoundingBoxf3 &bbox : bboxes) {
|
||||
bbox.min.x() -= offset;
|
||||
bbox.min.y() -= offset;
|
||||
bbox.min.x() += offset;
|
||||
bbox.min.y() += offset;
|
||||
}
|
||||
|
||||
// 2) Try to recover some of the trafos from print_object.
|
||||
|
||||
}
|
||||
|
||||
void print_objects_regions_update_volumes(PrintObjectRegions &print_object_regions, ModelVolumePtrs old_volumes, ModelVolumePtrs new_volumes)
|
||||
// Last PrintObject for this print_object_regions has been fully invalidated (deleted).
|
||||
// Keep print_object_regions, but delete those volumes, which were either removed from new_volumes, or which rotated or scaled, so they need
|
||||
// their bounding boxes to be recalculated.
|
||||
void print_objects_regions_invalidate_keep_some_volumes(PrintObjectRegions &print_object_regions, ModelVolumePtrs old_volumes, ModelVolumePtrs new_volumes)
|
||||
{
|
||||
assert(old_volumes.size() == print_object_regions.cached_volume_ids.size());
|
||||
|
||||
print_object_regions.all_regions.clear();
|
||||
|
||||
model_volumes_sort_by_id(old_volumes);
|
||||
model_volumes_sort_by_id(new_volumes);
|
||||
{
|
||||
size_t last = 0;
|
||||
size_t i_old = 0;
|
||||
for (size_t i_new = 0; i_new < new_volumes.size(); ++ i_new) {
|
||||
for (; i_old < old_volumes.size(); ++ i_old)
|
||||
if (old_volumes[i_old]->id() == new_volumes[i_new]->id())
|
||||
break;
|
||||
if (i_old == old_volumes.size())
|
||||
|
||||
size_t last = 0;
|
||||
size_t i_old = 0;
|
||||
for (size_t i_new = 0; i_new < new_volumes.size(); ++ i_new) {
|
||||
for (; i_old < old_volumes.size(); ++ i_old)
|
||||
if (old_volumes[i_old]->id() >= new_volumes[i_new]->id())
|
||||
break;
|
||||
if (old_volumes[i_old]->get_matrix().isApprox(new_volumes[i_new]->get_matrix())) {
|
||||
// Reuse the volume.
|
||||
new_volumes[last ++] = new_volumes[i_new];
|
||||
} else {
|
||||
// Don't reuse the volume.
|
||||
}
|
||||
if (i_old == old_volumes.size())
|
||||
break;
|
||||
if (old_volumes[i_old]->id() == new_volumes[i_new]->id() && old_volumes[i_old]->get_matrix().isApprox(new_volumes[i_new]->get_matrix())) {
|
||||
// Reuse the volume.
|
||||
print_object_regions.cached_volume_ids[last ++] = print_object_regions.cached_volume_ids[i_old];
|
||||
} else {
|
||||
// Don't reuse the volume.
|
||||
}
|
||||
old_volumes.clear();
|
||||
new_volumes.erase(new_volumes.begin() + last, new_volumes.end());
|
||||
}
|
||||
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_regions : print_object_regions.layer_ranges) {
|
||||
auto it = std::remove_if(layer_regions.volumes.begin(), layer_regions.volumes.end(),
|
||||
[](const PrintObjectRegions::VolumeExtents &v) { return model_volume_find_by_id(new_volumes, v.volume_id) == nullptr; });
|
||||
layer_regions.volumes.erase(it, layer_regions.volumes.end());
|
||||
layer_regions.volume_regions.clear();
|
||||
layer_regions.volume_regions.clear();
|
||||
layer_regions.painted_regions.clear();
|
||||
}
|
||||
print_object_regions.cached_volume_ids.erase(print_object_regions.cached_volume_ids.begin() + last, print_object_regions.cached_volume_ids.end());
|
||||
}
|
||||
|
||||
const BoundingBoxf3* find_volume(const PrintObjectLayerRange &layer_range, const ModelVolume &volume)
|
||||
const BoundingBoxf3* find_volume_extents(const PrintObjectRegions::LayerRangeRegions &layer_range, const ModelVolume &volume)
|
||||
{
|
||||
auto it = lower_bound_by_predicate(layer_range.volumes.begin(), layer_range.volumes.end(), [&volume](const PrintVolumeExtents &v){ return v.volume_id < volume.id(); });
|
||||
retun it != layer_range.volumes.end() && it->volume_id == volume.id() ? &it->bbox : nullptr;
|
||||
auto it = lower_bound_by_predicate(layer_range.volumes.begin(), layer_range.volumes.end(), [&volume](const PrintObjectRegions::VolumeExtents &v){ return v.volume_id < volume.id(); });
|
||||
return it != layer_range.volumes.end() && it->volume_id == volume.id() ? &it->bbox : nullptr;
|
||||
}
|
||||
|
||||
// Returns false if this object needs to be resliced.
|
||||
static bool verify_update_print_object_regions(
|
||||
ModelVolumePtrs model_volumes,
|
||||
const PrintRegionConfig &default_region_config,
|
||||
size_t num_extruders,
|
||||
const std::vector<unsigned int> &painting_extruders,
|
||||
const PrintObjectRegions &print_object_regions,
|
||||
std::function<> callback_invalidate)
|
||||
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders);
|
||||
|
||||
void print_region_ref_inc(PrintRegion &r) { ++ r.m_ref_cnt; }
|
||||
void print_region_ref_reset(PrintRegion &r) { r.m_ref_cnt = 0; }
|
||||
int print_region_ref_cnt(const PrintRegion &r) { return r.m_ref_cnt; }
|
||||
|
||||
// Verify whether the PrintRegions of a PrintObject are still valid, possibly after updating the region configs.
|
||||
// Before region configs are updated, callback_invalidate() is called to possibly stop background processing.
|
||||
// Returns false if this object needs to be resliced because regions were merged or split.
|
||||
bool verify_update_print_object_regions(
|
||||
ModelVolumePtrs model_volumes,
|
||||
const PrintRegionConfig &default_region_config,
|
||||
size_t num_extruders,
|
||||
const std::vector<unsigned int> &painting_extruders,
|
||||
PrintObjectRegions &print_object_regions,
|
||||
const std::function<void(const PrintRegionConfig&, const PrintRegionConfig&, const t_config_option_keys&)> &callback_invalidate)
|
||||
{
|
||||
// Sort by ModelVolume ID.
|
||||
std::sort(model_volumes.begin(), model_volumes.end(), [](const ModelVolume *l, const ModelVolume *r){ return l->id() < r->id(); });
|
||||
model_volumes_sort_by_id(model_volumes);
|
||||
|
||||
for (std::unique_ptr<PrintRegion> ®ion : all_regions)
|
||||
region->m_ref_cnt = 0;
|
||||
for (std::unique_ptr<PrintRegion> ®ion : print_object_regions.all_regions)
|
||||
print_region_ref_reset(*region);
|
||||
|
||||
// Verify and / or update PrintRegions produced by ModelVolumes, layer range modifiers, modifier volumes.
|
||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
||||
for (const PrintObjectRegions::VolumeRegion ®ion : layer_range.volume_regions) {
|
||||
auto it_model_volume = lower_bound_by_predicate(model_volumes.begin(), model_volumes.end(), [®ion](const ModelVolume *v){ return v->id() < region.volume_id});
|
||||
assert(it_model_volume != model_volumes.begin() && it_model_volume->id() == region.volume_id);
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
||||
for (PrintObjectRegions::VolumeRegion ®ion : layer_range.volume_regions) {
|
||||
auto it_model_volume = lower_bound_by_predicate(model_volumes.begin(), model_volumes.end(), [®ion](const ModelVolume *v){ return v->id() < region.model_volume->id(); });
|
||||
assert(it_model_volume != model_volumes.end() && (*it_model_volume)->id() == region.model_volume->id());
|
||||
PrintRegionConfig cfg = region.parent == -1 ?
|
||||
PrintObject::region_config_from_model_volume(default_region_config, region.config, *it_model_volume, num_extruders) :
|
||||
PrintObject::region_config_from_model_volume(parent_region.region->config(), nullptr, *it_model_volume, num_extruders);
|
||||
region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders) :
|
||||
region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders);
|
||||
if (cfg != region.region->config()) {
|
||||
// Region configuration changed.
|
||||
if (region.region->m_ref_cnt == 0) {
|
||||
if (print_region_ref_cnt(*region.region) == 0) {
|
||||
// Region is referenced for the first time. Just change its parameters.
|
||||
// Stop the background process before assigning new configuration to the regions.
|
||||
t_config_option_keys diff = override.region->config().diff(cfg);
|
||||
callback_invalidate(override.region->config(), cfg, diff);
|
||||
override.region->config().config_apply_only(cfg, diff, false);
|
||||
t_config_option_keys diff = region.region->config().diff(cfg);
|
||||
callback_invalidate(region.region->config(), cfg, diff);
|
||||
region.region->config_apply_only(cfg, diff, false);
|
||||
} else {
|
||||
// Region is referenced multiple times, thus the region is being split. We need to reslice.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++ region.region->m_ref_cnt;
|
||||
print_region_ref_inc(*region.region);
|
||||
}
|
||||
|
||||
// Verify and / or update PrintRegions produced by color painting.
|
||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
|
||||
size_t painted_region_idx = 0;
|
||||
for (unsigned int painted_extruder_id : painting_extruders)
|
||||
for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id) {
|
||||
const PrintVolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||
const PrintPaintedRegion ®ion = layer_range.painted_regions[painted_region_idx ++];
|
||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||
const PrintObjectRegions::PaintedRegion ®ion = layer_range.painted_regions[painted_region_idx ++];
|
||||
PrintRegionConfig cfg = parent_region.region->config();
|
||||
cfg.external_perimeter_extruder = painted_extruder_id;
|
||||
cfg.perimeter_extruder = painted_extruder_id;
|
||||
cfg.infill_extruder = painted_extruder_id;
|
||||
cfg.perimeter_extruder.value = painted_extruder_id;
|
||||
cfg.infill_extruder.value = painted_extruder_id;
|
||||
if (cfg != region.region->config()) {
|
||||
// Region configuration changed.
|
||||
if (region->m_ref_cnt == 0) {
|
||||
if (print_region_ref_cnt(*region.region) == 0) {
|
||||
// Region is referenced for the first time. Just change its parameters.
|
||||
// Stop the background process before assigning new configuration to the regions.
|
||||
t_config_option_keys diff = override.region->config().diff(cfg);
|
||||
callback_invalidate(override.region->config(), cfg, diff);
|
||||
override.region->config().config_apply_only(cfg, diff, false);
|
||||
t_config_option_keys diff = region.region->config().diff(cfg);
|
||||
callback_invalidate(region.region->config(), cfg, diff);
|
||||
region.region->config_apply_only(cfg, diff, false);
|
||||
} else {
|
||||
// Region is referenced multiple times, thus the region is being split. We need to reslice.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++ region.region->m_ref_cnt;
|
||||
print_region_ref_inc(*region.region);
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly verify, whether some regions were not merged.
|
||||
{
|
||||
std::vector<const PrintRegion*> regions;
|
||||
regions.reserve(all_regions.size());
|
||||
for (std::unique_ptr<PrintRegion> ®ion : all_regions) {
|
||||
assert(region->m_ref_cnt > 0);
|
||||
regions.emplace_back(&(*region));
|
||||
regions.reserve(print_object_regions.all_regions.size());
|
||||
for (std::unique_ptr<PrintRegion> ®ion : print_object_regions.all_regions) {
|
||||
assert(print_region_ref_cnt(*region) > 0);
|
||||
regions.emplace_back(&(*region.get()));
|
||||
}
|
||||
std::sort(regions.begin(), regions.end(), [](const PrintRegion *l, const PrintRegion *r){ return l->config_hash() < r->config_hash(); });
|
||||
for (size_t i = 0; i < regions.size(); ++ i) {
|
||||
|
@ -784,53 +719,143 @@ static bool verify_update_print_object_regions(
|
|||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update caches of volume bounding boxes.
|
||||
void update_volume_bboxes(
|
||||
std::vector<PrintObjectRegions::LayerRangeRegions> &layer_ranges,
|
||||
std::vector<ObjectID> &cached_volume_ids,
|
||||
ModelVolumePtrs model_volumes,
|
||||
const Transform3d &object_trafo,
|
||||
const float offset)
|
||||
{
|
||||
// output will be sorted by the order of model_volumes sorted by their ObjectIDs.
|
||||
model_volumes_sort_by_id(model_volumes);
|
||||
|
||||
if (layer_ranges.size() == 1) {
|
||||
PrintObjectRegions::LayerRangeRegions &layer_range = layer_ranges.front();
|
||||
std::vector<PrintObjectRegions::VolumeExtents> volumes_old(std::move(layer_range.volumes));
|
||||
layer_range.volumes.reserve(model_volumes.size());
|
||||
for (const ModelVolume *model_volume : model_volumes)
|
||||
if (model_volume_needs_bbox(*model_volume)) {
|
||||
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
||||
auto it = lower_bound_by_predicate(volumes_old.begin(), volumes_old.end(), [model_volume](PrintObjectRegions::VolumeExtents &v) { return v.volume_id == model_volume->id(); });
|
||||
if (it != volumes_old.end() && it->volume_id == model_volume->id())
|
||||
layer_range.volumes.emplace_back(*it);
|
||||
} else
|
||||
layer_range.volumes.emplace_back(model_volume->id(),
|
||||
transformed_its_bbox2d(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), offset));
|
||||
}
|
||||
} else {
|
||||
std::vector<std::vector<PrintObjectRegions::VolumeExtents>> volumes_old;
|
||||
if (cached_volume_ids.empty())
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges)
|
||||
layer_range.volumes.clear();
|
||||
else {
|
||||
volumes_old.reserve(layer_ranges.size());
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges)
|
||||
volumes_old.emplace_back(std::move(layer_range.volumes));
|
||||
}
|
||||
|
||||
std::vector<BoundingBoxf3> bboxes;
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.reserve(layer_ranges.size());
|
||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges) {
|
||||
t_layer_height_range r = layer_range.layer_height_range;
|
||||
r.first -= EPSILON;
|
||||
r.second += EPSILON;
|
||||
ranges.emplace_back(r);
|
||||
}
|
||||
for (const ModelVolume *model_volume : model_volumes)
|
||||
if (model_volume_needs_bbox(*model_volume)) {
|
||||
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges) {
|
||||
const auto &vold = volumes_old[&layer_range - layer_ranges.data()];
|
||||
auto it = lower_bound_by_predicate(vold.begin(), vold.end(), [model_volume](const PrintObjectRegions::VolumeExtents &v) { return v.volume_id == model_volume->id(); });
|
||||
if (it != vold.end() && it->volume_id == model_volume->id())
|
||||
layer_range.volumes.emplace_back(*it);
|
||||
}
|
||||
} else {
|
||||
transformed_its_bboxes_in_z_ranges(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), ranges, bboxes, offset);
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges)
|
||||
layer_range.volumes.emplace_back(model_volume->id(), bboxes[&layer_range - layer_ranges.data()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cached_volume_ids.clear();
|
||||
cached_volume_ids.reserve(model_volumes.size());
|
||||
for (const ModelVolume *v : model_volumes)
|
||||
cached_volume_ids.emplace_back(v->id());
|
||||
}
|
||||
|
||||
// Either a fresh PrintObject, or PrintObject regions were invalidated (merged, split).
|
||||
// Generate PrintRegions from scratch.
|
||||
static PrintObjectRegions generate_print_object_regions(
|
||||
static PrintObjectRegions* generate_print_object_regions(
|
||||
PrintObjectRegions *print_object_regions_old,
|
||||
const ModelVolumePtrs &model_volumes,
|
||||
const std::vector<PrintObjectLayerRange> &layer_ranges,
|
||||
const LayerRanges &model_layer_ranges,
|
||||
const PrintRegionConfig &default_region_config,
|
||||
const Transform3d &trafo,
|
||||
size_t num_extruders,
|
||||
const std::vector<unsigned int> &painting_extruders)
|
||||
{
|
||||
PrintObjectRegions out;
|
||||
auto &all_regions = all_regions;
|
||||
auto &layer_ranges_regions = layer_ranges;
|
||||
// Reuse the old object or generate a new one.
|
||||
auto out = print_object_regions_old ? std::unique_ptr<PrintObjectRegions>(print_object_regions_old) : std::make_unique<PrintObjectRegions>();
|
||||
auto &all_regions = out->all_regions;
|
||||
auto &layer_ranges_regions = out->layer_ranges;
|
||||
|
||||
layer_ranges_regions.assign(layer_ranges.size(), PrintObjectLayerRangeRegions{});
|
||||
for (PrintObjectLayerRangeRegions &lrr : layer_ranges_regions)
|
||||
lrr = layer_ranges[&lrr - layer_ranges_regions.data()];
|
||||
bool reuse_old = print_object_regions_old && !print_object_regions_old->layer_ranges.empty();
|
||||
|
||||
std::set<const PrintRegion*, > region_set;
|
||||
auto get_create_region = [®ion_set](PrintRegionConfig &&config) {
|
||||
if (reuse_old) {
|
||||
#ifndef NDEBUG
|
||||
// Verify that the old ranges match the new ranges.
|
||||
assert(model_layer_ranges.size() == layer_ranges_regions.size());
|
||||
for (const auto &range : model_layer_ranges) {
|
||||
const PrintObjectRegions::LayerRangeRegions &r = layer_ranges_regions[&range - &*(model_layer_ranges.end())];
|
||||
assert(range.layer_height_range == r.layer_height_range);
|
||||
assert(range.config == r.config);
|
||||
assert(r.volume_regions.empty());
|
||||
assert(r.painted_regions.empty());
|
||||
}
|
||||
#endif // NDEBUG
|
||||
} else {
|
||||
out->trafo_bboxes = trafo;
|
||||
layer_ranges_regions.reserve(model_layer_ranges.size());
|
||||
for (const auto &range : model_layer_ranges)
|
||||
layer_ranges_regions.push_back({ range.layer_height_range, range.config });
|
||||
}
|
||||
|
||||
update_volume_bboxes(layer_ranges_regions, out->cached_volume_ids, model_volumes, out->trafo_bboxes, std::max(0.f, float(print_object.config().xy_size_compensation()));
|
||||
|
||||
std::set<const PrintRegion*> region_set;
|
||||
auto get_create_region = [®ion_set](PrintRegionConfig &&config) -> PrintRegion* {
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
// Chain the regions in the order they are stored in the volumes list.
|
||||
for (int volume_id = 0; volume_id < int(model_volumes.size()); ++ volume_id) {
|
||||
const ModelVolume &volume = model_volumes[volume_id];
|
||||
const ModelVolume &volume = *model_volumes[volume_id];
|
||||
if (volume.type() == ModelVolumeType::MODEL_PART || volume.type() == ModelVolumeType::PARAMETER_MODIFIER) {
|
||||
for (const PrintObjectLayerRangeRegions &layer_range : layer_ranges_regions)
|
||||
if (const BoundingBoxf3 *bbox = find_volume(layer_range, volume); bbox) {
|
||||
if (volume.type() == MODEL_PART)
|
||||
layer_range.regions.push_back( {
|
||||
volume.id(), -1,
|
||||
get_create_region(PrintObject::region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders))
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
||||
if (const BoundingBoxf3 *bbox = find_volume_extents(layer_range, volume); bbox) {
|
||||
if (volume.is_model_part())
|
||||
layer_range.volume_regions.push_back({
|
||||
&volume, -1,
|
||||
get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders))
|
||||
});
|
||||
else {
|
||||
assert(volume.type() == ModelVolumeType::PARAMETER_MODIFIER);
|
||||
assert(volume.is_modifier());
|
||||
// Modifiers may be chained one over the other. Check for overlap, merge DynamicPrintConfigs.
|
||||
for (int parent_region_id = int(layer_range.regions.size()) - 1; parent_region_id >= 0; -- parent_region_id) {
|
||||
const PrintVolumeRegion &parent_region = layer_range.regions[parent_region_id];
|
||||
const BoundingBoxf3 *parent_bbox = find_volume(layer_range, parent_region.volume_id);
|
||||
for (int parent_region_id = int(layer_range.volume_regions.size()) - 1; parent_region_id >= 0; -- parent_region_id) {
|
||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||
const BoundingBoxf3 *parent_bbox = find_volume_extents(layer_range, *parent_region.model_volume);
|
||||
assert(parent_bbox != nullptr);
|
||||
if (parent_bbox->overlap(*bbox))
|
||||
layer_range.regions.push_back( {
|
||||
volume.id(), parent_region_id,
|
||||
get_create_region(PrintObject::region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders))
|
||||
layer_range.volume_regions.push_back( {
|
||||
&volume, parent_region_id,
|
||||
get_create_region(region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -839,19 +864,17 @@ static PrintObjectRegions generate_print_object_regions(
|
|||
}
|
||||
|
||||
// Finally add painting regions.
|
||||
for (const PrintObjectLayerRangeRegions &layer_range : layer_ranges_regions) {
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
||||
for (unsigned int painted_extruder_id : painting_extruders)
|
||||
for (int parent_region_id = 0; parent_region_id < int(layer_range.regions.size()); ++ parent_region_id) {
|
||||
const PrintVolumeRegion &parent_region = layer_range.regions[parent_region_id];
|
||||
for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id) {
|
||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||
PrintRegionConfig cfg = parent_region.region->config();
|
||||
cfg.external_perimeter_extruder = painted_extruder_id;
|
||||
cfg.perimeter_extruder = painted_extruder_id;
|
||||
cfg.infill_extruder = painted_extruder_id;
|
||||
cfg.perimeter_extruder.value = painted_extruder_id;
|
||||
cfg.infill_extruder.value = painted_extruder_id;
|
||||
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
return out.release();
|
||||
}
|
||||
|
||||
Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_config)
|
||||
|
@ -1021,14 +1044,14 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
// 3) Synchronize ModelObjects & PrintObjects.
|
||||
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
|
||||
ModelObject &model_object = *m_model.objects[idx_model_object];
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status.reuse(model_object));
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
|
||||
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
||||
model_object_status.print_instances = print_objects_from_model_object(*model_object_new);
|
||||
if (it_status->status == ModelObjectStatus::New)
|
||||
model_object_status.print_instances = print_objects_from_model_object(model_object_new);
|
||||
if (model_object_status.status == ModelObjectStatus::New)
|
||||
// PrintObject instances will be added in the next loop.
|
||||
continue;
|
||||
// Update the ModelObject instance, possibly invalidate the linked PrintObjects.
|
||||
assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved);
|
||||
assert(model_object_status.status == ModelObjectStatus::Old || model_object_status.status == ModelObjectStatus::Moved);
|
||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||
// Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
||||
|
@ -1036,27 +1059,31 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
||||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
||||
auto print_objects_range = print_object_status_db.get_range(&model_object);
|
||||
auto print_objects_range = print_object_status_db.get_range(model_object);
|
||||
assert(print_objects_range.begin() != print_objects_range.end());
|
||||
model_object_status.prints_objects_regions = (*print_objects_range.begin())->prints_objects_regions;
|
||||
model_object_status.prints_objects_regions->ref_cnt_inc();
|
||||
// All PrintObjects in print_objects_range shall point to the same prints_objects_regions
|
||||
model_object_status.print_object_regions = print_objects_range.begin()->print_object->m_shared_regions;
|
||||
model_object_status.print_object_regions->ref_cnt_inc();
|
||||
if (model_parts_differ || modifiers_differ ||
|
||||
model_object.origin_translation != model_object_new.origin_translation ||
|
||||
! model_object.layer_height_profile.timestamp_matches(model_object_new.layer_height_profile) ||
|
||||
layer_height_ranges_differ) {
|
||||
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
||||
model_object_status.prints_objects_regions_status =
|
||||
model_object.origin_translation == model_object_new.origin_translation && ! layer_height_ranges_differ ?
|
||||
model_object_status.print_object_regions_status =
|
||||
model_object.origin_translation == model_object_new.origin_translation && ! layer_height_ranges_differ ?
|
||||
// Drop print_objects_regions.
|
||||
ModelObjectStatus::PrintObjectRegionsStatus::Invalid :
|
||||
// Reuse bounding boxes of print_objects_regions for ModelVolumes with unmodified transformation.
|
||||
ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid;
|
||||
for (auto it : print_objects_range) {
|
||||
update_apply_status(it->print_object->invalidate_all_steps());
|
||||
const_cast<PrintObjectStatus&>(*it).status = PrintObjectStatus::Deleted;
|
||||
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
||||
update_apply_status(print_object_status.print_object->invalidate_all_steps());
|
||||
const_cast<PrintObjectStatus&>(print_object_status).status = PrintObjectStatus::Deleted;
|
||||
}
|
||||
if (model_object_status.prints_objects_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid)
|
||||
print_objects_regions_update_volumes(*model_object_status.prints_objects_regions, model_object.volumes, model_object_new.volumes);
|
||||
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid)
|
||||
// Drop everything from PrintObjectRegions but those VolumeExtents (of their particular ModelVolumes) that are still valid.
|
||||
print_objects_regions_invalidate_keep_some_volumes(*model_object_status.print_object_regions, model_object.volumes, model_object_new.volumes);
|
||||
else
|
||||
model_object_status.print_object_regions->clear();
|
||||
// Copy content of the ModelObject including its ID, do not change the parent.
|
||||
model_object.assign_copy(model_object_new);
|
||||
} else if (supports_differ || model_custom_supports_data_changed(model_object, model_object_new)) {
|
||||
|
@ -1066,8 +1093,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
update_apply_status(false);
|
||||
}
|
||||
// Invalidate just the supports step.
|
||||
for (auto it : print_objects_range)
|
||||
update_apply_status(it->print_object->invalidate_step(posSupportMaterial));
|
||||
for (const PrintObjectStatus &print_object_status : print_objects_range)
|
||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
||||
if (supports_differ) {
|
||||
// Copy just the support volumes.
|
||||
model_volume_list_update_supports(model_object, model_object_new);
|
||||
|
@ -1082,11 +1109,11 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
model_object.config.assign_config(model_object_new.config);
|
||||
if (! object_diff.empty() || object_config_changed || num_extruders_changed) {
|
||||
PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders);
|
||||
for (auto it : print_object_status_db.get_range(model_object)) {
|
||||
t_config_option_keys diff = it->print_object->config().diff(new_config);
|
||||
for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(model_object)) {
|
||||
t_config_option_keys diff = print_object_status.print_object->config().diff(new_config);
|
||||
if (! diff.empty()) {
|
||||
update_apply_status(it->print_object->invalidate_state_by_config_options(it->print_object->config(), new_config, diff));
|
||||
it->print_object->config_apply_only(new_config, diff, true);
|
||||
update_apply_status(print_object_status.print_object->invalidate_state_by_config_options(print_object_status.print_object->config(), new_config, diff));
|
||||
print_object_status.print_object->config_apply_only(new_config, diff, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1133,16 +1160,16 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
bool new_objects = false;
|
||||
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
||||
for (ModelObject *model_object : m_model.objects) {
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status.reuse(model_object));
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(*model_object));
|
||||
std::vector<const PrintObjectStatus*> old;
|
||||
old.reserve(print_object_status.count(*model_object));
|
||||
for (auto it : print_object_status.get_range(*model_object))
|
||||
if (it->status != PrintObjectStatus::Deleted)
|
||||
old.emplace_back(&(*it));
|
||||
old.reserve(print_object_status_db.count(*model_object));
|
||||
for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(*model_object))
|
||||
if (print_object_status.status != PrintObjectStatus::Deleted)
|
||||
old.emplace_back(&print_object_status);
|
||||
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
||||
// Producing the config for PrintObject on demand, caching it at print_object_last.
|
||||
const PrintObject *print_object_last = nullptr;
|
||||
auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders](PrintObject* print_object) {
|
||||
auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders](PrintObject *print_object) {
|
||||
print_object->config_apply(print_object_last ?
|
||||
print_object_last->config() :
|
||||
PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders));
|
||||
|
@ -1164,7 +1191,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); });
|
||||
// Merge the old / new lists.
|
||||
auto it_old = old.begin();
|
||||
size_t num_old = old.size();
|
||||
for (PrintObjectTrafoAndInstances &new_instances : model_object_status.print_instances) {
|
||||
for (; it_old != old.end() && transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old);
|
||||
if (it_old == old.end() || ! transform3d_equal((*it_old)->trafo, new_instances.trafo)) {
|
||||
|
@ -1174,11 +1200,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
print_objects_new.emplace_back(print_object);
|
||||
// print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
||||
new_objects = true;
|
||||
if (it_old != old.end()) {
|
||||
if (-- num_old == 0)
|
||||
update_model_object_status_layers_bboxes(*model_object, model_object_status, std::move(*old.front()->print_object));
|
||||
if (it_old != old.end())
|
||||
const_cast<PrintObjectStatus*>(*it_old)->status = PrintObjectStatus::Deleted;
|
||||
}
|
||||
} else {
|
||||
// The PrintObject already exists and the copies differ.
|
||||
PrintBase::ApplyStatus status = (*it_old)->print_object->set_instances(std::move(new_instances.instances));
|
||||
|
@ -1195,7 +1218,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
m_objects = print_objects_new;
|
||||
// Delete the PrintObjects marked as Unknown or Deleted.
|
||||
bool deleted_objects = false;
|
||||
for (auto &pos : print_object_status_db)
|
||||
for (const PrintObjectStatus &pos : print_object_status_db)
|
||||
if (pos.status == PrintObjectStatus::Unknown || pos.status == PrintObjectStatus::Deleted) {
|
||||
update_apply_status(pos.print_object->invalidate_all_steps());
|
||||
delete pos.print_object;
|
||||
|
@ -1207,25 +1230,30 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
update_apply_status(false);
|
||||
print_regions_reshuffled = true;
|
||||
}
|
||||
print_object_status.clear();
|
||||
print_object_status_db.clear();
|
||||
}
|
||||
|
||||
// All regions now have distinct settings.
|
||||
// Check whether applying the new region config defaults we would get different regions.
|
||||
// Check whether applying the new region config defaults we would get different regions,
|
||||
// update regions or create regions from scratch.
|
||||
const std::vector<unsigned int> painting_extruders;
|
||||
for (auto it_print_object = m_objects.begin(); it_print_object != m_objects.end();) {
|
||||
// Find the range of PrintObjects sharing the same associated ModelObject.
|
||||
auto it_print_object_end = m_objects.begin();
|
||||
PrintObject &print_object = *(*it_print_object);
|
||||
const ModelObject &model_object = *print_object.model_object();
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status.reuse(model_object));
|
||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
|
||||
PrintObjectRegions *print_object_regions = model_object_status.print_object_regions;
|
||||
for (++ it_print_object_end; it_print_object != m_objects.end() && (*it_print_object)->model_object() == (*it_print_object_end)->model_object(); ++ it_print_object_end)
|
||||
assert((*it_print_object_end)->m_shared_regions == nullptr || (*it_print_object_end)->m_shared_regions == print_object_regions);
|
||||
if (print_object_regions == nullptr)
|
||||
print_object_regions = new PrintObjectRegions {};
|
||||
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
|
||||
if (verify_update_print_object_regions(
|
||||
// Verify that the trafo for regions & volume bounding boxes thus for regions is still applicable.
|
||||
if (print_object_regions && ! trafos_differ_in_rotation_and_mirroring_by_z_only(print_object_regions->trafo_bboxes, model_object_status.print_instances.front().trafo))
|
||||
print_object_regions->clear();
|
||||
if (print_object_regions &&
|
||||
verify_update_print_object_regions(
|
||||
print_object.model_object()->volumes,
|
||||
m_default_region_config,
|
||||
num_extruders,
|
||||
|
@ -1237,44 +1265,38 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
update_apply_status(print_object->invalidate_state_by_config_options(region.config(), region_config, diff));
|
||||
region.config_apply_only(region_config, diff, false);
|
||||
})) {
|
||||
// Regions are valid, assign them to the other PrintObjects.
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++ it)
|
||||
if ((*it)->m_shared_regions == nullptr) {
|
||||
(*it)->m_shared_regions = print_object_regions;
|
||||
print_object_regions->ref_cnt_inc();
|
||||
}
|
||||
// Regions are valid, just keep them.
|
||||
} else {
|
||||
// Regions were reshuffled.
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++ it)
|
||||
if ((*it)->m_shared_regions != nullptr) {
|
||||
assert(print_object_regions == (*it)->m_shared_regions);
|
||||
update_apply_status((*it)->invalidate_all_steps());
|
||||
(*it)->m_shared_regions = nullptr;
|
||||
print_object_regions->ref_cnt_dec();
|
||||
}
|
||||
// At least reuse layer ranges and bounding boxes of ModelVolumes.
|
||||
model_object_status.print_object_regions_status = ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid;
|
||||
print_regions_reshuffled = true;
|
||||
}
|
||||
}
|
||||
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid) {
|
||||
// Reuse layer ranges and bounding boxes of ModelVolumes.
|
||||
} else {
|
||||
assert(model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Invalid);
|
||||
// Layer ranges with their associated configurations.
|
||||
LayerRanges layer_ranges;
|
||||
layer_ranges.assign(print_object.model_object()->layer_config_ranges);
|
||||
print_object_regions = new PrintObjectRegions(generate_print_object_regions(
|
||||
if (print_object_regions == nullptr || model_object_status.print_object_regions_status != ModelObjectStatus::PrintObjectRegionsStatus::Valid) {
|
||||
// Layer ranges with their associated configurations. Remove overlaps between the ranges
|
||||
// and create the regions from scratch.
|
||||
print_object_regions = generate_print_object_regions(
|
||||
print_object_regions,
|
||||
print_object.model_object()->volumes,
|
||||
layer_ranges,
|
||||
LayerRanges(print_object.model_object()->layer_config_ranges),
|
||||
model_object_status.print_instances.front().trafo,
|
||||
m_default_region_config,
|
||||
num_extruders,
|
||||
painting_extruders));
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++ it) {
|
||||
painting_extruders);
|
||||
}
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
||||
if ((*it)->m_shared_regions)
|
||||
assert((*it)->m_shared_regions == print_object_regions);
|
||||
else {
|
||||
(*it)->m_shared_regions = print_object_regions;
|
||||
print_object_regions->ref_cnt_inc();
|
||||
}
|
||||
}
|
||||
it_print_object = it_print_object_end;
|
||||
}
|
||||
|
||||
|
@ -1284,7 +1306,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
std::set<const PrintRegion*, cmp> region_set;
|
||||
m_print_regions.clear();
|
||||
PrintObjectRegions *print_object_regions = nullptr;
|
||||
for (PrintObject *print_object : m_objects) {
|
||||
for (PrintObject *print_object : m_objects)
|
||||
if (print_object_regions != print_object->m_shared_regions) {
|
||||
print_object_regions = print_object->m_shared_regions;
|
||||
for (std::unique_ptr<Slic3r::PrintRegion> &print_region : print_object_regions->all_regions)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue