Merge pull request #43 from Prusa-Development/ys_10631
Fix for #10631 - Negative Volumes get messed up when cutting an object
This commit is contained in:
commit
a5ed864639
@ -22,6 +22,7 @@ namespace GUI {
|
|||||||
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
|
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
|
||||||
static const ColorRGBA UPPER_PART_COLOR = ColorRGBA::CYAN();
|
static const ColorRGBA UPPER_PART_COLOR = ColorRGBA::CYAN();
|
||||||
static const ColorRGBA LOWER_PART_COLOR = ColorRGBA::MAGENTA();
|
static const ColorRGBA LOWER_PART_COLOR = ColorRGBA::MAGENTA();
|
||||||
|
static const ColorRGBA MODIFIER_COLOR = ColorRGBA(0.75f, 0.75f, 0.75f, 0.5f);
|
||||||
|
|
||||||
// connector colors
|
// connector colors
|
||||||
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
|
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
|
||||||
@ -1405,7 +1406,7 @@ GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transfor
|
|||||||
m_parts.clear();
|
m_parts.clear();
|
||||||
for (const ModelVolume* volume : volumes) {
|
for (const ModelVolume* volume : volumes) {
|
||||||
assert(volume != nullptr);
|
assert(volume != nullptr);
|
||||||
m_parts.emplace_back(Part{GLModel(), MeshRaycaster(volume->mesh()), true});
|
m_parts.emplace_back(Part{GLModel(), MeshRaycaster(volume->mesh()), true, !volume->is_model_part()});
|
||||||
m_parts.back().glmodel.set_color({ 0.f, 0.f, 1.f, 1.f });
|
m_parts.back().glmodel.set_color({ 0.f, 0.f, 1.f, 1.f });
|
||||||
m_parts.back().glmodel.init_from(volume->mesh());
|
m_parts.back().glmodel.init_from(volume->mesh());
|
||||||
|
|
||||||
@ -1484,13 +1485,19 @@ void GLGizmoCut3D::PartSelection::render(const Vec3d* normal, GLModel& sphere_mo
|
|||||||
const bool is_looking_forward = normal && camera.get_dir_forward().dot(*normal) < 0.05;
|
const bool is_looking_forward = normal && camera.get_dir_forward().dot(*normal) < 0.05;
|
||||||
|
|
||||||
for (size_t id=0; id<m_parts.size(); ++id) {
|
for (size_t id=0; id<m_parts.size(); ++id) {
|
||||||
if (normal && (( is_looking_forward && m_parts[id].selected) ||
|
if (!m_parts[id].is_modifier && normal && ((is_looking_forward && m_parts[id].selected) ||
|
||||||
(!is_looking_forward && !m_parts[id].selected) ) )
|
(!is_looking_forward && !m_parts[id].selected) ) )
|
||||||
continue;
|
continue;
|
||||||
const Vec3d volume_offset = model_object()->volumes[id]->get_offset();
|
const Vec3d volume_offset = model_object()->volumes[id]->get_offset();
|
||||||
shader->set_uniform("view_model_matrix", view_inst_matrix * translation_transform(volume_offset));
|
shader->set_uniform("view_model_matrix", view_inst_matrix * translation_transform(volume_offset));
|
||||||
m_parts[id].glmodel.set_color(m_parts[id].selected ? UPPER_PART_COLOR : LOWER_PART_COLOR);
|
if (m_parts[id].is_modifier) {
|
||||||
|
glsafe(::glEnable(GL_BLEND));
|
||||||
|
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
|
}
|
||||||
|
m_parts[id].glmodel.set_color(m_parts[id].is_modifier ? MODIFIER_COLOR : (m_parts[id].selected ? UPPER_PART_COLOR : LOWER_PART_COLOR));
|
||||||
m_parts[id].glmodel.render();
|
m_parts[id].glmodel.render();
|
||||||
|
if (m_parts[id].is_modifier)
|
||||||
|
glsafe(::glDisable(GL_BLEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
@ -1551,7 +1558,7 @@ bool GLGizmoCut3D::PartSelection::is_one_object() const
|
|||||||
if (m_parts.size() < 2)
|
if (m_parts.size() < 2)
|
||||||
return true;
|
return true;
|
||||||
return std::all_of(m_parts.begin(), m_parts.end(), [this](const Part& part) {
|
return std::all_of(m_parts.begin(), m_parts.end(), [this](const Part& part) {
|
||||||
return part.selected == m_parts.front().selected;
|
return part.is_modifier || part.selected == m_parts.front().selected;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2535,29 +2542,66 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
};
|
};
|
||||||
|
|
||||||
const size_t cut_parts_cnt = m_part_selection.parts().size();
|
const size_t cut_parts_cnt = m_part_selection.parts().size();
|
||||||
|
bool has_modifiers = false;
|
||||||
|
|
||||||
|
// Distribute SolidParts to the Upper/Lower object
|
||||||
for (size_t id = 0; id < cut_parts_cnt; ++id) {
|
for (size_t id = 0; id < cut_parts_cnt; ++id) {
|
||||||
if (ModelObject* obj = (m_part_selection.parts()[id].selected ? upper : lower))
|
if (m_part_selection.parts()[id].is_modifier)
|
||||||
|
has_modifiers = true; // modifiers will be added later to the related parts
|
||||||
|
else if (ModelObject* obj = (m_part_selection.parts()[id].selected ? upper : lower))
|
||||||
obj->add_volume(*(cut_mo->volumes[id]));
|
obj->add_volume(*(cut_mo->volumes[id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_modifiers) {
|
||||||
|
// Distribute Modifiers to the Upper/Lower object
|
||||||
|
auto upper_bb = upper ? upper->instance_bounding_box(instance_idx) : BoundingBoxf3();
|
||||||
|
auto lower_bb = lower ? lower->instance_bounding_box(instance_idx) : BoundingBoxf3();
|
||||||
|
const Transform3d inst_matrix = cut_mo->instances[instance_idx]->get_transformation().get_matrix();
|
||||||
|
|
||||||
|
for (size_t id = 0; id < cut_parts_cnt; ++id)
|
||||||
|
if (m_part_selection.parts()[id].is_modifier) {
|
||||||
|
ModelVolume* vol = cut_mo->volumes[id];
|
||||||
|
auto bb = vol->mesh().transformed_bounding_box(inst_matrix * vol->get_matrix());
|
||||||
|
// Don't add modifiers which are not intersecting with solid parts
|
||||||
|
if (upper_bb.intersects(bb))
|
||||||
|
upper->add_volume(*vol);
|
||||||
|
if (lower_bb.intersects(bb))
|
||||||
|
lower->add_volume(*vol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ModelVolumePtrs& volumes = cut_mo->volumes;
|
ModelVolumePtrs& volumes = cut_mo->volumes;
|
||||||
if (volumes.size() == cut_parts_cnt)
|
if (volumes.size() == cut_parts_cnt) {
|
||||||
|
// Means that object is cut without connectors
|
||||||
|
|
||||||
|
// Just add Upper and Lower objects to cut_object_ptrs and invalidate any cut information
|
||||||
add_cut_objects(cut_object_ptrs, upper, lower);
|
add_cut_objects(cut_object_ptrs, upper, lower);
|
||||||
|
}
|
||||||
else if (volumes.size() > cut_parts_cnt) {
|
else if (volumes.size() > cut_parts_cnt) {
|
||||||
|
// Means that object is cut with connectors
|
||||||
|
|
||||||
|
// All volumes are distributed to Upper / Lower object,
|
||||||
|
// So we don’t need them anymore
|
||||||
for (size_t id = 0; id < cut_parts_cnt; id++)
|
for (size_t id = 0; id < cut_parts_cnt; id++)
|
||||||
delete *(volumes.begin() + id);
|
delete *(volumes.begin() + id);
|
||||||
volumes.erase(volumes.begin(), volumes.begin() + cut_parts_cnt);
|
volumes.erase(volumes.begin(), volumes.begin() + cut_parts_cnt);
|
||||||
|
|
||||||
|
// Perform cut just to get connectors
|
||||||
const ModelObjectPtrs cut_connectors_obj = cut_mo->cut(instance_idx, get_cut_matrix(selection), attributes);
|
const ModelObjectPtrs cut_connectors_obj = cut_mo->cut(instance_idx, get_cut_matrix(selection), attributes);
|
||||||
assert(create_dowels_as_separate_object ? cut_connectors_obj.size() >= 3 : cut_connectors_obj.size() == 2);
|
assert(create_dowels_as_separate_object ? cut_connectors_obj.size() >= 3 : cut_connectors_obj.size() == 2);
|
||||||
|
|
||||||
|
// Connectors from upper object
|
||||||
for (const ModelVolume* volume : cut_connectors_obj[0]->volumes)
|
for (const ModelVolume* volume : cut_connectors_obj[0]->volumes)
|
||||||
upper->add_volume(*volume, volume->type());
|
upper->add_volume(*volume, volume->type());
|
||||||
|
|
||||||
|
// Connectors from lower object
|
||||||
for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
|
for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
|
||||||
lower->add_volume(*volume, volume->type());
|
lower->add_volume(*volume, volume->type());
|
||||||
|
|
||||||
|
// Add Upper and Lower objects to cut_object_ptrs with saved cut information
|
||||||
add_cut_objects(cut_object_ptrs, upper, lower, false);
|
add_cut_objects(cut_object_ptrs, upper, lower, false);
|
||||||
|
|
||||||
|
// Add Dowel-connectors as separate objects to cut_object_ptrs
|
||||||
if (cut_connectors_obj.size() >= 3)
|
if (cut_connectors_obj.size() >= 3)
|
||||||
for (size_t id = 2; id < cut_connectors_obj.size(); id++)
|
for (size_t id = 2; id < cut_connectors_obj.size(); id++)
|
||||||
cut_object_ptrs.push_back(cut_connectors_obj[id]);
|
cut_object_ptrs.push_back(cut_connectors_obj[id]);
|
||||||
@ -2567,8 +2611,9 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
{
|
{
|
||||||
for (ModelObject* mo : cut_object_ptrs) {
|
for (ModelObject* mo : cut_object_ptrs) {
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
|
// Merge all SolidPart but not Connectors
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part() && !mv->is_cut_connector()) {
|
||||||
TriangleMesh m = mv->mesh();
|
TriangleMesh m = mv->mesh();
|
||||||
m.transform(mv->get_matrix());
|
m.transform(mv->get_matrix());
|
||||||
mesh.merge(m);
|
mesh.merge(m);
|
||||||
@ -2576,13 +2621,17 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
}
|
}
|
||||||
if (! mesh.empty()) {
|
if (! mesh.empty()) {
|
||||||
ModelVolume* new_volume = mo->add_volume(mesh);
|
ModelVolume* new_volume = mo->add_volume(mesh);
|
||||||
for (int i=int(mo->volumes.size())-2; i>=0; --i)
|
new_volume->name = mo->name;
|
||||||
if (mo->volumes[i]->type() == ModelVolumeType::MODEL_PART)
|
// Delete all merged SolidPart but not Connectors
|
||||||
|
for (int i=int(mo->volumes.size())-2; i>=0; --i) {
|
||||||
|
const ModelVolume* mv = mo->volumes[i];
|
||||||
|
if (mv->is_model_part() && !mv->is_cut_connector())
|
||||||
mo->delete_volume(i);
|
mo->delete_volume(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cut_object_ptrs = mo->cut(instance_idx, cut_matrix, attributes);
|
cut_object_ptrs = mo->cut(instance_idx, cut_matrix, attributes);
|
||||||
|
|
||||||
|
@ -149,6 +149,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
GLModel glmodel;
|
GLModel glmodel;
|
||||||
MeshRaycaster raycaster;
|
MeshRaycaster raycaster;
|
||||||
bool selected;
|
bool selected;
|
||||||
|
bool is_modifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
void render(const Vec3d* normal, GLModel& sphere_model);
|
void render(const Vec3d* normal, GLModel& sphere_model);
|
||||||
|
Loading…
Reference in New Issue
Block a user