mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-15 18:58:00 -06:00
Only consider part above plate when checking for object outside (#8456)
Fix #8218 Before:  After:   Note: there is still an issue that you still cannot slice if object below plate overlaps exclusion area. It won't be easy to fix and also will be computational costy, so I won't try to solve this in this PR yet. 
This commit is contained in:
commit
61efef9e88
4 changed files with 63 additions and 40 deletions
|
@ -2211,48 +2211,12 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
|
||||||
unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume &build_volume)
|
unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume &build_volume)
|
||||||
{
|
{
|
||||||
unsigned int num_printable = 0;
|
unsigned int num_printable = 0;
|
||||||
enum {
|
|
||||||
INSIDE = 1,
|
|
||||||
OUTSIDE = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
//BBS: add logs for build_volume
|
//BBS: add logs for build_volume
|
||||||
//const BoundingBoxf3& print_volume = build_volume.bounding_volume();
|
//const BoundingBoxf3& print_volume = build_volume.bounding_volume();
|
||||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", print_volume {%1%, %2%, %3%} to {%4%, %5%, %6%}")\
|
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", print_volume {%1%, %2%, %3%} to {%4%, %5%, %6%}")\
|
||||||
// %print_volume.min.x() %print_volume.min.y() %print_volume.min.z()%print_volume.max.x() %print_volume.max.y() %print_volume.max.z();
|
// %print_volume.min.x() %print_volume.min.y() %print_volume.min.z()%print_volume.max.x() %print_volume.max.y() %print_volume.max.z();
|
||||||
for (ModelInstance* model_instance : this->instances) {
|
for (ModelInstance* model_instance : this->instances) {
|
||||||
unsigned int inside_outside = 0;
|
if (model_instance->update_print_volume_state(build_volume) == ModelInstancePVS_Inside) {
|
||||||
for (const ModelVolume *vol : this->volumes) {
|
|
||||||
if (vol->is_model_part()) {
|
|
||||||
//BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object)
|
|
||||||
BoundingBoxf3 bb = vol->get_convex_hull().bounding_box();
|
|
||||||
Vec3d size = bb.size();
|
|
||||||
if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) {
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->name %vol->name\
|
|
||||||
%bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix();
|
|
||||||
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
|
|
||||||
if (state == BuildVolume::ObjectState::Inside)
|
|
||||||
// Volume is completely inside.
|
|
||||||
inside_outside |= INSIDE;
|
|
||||||
else if (state == BuildVolume::ObjectState::Outside)
|
|
||||||
// Volume is completely outside.
|
|
||||||
inside_outside |= OUTSIDE;
|
|
||||||
else if (state == BuildVolume::ObjectState::Below) {
|
|
||||||
// Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable
|
|
||||||
// if some of its volumes are still inside the build volume.
|
|
||||||
} else
|
|
||||||
// Volume colliding with the build volume.
|
|
||||||
inside_outside |= INSIDE | OUTSIDE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model_instance->print_volume_state =
|
|
||||||
inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
|
|
||||||
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
|
|
||||||
if (inside_outside == INSIDE) {
|
|
||||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s instance inside print volum")%this->name;
|
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s instance inside print volum")%this->name;
|
||||||
++num_printable;
|
++num_printable;
|
||||||
}
|
}
|
||||||
|
@ -3280,6 +3244,46 @@ void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConf
|
||||||
ret.extrude_ids.push_back(1);
|
ret.extrude_ids.push_back(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const BuildVolume& build_volume) const
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
INSIDE = 1,
|
||||||
|
OUTSIDE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int inside_outside = 0;
|
||||||
|
for (const ModelVolume* vol : this->object->volumes) {
|
||||||
|
if (vol->is_model_part()) {
|
||||||
|
//BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object)
|
||||||
|
BoundingBoxf3 bb = vol->get_convex_hull().bounding_box();
|
||||||
|
Vec3d size = bb.size();
|
||||||
|
if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->object->name %vol->name\
|
||||||
|
%bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Transform3d matrix = this->get_matrix() * vol->get_matrix();
|
||||||
|
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
|
||||||
|
if (state == BuildVolume::ObjectState::Inside)
|
||||||
|
// Volume is completely inside.
|
||||||
|
inside_outside |= INSIDE;
|
||||||
|
else if (state == BuildVolume::ObjectState::Outside)
|
||||||
|
// Volume is completely outside.
|
||||||
|
inside_outside |= OUTSIDE;
|
||||||
|
else if (state == BuildVolume::ObjectState::Below) {
|
||||||
|
// Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable
|
||||||
|
// if some of its volumes are still inside the build volume.
|
||||||
|
} else
|
||||||
|
// Volume colliding with the build volume.
|
||||||
|
inside_outside |= INSIDE | OUTSIDE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
|
||||||
|
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
|
||||||
|
}
|
||||||
|
|
||||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||||
{
|
{
|
||||||
TriangleSelector selector(mv.mesh());
|
TriangleSelector selector(mv.mesh());
|
||||||
|
|
|
@ -1325,6 +1325,8 @@ public:
|
||||||
this->object->invalidate_bounding_box();
|
this->object->invalidate_bounding_box();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelInstanceEPrintVolumeState calc_print_volume_state(const BuildVolume& build_volume) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Print;
|
friend class Print;
|
||||||
friend class SLAPrint;
|
friend class SLAPrint;
|
||||||
|
@ -1334,6 +1336,12 @@ protected:
|
||||||
explicit ModelInstance(const ModelInstance &rhs) = default;
|
explicit ModelInstance(const ModelInstance &rhs) = default;
|
||||||
void set_model_object(ModelObject *model_object) { object = model_object; }
|
void set_model_object(ModelObject *model_object) { object = model_object; }
|
||||||
|
|
||||||
|
ModelInstanceEPrintVolumeState update_print_volume_state(const BuildVolume& build_volume)
|
||||||
|
{
|
||||||
|
print_volume_state = calc_print_volume_state(build_volume);
|
||||||
|
return print_volume_state;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Parent object, owning this instance.
|
// Parent object, owning this instance.
|
||||||
ModelObject* object;
|
ModelObject* object;
|
||||||
|
|
|
@ -1077,14 +1077,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||||
{
|
{
|
||||||
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
|
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
|
||||||
BuildVolume::ObjectState state;
|
BuildVolume::ObjectState state;
|
||||||
const BoundingBoxf3& bb = volume_bbox(*volume);
|
|
||||||
if (volume_below(*volume))
|
if (volume_below(*volume))
|
||||||
state = BuildVolume::ObjectState::Below;
|
state = BuildVolume::ObjectState::Below;
|
||||||
else {
|
else {
|
||||||
switch (plate_build_volume.type()) {
|
switch (plate_build_volume.type()) {
|
||||||
case BuildVolume_Type::Rectangle:
|
case BuildVolume_Type::Rectangle: {
|
||||||
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
|
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
|
||||||
|
const BoundingBoxf3& bb = volume_bbox(*volume);
|
||||||
state = plate_build_volume.volume_state_bbox(bb);
|
state = plate_build_volume.volume_state_bbox(bb);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BuildVolume_Type::Circle:
|
case BuildVolume_Type::Circle:
|
||||||
case BuildVolume_Type::Convex:
|
case BuildVolume_Type::Convex:
|
||||||
|
|
|
@ -2074,6 +2074,16 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
||||||
if (instance_box.max.z() > plate_box.min.z())
|
if (instance_box.max.z() > plate_box.min.z())
|
||||||
plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking
|
plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking
|
||||||
|
|
||||||
|
if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
|
||||||
|
// Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
|
||||||
|
if (plate_box.intersects(instance_box)) {
|
||||||
|
// TODO: FIXME: this does not take exclusion area into account
|
||||||
|
const BuildVolume build_volume(get_shape(), m_plater->build_volume().printable_height());
|
||||||
|
const auto state = instance->calc_print_volume_state(build_volume);
|
||||||
|
outside = state == ModelInstancePVS_Partly_Outside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
if (plate_box.contains(instance_box))
|
if (plate_box.contains(instance_box))
|
||||||
{
|
{
|
||||||
if (m_exclude_bounding_box.size() > 0)
|
if (m_exclude_bounding_box.size() > 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue