Fix for #10631 - Negative Volumes get messed up when cutting an object
+ After cut by contours: * Set merged volume name as same as a object name * Merge all SolidPart but not Connectors
This commit is contained in:
parent
80b59ef769
commit
9d736ee68f
@ -22,6 +22,7 @@ namespace GUI {
|
||||
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
|
||||
static const ColorRGBA UPPER_PART_COLOR = ColorRGBA::CYAN();
|
||||
static const ColorRGBA LOWER_PART_COLOR = ColorRGBA::MAGENTA();
|
||||
static const ColorRGBA MODIFIER_COLOR = ColorRGBA(0.75f, 0.75f, 0.75f, 0.5f);
|
||||
|
||||
// connector colors
|
||||
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
|
||||
@ -1405,7 +1406,7 @@ GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transfor
|
||||
m_parts.clear();
|
||||
for (const ModelVolume* volume : volumes) {
|
||||
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.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;
|
||||
|
||||
for (size_t id=0; id<m_parts.size(); ++id) {
|
||||
if (normal && (( is_looking_forward && m_parts[id].selected) ||
|
||||
(!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) ) )
|
||||
continue;
|
||||
const Vec3d volume_offset = model_object()->volumes[id]->get_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();
|
||||
if (m_parts[id].is_modifier)
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
shader->stop_using();
|
||||
@ -1551,7 +1558,7 @@ bool GLGizmoCut3D::PartSelection::is_one_object() const
|
||||
if (m_parts.size() < 2)
|
||||
return true;
|
||||
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();
|
||||
bool has_modifiers = false;
|
||||
|
||||
// Distribute SolidParts to the Upper/Lower object
|
||||
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]));
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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++)
|
||||
delete *(volumes.begin() + id);
|
||||
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);
|
||||
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)
|
||||
upper->add_volume(*volume, volume->type());
|
||||
|
||||
// Connectors from lower object
|
||||
for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
|
||||
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 Dowel-connectors as separate objects to cut_object_ptrs
|
||||
if (cut_connectors_obj.size() >= 3)
|
||||
for (size_t id = 2; id < cut_connectors_obj.size(); 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) {
|
||||
TriangleMesh mesh;
|
||||
// Merge all SolidPart but not Connectors
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (mv->is_model_part()) {
|
||||
if (mv->is_model_part() && !mv->is_cut_connector()) {
|
||||
TriangleMesh m = mv->mesh();
|
||||
m.transform(mv->get_matrix());
|
||||
mesh.merge(m);
|
||||
@ -2576,9 +2621,13 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||
}
|
||||
if (! mesh.empty()) {
|
||||
ModelVolume* new_volume = mo->add_volume(mesh);
|
||||
for (int i=int(mo->volumes.size())-2; i>=0; --i)
|
||||
if (mo->volumes[i]->type() == ModelVolumeType::MODEL_PART)
|
||||
new_volume->name = mo->name;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
GLModel glmodel;
|
||||
MeshRaycaster raycaster;
|
||||
bool selected;
|
||||
bool is_modifier;
|
||||
};
|
||||
|
||||
void render(const Vec3d* normal, GLModel& sphere_model);
|
||||
|
Loading…
Reference in New Issue
Block a user