Merge remote-tracking branch 'upstream/main' into libvgcode
# Conflicts: # src/libslic3r/GCode/GCodeProcessor.cpp # src/libslic3r/GCode/GCodeProcessor.hpp # src/slic3r/CMakeLists.txt # src/slic3r/GUI/GCodeViewer.cpp # src/slic3r/GUI/GCodeViewer.hpp # src/slic3r/GUI/GLCanvas3D.cpp # src/slic3r/GUI/GLCanvas3D.hpp # src/slic3r/GUI/GUI_Preview.cpp
This commit is contained in:
@@ -63,25 +63,6 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char
|
||||
}
|
||||
#endif // HAS_GLSAFE
|
||||
|
||||
// BBS
|
||||
std::vector<Slic3r::ColorRGBA> get_extruders_colors()
|
||||
{
|
||||
unsigned char rgba_color[4] = {};
|
||||
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
std::vector<Slic3r::ColorRGBA> colors_out(colors.size());
|
||||
for (const std::string &color : colors) {
|
||||
Slic3r::GUI::BitmapCache::parse_color4(color, rgba_color);
|
||||
size_t color_idx = &color - &colors.front();
|
||||
colors_out[color_idx] = {
|
||||
float(rgba_color[0]) / 255.f,
|
||||
float(rgba_color[1]) / 255.f,
|
||||
float(rgba_color[2]) / 255.f,
|
||||
float(rgba_color[3]) / 255.f,
|
||||
};
|
||||
}
|
||||
return colors_out;
|
||||
}
|
||||
|
||||
float FullyTransparentMaterialThreshold = 0.1f;
|
||||
float FullTransparentModdifiedToFixAlpha = 0.3f;
|
||||
// Be careful changing this value because it could break thumbnail color due to rounding error!
|
||||
@@ -224,6 +205,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
|
||||
, partly_inside(false)
|
||||
, hover(HS_None)
|
||||
, is_modifier(false)
|
||||
, slice_error(false)
|
||||
, is_wipe_tower(false)
|
||||
, is_extrusion_path(false)
|
||||
, force_transparent(false)
|
||||
@@ -421,7 +403,7 @@ void GLVolume::render()
|
||||
return;
|
||||
|
||||
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
||||
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||
std::vector<ColorRGBA> colors = GUI::wxGetApp().plater()->get_extruders_colors();
|
||||
|
||||
simple_render(shader, model_objects, colors);
|
||||
}
|
||||
@@ -437,7 +419,7 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size)
|
||||
return;
|
||||
|
||||
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
||||
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||
std::vector<ColorRGBA> colors = GUI::wxGetApp().plater()->get_extruders_colors();
|
||||
|
||||
const GUI::OpenGLManager::EFramebufferType framebuffers_type = GUI::OpenGLManager::get_framebuffers_type();
|
||||
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Unknown) {
|
||||
@@ -798,7 +780,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
if (height == 0.0f)
|
||||
height = 0.1f;
|
||||
|
||||
std::vector<ColorRGBA> extruder_colors = get_extruders_colors();
|
||||
std::vector<ColorRGBA> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors();
|
||||
std::vector<ColorRGBA> colors;
|
||||
GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list();
|
||||
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true);
|
||||
@@ -834,6 +816,48 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
return int(volumes.size() - 1);
|
||||
}
|
||||
|
||||
int GLVolumeCollection::load_real_wipe_tower_preview(
|
||||
int obj_idx, float pos_x, float pos_y, const TriangleMesh& wt_mesh,const TriangleMesh &brim_mesh,bool render_brim, float rotation_angle, bool size_unknown, bool opengl_initialized)
|
||||
{
|
||||
int plate_idx = obj_idx - 1000;
|
||||
if (wt_mesh.its.vertices.empty()) return int(this->volumes.size() - 1);
|
||||
|
||||
std::vector<Slic3r::ColorRGBA> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors();
|
||||
GUI::PartPlateList &ppl = GUI::wxGetApp().plater()->get_partplate_list();
|
||||
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true);
|
||||
std::vector<Slic3r::ColorRGBA> colors;
|
||||
if (!plate_extruders.empty()) {
|
||||
if (plate_extruders.front() <= extruder_colors.size())
|
||||
colors.push_back(extruder_colors[plate_extruders.front() - 1]);
|
||||
else
|
||||
colors.push_back(extruder_colors[0]);
|
||||
}
|
||||
if (colors.empty()) return int(this->volumes.size() - 1);
|
||||
volumes.emplace_back(new GLWipeTowerVolume({colors}));
|
||||
GLWipeTowerVolume &v = *dynamic_cast<GLWipeTowerVolume *>(volumes.back());
|
||||
auto mesh = wt_mesh;
|
||||
if (render_brim) {
|
||||
mesh.merge(brim_mesh);
|
||||
}
|
||||
if (!colors.empty()) {
|
||||
v.model_per_colors.resize(1);
|
||||
v.model_per_colors[0].init_from(mesh);
|
||||
}
|
||||
TriangleMesh wipe_tower_shell = mesh.convex_hull_3d();
|
||||
v.model.init_from(wipe_tower_shell);
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(wipe_tower_shell));
|
||||
v.set_convex_hull(wipe_tower_shell);
|
||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
|
||||
v.geometry_id.first = 0;
|
||||
v.geometry_id.second = wipe_tower_instance_id().id + (obj_idx - 1000);
|
||||
v.is_wipe_tower = true;
|
||||
v.shader_outside_printer_detection_enabled = !size_unknown;
|
||||
return int(volumes.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
GLVolume* GLVolumeCollection::new_toolpath_volume(const ColorRGBA& rgba)
|
||||
{
|
||||
GLVolume* out = new_nontoolpath_volume(rgba);
|
||||
@@ -1003,7 +1027,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||
#endif // ENABLE_ENVIRONMENT_MAP
|
||||
glcheck();
|
||||
|
||||
volume.first->model.set_color(volume.first->render_color);
|
||||
auto red_color = ColorRGBA{1.0f, 0.0f, 0.0f, 1.0f};//slice_error
|
||||
volume.first->model.set_color(volume.first->slice_error ? red_color : volume.first->render_color);
|
||||
const Transform3d model_matrix = volume.first->world_matrix();
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
shader->set_uniform("projection_matrix", projection_matrix);
|
||||
@@ -1049,7 +1074,41 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const
|
||||
bool GLVolumeCollection::check_wipe_tower_outside_state(const Slic3r::BuildVolume &build_volume, int plate_id) const
|
||||
{
|
||||
for (GLVolume *volume : this->volumes) {
|
||||
if (volume->is_wipe_tower) {
|
||||
int wipe_tower_plate_id = volume->composite_id.object_id - 1000;
|
||||
if (wipe_tower_plate_id != plate_id)
|
||||
continue;
|
||||
const std::vector<Vec2d>& printable_area = build_volume.printable_area();
|
||||
Polygon printable_poly = Polygon::new_scale(printable_area);
|
||||
|
||||
// multi-extruder
|
||||
Polygons extruder_polys;
|
||||
const std::vector<std::vector<Vec2d>> & extruder_areas = build_volume.extruder_areas();
|
||||
if (!extruder_areas.empty()) {
|
||||
for (size_t i = 0; i < extruder_areas.size(); ++i) {
|
||||
extruder_polys.emplace_back(Polygon::new_scale(extruder_areas[i]));
|
||||
}
|
||||
extruder_polys = union_(extruder_polys);
|
||||
if (extruder_polys.empty())
|
||||
return false;
|
||||
|
||||
printable_poly = extruder_polys[0];
|
||||
}
|
||||
|
||||
const BoundingBoxf3 &bbox = volume->transformed_convex_hull_bounding_box();
|
||||
Polygon wipe_tower_polygon = bbox.polygon(true);
|
||||
|
||||
Polygons diff_res = diff(wipe_tower_polygon, printable_poly);
|
||||
return diff_res.empty();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults* object_results) const
|
||||
{
|
||||
if (GUI::wxGetApp().plater() == NULL)
|
||||
{
|
||||
@@ -1071,19 +1130,25 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||
auto volume_convex_mesh = [volume_sinking, &model](GLVolume& volume) -> const TriangleMesh&
|
||||
{ return volume_sinking(volume) ? model.objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); };
|
||||
|
||||
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
|
||||
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Fully_Outside;
|
||||
bool contained_min_one = false;
|
||||
|
||||
//BBS: add instance judge logic, besides to original volume judge logic
|
||||
std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
|
||||
//std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
|
||||
|
||||
GUI::PartPlate* curr_plate = GUI::wxGetApp().plater()->get_partplate_list().get_selected_plate();
|
||||
const Pointfs& pp_bed_shape = curr_plate->get_shape();
|
||||
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height());
|
||||
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height(), build_volume.extruder_areas(), build_volume.extruder_heights());
|
||||
const std::vector<BoundingBoxf3>& exclude_areas = curr_plate->get_exclude_areas();
|
||||
|
||||
std::map<ModelObject*, std::map<int, std::set<int>>> objects_unprintable_filaments;
|
||||
int extruder_count = build_volume.get_extruder_area_count();
|
||||
std::vector<std::set<int>> unprintable_filament_ids(extruder_count, std::set<int>());
|
||||
std::set<ModelObject*> partly_objects_set;
|
||||
const ModelObjectPtrs &model_objects = model.objects;
|
||||
for (GLVolume* volume : this->volumes)
|
||||
{
|
||||
std::vector<bool> inside_extruders;
|
||||
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
|
||||
BuildVolume::ObjectState state;
|
||||
if (volume_below(*volume))
|
||||
@@ -1094,38 +1159,69 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||
//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);
|
||||
}
|
||||
if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1))
|
||||
{
|
||||
state = plate_build_volume.check_volume_bbox_state_with_extruder_areas(bb, inside_extruders);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BuildVolume_Type::Circle:
|
||||
case BuildVolume_Type::Convex:
|
||||
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||
case BuildVolume_Type::Custom:
|
||||
state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
|
||||
{
|
||||
const indexed_triangle_set& convex_mesh_it = volume_convex_mesh(*volume).its;
|
||||
const Transform3f trafo = volume->world_matrix().cast<float>();
|
||||
state = plate_build_volume.object_state(convex_mesh_it, trafo, volume_sinking(*volume));
|
||||
if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1))
|
||||
{
|
||||
state = plate_build_volume.check_object_state_with_extruder_areas(convex_mesh_it, trafo, inside_extruders);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignore, don't produce any collision.
|
||||
state = BuildVolume::ObjectState::Inside;
|
||||
break;
|
||||
}
|
||||
assert(state != BuildVolume::ObjectState::Below);
|
||||
|
||||
if (state == BuildVolume::ObjectState::Limited) {
|
||||
//unprintable_filament_ids.resize(inside_extruders.size());
|
||||
ModelObject *model_object = model_objects[volume->object_idx()];
|
||||
ModelVolume *model_volume = model_object->volumes[volume->volume_idx()];
|
||||
for (size_t i = 0; i < inside_extruders.size(); ++i) {
|
||||
if (!inside_extruders[i]) {
|
||||
std::vector<int> filaments = model_volume->get_extruders();
|
||||
unprintable_filament_ids[i].insert(filaments.begin(), filaments.end());
|
||||
if (object_results) {
|
||||
std::map<int, std::set<int>>& obj_extruder_filament_maps = objects_unprintable_filaments[model_object];
|
||||
std::set<int>& obj_extruder_filaments = obj_extruder_filament_maps[i+1];
|
||||
obj_extruder_filaments.insert(filaments.begin(), filaments.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
|
||||
volume->is_outside = state != BuildVolume::ObjectState::Inside;
|
||||
//volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
|
||||
//int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
|
||||
volume->is_outside = (state != BuildVolume::ObjectState::Inside && state != BuildVolume::ObjectState::Limited);
|
||||
volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
|
||||
if (volume->printable) {
|
||||
if (overall_state == ModelInstancePVS_Inside && volume->is_outside) {
|
||||
overall_state = ModelInstancePVS_Fully_Outside;
|
||||
}
|
||||
|
||||
if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
|
||||
if (state == BuildVolume::ObjectState::Colliding)
|
||||
{
|
||||
overall_state = ModelInstancePVS_Partly_Outside;
|
||||
partly_objects_set.emplace(model_objects[volume->object_idx()]);
|
||||
}
|
||||
else if ((state == BuildVolume::ObjectState::Limited) && (overall_state != ModelInstancePVS_Partly_Outside))
|
||||
overall_state = ModelInstancePVS_Limited;
|
||||
else if ((state == BuildVolume::ObjectState::Inside) && (overall_state == ModelInstancePVS_Fully_Outside)) {
|
||||
overall_state = ModelInstancePVS_Fully_Outside;
|
||||
}
|
||||
contained_min_one |= !volume->is_outside;
|
||||
}
|
||||
|
||||
ModelInstanceEPrintVolumeState volume_state;
|
||||
/*ModelInstanceEPrintVolumeState volume_state;
|
||||
//if (volume->is_outside && (plate_build_volume.bounding_volume().intersects(volume->bounding_box())))
|
||||
if (volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
|
||||
volume_state = ModelInstancePVS_Partly_Outside;
|
||||
@@ -1154,11 +1250,121 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||
if (model_state[comp_id] == ModelInstancePVS_Partly_Outside) {
|
||||
overall_state = ModelInstancePVS_Partly_Outside;
|
||||
BOOST_LOG_TRIVIAL(debug) << "instance includes " << volume->name << " is partially outside of bed";
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<int>> unprintable_filament_vec;
|
||||
for (const std::set<int>& filamnt_ids : unprintable_filament_ids) {
|
||||
unprintable_filament_vec.emplace_back(std::vector<int>(filamnt_ids.begin(), filamnt_ids.end()));
|
||||
}
|
||||
|
||||
if (object_results && !partly_objects_set.empty()) {
|
||||
object_results->partly_outside_objects = std::vector<ModelObject*>(partly_objects_set.begin(), partly_objects_set.end());
|
||||
}
|
||||
|
||||
//check per-object error for extruder areas
|
||||
if (object_results && (extruder_count > 1))
|
||||
{
|
||||
const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config;
|
||||
object_results->mode = curr_plate->get_real_filament_map_mode(project_config);
|
||||
if (object_results->mode < FilamentMapMode::fmmManual)
|
||||
{
|
||||
std::vector<int> conflict_filament_vector;
|
||||
for (int index = 0; index < extruder_count; index++ )
|
||||
{
|
||||
if (!unprintable_filament_vec[index].empty())
|
||||
{
|
||||
std::sort (unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end());
|
||||
if (index == 0)
|
||||
conflict_filament_vector = unprintable_filament_vec[index];
|
||||
else
|
||||
{
|
||||
std::vector<int> result_filaments;
|
||||
//result_filaments.reserve(conflict_filaments.size());
|
||||
std::set_intersection (conflict_filament_vector.begin(), conflict_filament_vector.end(), unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end(), insert_iterator<vector<int>>(result_filaments, result_filaments.begin()));
|
||||
conflict_filament_vector = result_filaments;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
conflict_filament_vector.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conflict_filament_vector.empty())
|
||||
{
|
||||
std::set<int> conflict_filaments_set(conflict_filament_vector.begin(), conflict_filament_vector.end());
|
||||
object_results->filaments = conflict_filament_vector;
|
||||
|
||||
for (auto& object_map: objects_unprintable_filaments)
|
||||
{
|
||||
ModelObject *model_object = object_map.first;
|
||||
std::map<int, std::set<int>>& obj_extruder_filament_maps = object_map.second;
|
||||
std::set<int> obj_filaments_set;
|
||||
ObjectFilamentInfo object_filament_info;
|
||||
object_filament_info.object = model_object;
|
||||
|
||||
for (std::map<int, std::set<int>>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ )
|
||||
{
|
||||
int extruder_id = extruder_map_iter->first;
|
||||
std::set<int>& filaments_set = extruder_map_iter->second;
|
||||
|
||||
for (int filament: filaments_set)
|
||||
{
|
||||
if (conflict_filaments_set.find(filament) != conflict_filaments_set.end())
|
||||
{
|
||||
obj_filaments_set.emplace(filament);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!obj_filaments_set.empty()) {
|
||||
object_filament_info.auto_filaments = std::vector<int>(obj_filaments_set.begin(), obj_filaments_set.end());
|
||||
object_results->object_filaments.push_back(std::move(object_filament_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::set<int> conflict_filaments_set;
|
||||
const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config;
|
||||
std::vector<int> filament_maps = curr_plate->get_real_filament_maps(project_config);
|
||||
for (auto& object_map: objects_unprintable_filaments)
|
||||
{
|
||||
ModelObject *model_object = object_map.first;
|
||||
std::map<int, std::set<int>>& obj_extruder_filament_maps = object_map.second;
|
||||
ObjectFilamentInfo object_filament_info;
|
||||
object_filament_info.object = model_object;
|
||||
|
||||
for (std::map<int, std::set<int>>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ )
|
||||
{
|
||||
int extruder_id = extruder_map_iter->first;
|
||||
std::set<int>& filaments_set = extruder_map_iter->second;
|
||||
|
||||
for (int filament: filaments_set)
|
||||
{
|
||||
if (filament_maps[filament - 1] == extruder_id)
|
||||
{
|
||||
object_filament_info.manual_filaments.emplace(filament, extruder_id);
|
||||
object_results->filament_maps[filament] = extruder_id;
|
||||
conflict_filaments_set.emplace(filament);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!object_filament_info.manual_filaments.empty())
|
||||
{
|
||||
object_results->object_filaments.push_back(std::move(object_filament_info));
|
||||
}
|
||||
}
|
||||
if (!conflict_filaments_set.empty()) {
|
||||
object_results->filaments = std::vector<int>(conflict_filaments_set.begin(), conflict_filaments_set.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (GLVolume* volume : this->volumes)
|
||||
/*for (GLVolume* volume : this->volumes)
|
||||
{
|
||||
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0)))
|
||||
{
|
||||
@@ -1172,7 +1378,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
||||
volume->partly_inside = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (out_state != nullptr)
|
||||
*out_state = overall_state;
|
||||
|
||||
Reference in New Issue
Block a user