diff --git a/localization/i18n/Snapmaker_Orca.pot b/localization/i18n/Snapmaker_Orca.pot index ad310cb94c..c11cab95be 100644 --- a/localization/i18n/Snapmaker_Orca.pot +++ b/localization/i18n/Snapmaker_Orca.pot @@ -4341,9 +4341,8 @@ msgid "" msgstr "" msgid "" -"An object is too close to the plate boundary. Spiral lift during printing " -"may exceed the bed and cause a crash. Please move the object away from the " -"edge (recommend keeping at least 3mm distance)." +"Model too close to bed boundary. Disable spiral lifting or keep at least " +"3.5mm gap to avoid collision." msgstr "" msgid "Calibration step selection" diff --git a/localization/i18n/zh_CN/Snapmaker_Orca_zh_CN.po b/localization/i18n/zh_CN/Snapmaker_Orca_zh_CN.po index 1ab8575b0a..d7b130e18c 100644 --- a/localization/i18n/zh_CN/Snapmaker_Orca_zh_CN.po +++ b/localization/i18n/zh_CN/Snapmaker_Orca_zh_CN.po @@ -4268,11 +4268,10 @@ msgstr "" "请通过将其完全移动到构建板内或构建板外,并确认高度在构建空间以内来解决问题。" msgid "" -"An object is too close to the plate boundary. Spiral lift during printing " -"may exceed the bed and cause a crash. Please move the object away from the " -"edge (recommend keeping at least 3mm distance)." +"Model too close to bed boundary. Disable spiral lifting or keep at least " +"3.5mm gap to avoid collision." msgstr "" -"模型距离打印床边界太近。打印过程中的螺旋抬升可能会超出床范围导致撞机。请将模型移离边缘(建议保持至少3mm的距离)。" +"模型太靠近热床边界,建议暂时关闭螺旋抬升或至少距离边界3.5mm距离,防止超出打印区域引发撞击。" msgid "Calibration step selection" msgstr "校准步骤选择" diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b43e52db9e..769095e194 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -437,10 +437,6 @@ std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::T auto transform_wt_pt = [&alpha, this](const Vec2f& pt) -> Vec2f { Vec2f out = Eigen::Rotation2Df(alpha) * pt; - // Simple safety check to prevent extreme out-of-bounds coordinates - // This is a safety net for Rib wall geometry issues - out.x() = std::clamp(out.x(), -50.f, 500.f); - out.y() = std::clamp(out.y(), -50.f, 500.f); out += m_wipe_tower_pos; return out; }; @@ -701,10 +697,6 @@ std::string WipeTowerIntegration::append_tcr2(GCode& gcodegen, const WipeTower:: auto transform_wt_pt = [&alpha, this](const Vec2f& pt) -> Vec2f { Vec2f out = Eigen::Rotation2Df(alpha) * pt; - // Simple safety check to prevent extreme out-of-bounds coordinates - // This is a safety net for Rib wall geometry issues - out.x() = std::clamp(out.x(), -50.f, 500.f); - out.y() = std::clamp(out.y(), -50.f, 500.f); out += m_wipe_tower_pos; return out; }; diff --git a/src/libslic3r/GCode/WipeTower2.cpp b/src/libslic3r/GCode/WipeTower2.cpp index ebac2a6311..098d7aa15f 100644 --- a/src/libslic3r/GCode/WipeTower2.cpp +++ b/src/libslic3r/GCode/WipeTower2.cpp @@ -1237,11 +1237,6 @@ private: double s = sin(angle); Vec2f result(float(pt.x() * c - pt.y() * s) + m_wipe_tower_width / 2.f, float(pt.x() * s + pt.y() * c) + m_wipe_tower_depth / 2.f); - // Clamp rotated coordinates to valid range to prevent out-of-bounds positions - // This fixes issues with Rib wall geometry extending beyond expected bounds - result.x() = std::clamp(result.x(), 0.f, m_wipe_tower_width); - result.y() = std::clamp(result.y(), 0.f, m_wipe_tower_depth); - return result; } @@ -1969,10 +1964,9 @@ void WipeTower2::toolchange_Wipe(WipeTowerWriter2& writer, const WipeTower::box_ // We may be going back to the model - wipe the nozzle. If this is followed // by finish_layer, this wipe path will be overwritten. - // Clamp wipe point coordinates to valid range to prevent out-of-bounds positions - float wipe_y = std::clamp(writer.y() - dy, 0.f, m_wipe_tower_depth); - float wipe_x = std::clamp(!m_left_to_right ? m_wipe_tower_width : 0.f, 0.f, m_wipe_tower_width); - writer.add_wipe_point(writer.x(), writer.y()).add_wipe_point(writer.x(), wipe_y).add_wipe_point(wipe_x, wipe_y); + writer.add_wipe_point(writer.x(), writer.y()) + .add_wipe_point(writer.x(), writer.y() - dy) + .add_wipe_point(! m_left_to_right ? m_wipe_tower_width : 0.f, writer.y() - dy); if (m_layer_info != m_plan.end() && m_current_tool != m_layer_info->tool_changes.back().new_tool) m_left_to_right = !m_left_to_right; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index c092818ea5..d888490973 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -49,16 +49,18 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char return; const char* sErr = 0; switch (err) { - case GL_INVALID_ENUM: sErr = "Invalid Enum"; break; - case GL_INVALID_VALUE: sErr = "Invalid Value"; break; - // be aware that GL_INVALID_OPERATION is generated if glGetError is executed between the execution of glBegin and the corresponding execution of glEnd - case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break; - case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break; - case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break; - case GL_OUT_OF_MEMORY: sErr = "Out Of Memory"; break; - default: sErr = "Unknown"; break; + case GL_INVALID_ENUM: sErr = "Invalid Enum"; break; + case GL_INVALID_VALUE: sErr = "Invalid Value"; break; + // be aware that GL_INVALID_OPERATION is generated if glGetError is executed between the execution of glBegin and the corresponding + // execution of glEnd + case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break; + case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break; + case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break; + case GL_OUT_OF_MEMORY: sErr = "Out Of Memory"; break; + default: sErr = "Unknown"; break; } - BOOST_LOG_TRIVIAL(error) << "OpenGL error in " << file_name << ":" << line << ", function " << function_name << "() : " << (int)err << " - " << sErr; + BOOST_LOG_TRIVIAL(error) << "OpenGL error in " << file_name << ":" << line << ", function " << function_name << "() : " << (int) err + << " - " << sErr; assert(false); } #endif // HAS_GLSAFE @@ -66,10 +68,10 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char // BBS std::vector get_extruders_colors() { - unsigned char rgba_color[4] = {}; - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + unsigned char rgba_color[4] = {}; + std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); std::vector colors_out(colors.size()); - for (const std::string &color : colors) { + 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] = { @@ -90,21 +92,18 @@ float FullTransparentModdifiedToFixAlpha = 0.3f; // which breaks the `SelectMachineDialog::record_edge_pixels_data()` function! float FULL_BLACK_THRESHOLD = 0.2f; -Slic3r::ColorRGBA adjust_color_for_rendering(const Slic3r::ColorRGBA &colors) +Slic3r::ColorRGBA adjust_color_for_rendering(const Slic3r::ColorRGBA& colors) { if (colors.a() < FullyTransparentMaterialThreshold) { // completely transparent return {1, 1, 1, FullTransparentModdifiedToFixAlpha}; - } - else if(colors.r() < FULL_BLACK_THRESHOLD && colors.g() < FULL_BLACK_THRESHOLD && colors.b() < FULL_BLACK_THRESHOLD) { // black + } else if (colors.r() < FULL_BLACK_THRESHOLD && colors.g() < FULL_BLACK_THRESHOLD && colors.b() < FULL_BLACK_THRESHOLD) { // black return {FULL_BLACK_THRESHOLD, FULL_BLACK_THRESHOLD, FULL_BLACK_THRESHOLD, colors.a()}; - } - else + } else return colors; } namespace Slic3r { - const float GLVolume::SinkingContours::HalfWidth = 0.25f; void GLVolume::SinkingContours::render() @@ -123,66 +122,59 @@ void GLVolume::SinkingContours::render() void GLVolume::SinkingContours::update() { - const int object_idx = m_parent.object_idx(); - const Model& model = GUI::wxGetApp().plater()->model(); + const int object_idx = m_parent.object_idx(); + const Model& model = GUI::wxGetApp().plater()->model(); if (0 <= object_idx && object_idx < int(model.objects.size()) && m_parent.is_sinking() && !m_parent.is_below_printbed()) { const BoundingBoxf3& box = m_parent.transformed_convex_hull_bounding_box(); if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) { m_old_box = box; - m_shift = Vec3d::Zero(); + m_shift = Vec3d::Zero(); const TriangleMesh& mesh = model.objects[object_idx]->volumes[m_parent.volume_idx()]->mesh(); m_model.reset(); GUI::GLModel::Geometry init_data; - init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3 }; - init_data.color = ColorRGBA::WHITE(); - unsigned int vertices_counter = 0; + init_data.format = {GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3}; + init_data.color = ColorRGBA::WHITE(); + unsigned int vertices_counter = 0; MeshSlicingParams slicing_params; - slicing_params.trafo = m_parent.world_matrix(); + slicing_params.trafo = m_parent.world_matrix(); const Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params)); for (const ExPolygon& expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) { const std::vector triangulation = triangulate_expolygon_3d(expoly); init_data.reserve_vertices(init_data.vertices_count() + triangulation.size()); init_data.reserve_indices(init_data.indices_count() + triangulation.size()); for (const Vec3d& v : triangulation) { - init_data.add_vertex((Vec3f)(v.cast() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting + init_data.add_vertex((Vec3f) (v.cast() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting ++vertices_counter; if (vertices_counter % 3 == 0) init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); } } m_model.init_from(std::move(init_data)); - } - else + } else m_shift = box.center() - m_old_box.center(); - } - else + } else m_model.reset(); } ColorRGBA GLVolume::DISABLED_COLOR = ColorRGBA::DARK_GRAY(); ColorRGBA GLVolume::SLA_SUPPORT_COLOR = ColorRGBA::LIGHT_GRAY(); -ColorRGBA GLVolume::SLA_PAD_COLOR = { 0.0f, 0.2f, 0.0f, 1.0f }; +ColorRGBA GLVolume::SLA_PAD_COLOR = {0.0f, 0.2f, 0.0f, 1.0f}; // BBS -ColorRGBA GLVolume::NEUTRAL_COLOR = { 0.8f, 0.8f, 0.8f, 1.0f }; -ColorRGBA GLVolume::UNPRINTABLE_COLOR = { 0.0f, 0.0f, 0.0f, 0.5f }; +ColorRGBA GLVolume::NEUTRAL_COLOR = {0.8f, 0.8f, 0.8f, 1.0f}; +ColorRGBA GLVolume::UNPRINTABLE_COLOR = {0.0f, 0.0f, 0.0f, 0.5f}; ColorRGBA GLVolume::MODEL_MIDIFIER_COL = {1.0f, 1.0f, 0.0f, 0.6f}; ColorRGBA GLVolume::MODEL_NEGTIVE_COL = {0.3f, 0.3f, 0.3f, 0.4f}; ColorRGBA GLVolume::SUPPORT_ENFORCER_COL = {0.3f, 0.3f, 1.0f, 0.4f}; ColorRGBA GLVolume::SUPPORT_BLOCKER_COL = {1.0f, 0.3f, 0.3f, 0.4f}; -ColorRGBA GLVolume::MODEL_HIDDEN_COL = {0.f, 0.f, 0.f, 0.3f}; +ColorRGBA GLVolume::MODEL_HIDDEN_COL = {0.f, 0.f, 0.f, 0.3f}; -std::array GLVolume::MODEL_COLOR = { { - { 1.0f, 1.0f, 0.0f, 1.f }, - { 1.0f, 0.5f, 0.5f, 1.f }, - { 0.5f, 1.0f, 0.5f, 1.f }, - { 0.5f, 0.5f, 1.0f, 1.f }, - { 1.0f, 1.0f, 0.0f, 1.f } -} }; +std::array GLVolume::MODEL_COLOR = { + {{1.0f, 1.0f, 0.0f, 1.f}, {1.0f, 0.5f, 0.5f, 1.f}, {0.5f, 1.0f, 0.5f, 1.f}, {0.5f, 0.5f, 1.0f, 1.f}, {1.0f, 1.0f, 0.0f, 1.f}}}; void GLVolume::update_render_colors() { @@ -193,16 +185,15 @@ void GLVolume::update_render_colors() GLVolume::MODEL_COLOR[2] = GUI::ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Support_Enforcer]); GLVolume::MODEL_COLOR[3] = GUI::ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Support_Blocker]); GLVolume::UNPRINTABLE_COLOR = GUI::ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Model_Unprintable]); - } void GLVolume::load_render_colors() { - RenderColor::colors[RenderCol_Model_Disable] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::DISABLED_COLOR); - RenderColor::colors[RenderCol_Model_Neutral] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::NEUTRAL_COLOR); - RenderColor::colors[RenderCol_Modifier] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[0]); - RenderColor::colors[RenderCol_Negtive_Volume] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[1]); - RenderColor::colors[RenderCol_Support_Enforcer] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[2]); + RenderColor::colors[RenderCol_Model_Disable] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::DISABLED_COLOR); + RenderColor::colors[RenderCol_Model_Neutral] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::NEUTRAL_COLOR); + RenderColor::colors[RenderCol_Modifier] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[0]); + RenderColor::colors[RenderCol_Negtive_Volume] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[1]); + RenderColor::colors[RenderCol_Support_Enforcer] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[2]); RenderColor::colors[RenderCol_Support_Blocker] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::MODEL_COLOR[3]); RenderColor::colors[RenderCol_Model_Unprintable] = GUI::ImGuiWrapper::to_ImVec4(GLVolume::UNPRINTABLE_COLOR); } @@ -233,14 +224,13 @@ GLVolume::GLVolume(float r, float g, float b, float a) , picking(false) , tverts_range(0, size_t(-1)) { - color = { r, g, b, a }; + color = {r, g, b, a}; set_render_color(color); mmuseg_ts = 0; } - // BBS -float GLVolume::explosion_ratio = 1.0; +float GLVolume::explosion_ratio = 1.0; float GLVolume::last_explosion_ratio = 1.0; void GLVolume::set_render_color() @@ -260,8 +250,7 @@ void GLVolume::set_render_color() #ifdef ENABLE_OUTSIDE_COLOR } #endif - } - else { + } else { /* BBS if (hover == HS_Select) set_render_color(HOVER_SELECT_COLOR); @@ -278,7 +267,7 @@ void GLVolume::set_render_color() set_render_color(OUTSIDE_COLOR); #endif else { - //to make black not too hard too see + // to make black not too hard too see ColorRGBA new_color = adjust_color_for_rendering(color); set_render_color(new_color); } @@ -292,12 +281,12 @@ void GLVolume::set_render_color() } } - //BBS set unprintable color + // BBS set unprintable color if (!printable) { render_color = UNPRINTABLE_COLOR; } - //BBS set invisible color + // BBS set invisible color if (!visible) { render_color = MODEL_HIDDEN_COL; } @@ -312,7 +301,7 @@ ColorRGBA color_from_model_volume(const ModelVolume& model_volume) #if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT return GLVolume::MODEL_MIDIFIER_COL; #else - color = { 0.2f, 1.0f, 0.2f, 1.0f }; + color = {0.2f, 1.0f, 0.2f, 1.0f}; #endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT else if (model_volume.is_support_blocker()) return GLVolume::SUPPORT_BLOCKER_COL; @@ -323,9 +312,9 @@ ColorRGBA color_from_model_volume(const ModelVolume& model_volume) Transform3d GLVolume::world_matrix() const { - Transform3d m = m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix(); - Vec3d ofs2ass = m_offset_to_assembly * (GLVolume::explosion_ratio - 1.0); - Vec3d volofs2obj = m_volume_transformation.get_offset() * (GLVolume::explosion_ratio - 1.0); + Transform3d m = m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix(); + Vec3d ofs2ass = m_offset_to_assembly * (GLVolume::explosion_ratio - 1.0); + Vec3d volofs2obj = m_volume_transformation.get_offset() * (GLVolume::explosion_ratio - 1.0); m.translation()(2) += m_sla_shift_z; m.translate(ofs2ass + volofs2obj); @@ -334,8 +323,8 @@ Transform3d GLVolume::world_matrix() const bool GLVolume::is_left_handed() const { - const Vec3d &m1 = m_instance_transformation.get_mirror(); - const Vec3d &m2 = m_volume_transformation.get_mirror(); + const Vec3d& m1 = m_instance_transformation.get_mirror(); + const Vec3d& m2 = m_volume_transformation.get_mirror(); return m1.x() * m1.y() * m1.z() * m2.x() * m2.y() * m2.z() < 0.; } @@ -345,8 +334,8 @@ const BoundingBoxf3& GLVolume::transformed_bounding_box() const const BoundingBoxf3& box = bounding_box(); assert(box.defined || box.min.x() >= box.max.x() || box.min.y() >= box.max.y() || box.min.z() >= box.max.z()); std::optional* trans_box = const_cast*>(&m_transformed_bounding_box); - *trans_box = box.transformed(world_matrix()); - last_explosion_ratio = explosion_ratio; + *trans_box = box.transformed(world_matrix()); + last_explosion_ratio = explosion_ratio; } return *m_transformed_bounding_box; } @@ -355,16 +344,14 @@ const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const { if (!m_transformed_convex_hull_bounding_box.has_value()) { std::optional* trans_box = const_cast*>(&m_transformed_convex_hull_bounding_box); - *trans_box = transformed_convex_hull_bounding_box(world_matrix()); + *trans_box = transformed_convex_hull_bounding_box(world_matrix()); } return *m_transformed_convex_hull_bounding_box; } -BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &trafo) const +BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d& trafo) const { - return (m_convex_hull && ! m_convex_hull->empty()) ? - m_convex_hull->transformed_bounding_box(trafo) : - bounding_box().transformed(trafo); + return (m_convex_hull && !m_convex_hull->empty()) ? m_convex_hull->transformed_bounding_box(trafo) : bounding_box().transformed(trafo); } BoundingBoxf3 GLVolume::transformed_non_sinking_bounding_box(const Transform3d& trafo) const @@ -376,15 +363,15 @@ const BoundingBoxf3& GLVolume::transformed_non_sinking_bounding_box() const { if (!m_transformed_non_sinking_bounding_box.has_value()) { std::optional* trans_box = const_cast*>(&m_transformed_non_sinking_bounding_box); - const Transform3d& trafo = world_matrix(); - *trans_box = transformed_non_sinking_bounding_box(trafo); + const Transform3d& trafo = world_matrix(); + *trans_box = transformed_non_sinking_bounding_box(trafo); } return *m_transformed_non_sinking_bounding_box; } void GLVolume::set_range(double min_z, double max_z) { - this->tverts_range.first = 0; + this->tverts_range.first = 0; this->tverts_range.second = this->model.indices_count(); if (!this->print_zs.empty()) { @@ -395,7 +382,8 @@ void GLVolume::set_range(double min_z, double max_z) else { // Then find the lowest layer to be displayed. size_t i = 0; - for (; i < this->print_zs.size() && this->print_zs[i] < min_z; ++i); + for (; i < this->print_zs.size() && this->print_zs[i] < min_z; ++i) + ; if (i == this->print_zs.size()) // This shall not happen. this->tverts_range.second = 0; @@ -403,7 +391,8 @@ void GLVolume::set_range(double min_z, double max_z) // Remember start of the layer. this->tverts_range.first = this->offsets[i]; // Some layers are above $min_z. Which? - for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++i); + for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++i) + ; if (i < this->print_zs.size()) this->tverts_range.second = this->offsets[i]; } @@ -416,28 +405,28 @@ void GLVolume::render() if (!is_active) return; - GLShaderProgram *shader = GUI::wxGetApp().get_current_shader(); + GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); if (shader == nullptr) return; - ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects; - std::vector colors = get_extruders_colors(); + ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects; + std::vector colors = get_extruders_colors(); simple_render(shader, model_objects, colors); } -//BBS: add outline related logic +// BBS: add outline related logic void GLVolume::render_with_outline(const GUI::Size& cnv_size) { if (!is_active) return; - GLShaderProgram *shader = GUI::wxGetApp().get_current_shader(); + GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); if (shader == nullptr) return; - ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects; - std::vector colors = get_extruders_colors(); + ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects; + std::vector colors = get_extruders_colors(); const GUI::OpenGLManager::EFramebufferType framebuffers_type = GUI::OpenGLManager::get_framebuffers_type(); if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Unknown) { @@ -447,7 +436,7 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size) } // 1st. render pass, render the model into a separate render target that has only depth buffer - GLuint depth_fbo = 0; + GLuint depth_fbo = 0; GLuint depth_tex = 0; if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) { glsafe(::glGenFramebuffers(1, &depth_fbo)); @@ -460,7 +449,8 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size) glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr)); + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, + GL_FLOAT, nullptr)); glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0)); } else { @@ -474,7 +464,8 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size) glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr)); + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, + GL_FLOAT, nullptr)); glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0)); } @@ -514,14 +505,17 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size) glsafe(::glDeleteTextures(1, &depth_tex)); } -//BBS add render for simple case -void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector& extruder_colors, bool ban_light) +// BBS add render for simple case +void GLVolume::simple_render(GLShaderProgram* shader, + ModelObjectPtrs& model_objects, + std::vector& extruder_colors, + bool ban_light) { if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - bool color_volume = false; + bool color_volume = false; ModelObject* model_object = nullptr; ModelVolume* model_volume = nullptr; do { @@ -529,7 +523,7 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj break; model_object = model_objects[object_idx()]; - if (volume_idx() >= model_object->volumes.size()) + if (volume_idx() >= model_object->volumes.size()) break; model_volume = model_object->volumes[volume_idx()]; if (model_volume->mmu_segmentation_facets.empty()) @@ -552,12 +546,12 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj if (color_volume && !picking) { // when force_transparent, we need to keep the alpha if (force_native_color && render_color.is_transparent()) { - for (auto &extruder_color : extruder_colors) + for (auto& extruder_color : extruder_colors) extruder_color.a(render_color.a()); } for (int idx = 0; idx < mmuseg_models.size(); idx++) { - GUI::GLModel &m = mmuseg_models[idx]; + GUI::GLModel& m = mmuseg_models[idx]; if (!m.is_initialized()) continue; @@ -566,26 +560,24 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj int extruder_id = model_volume->extruder_id(); if (extruder_id <= 0) extruder_id = 1; - //to make black not too hard too see + // to make black not too hard too see ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[extruder_id - 1]); if (ban_light) { - new_color[3] = (255 - (extruder_id - 1))/255.0f; + new_color[3] = (255 - (extruder_id - 1)) / 255.0f; } m.set_color(new_color); // shader->set_uniform("uniform_color", new_color); - } - else { + } else { if (idx <= extruder_colors.size()) { - //to make black not too hard too see + // to make black not too hard too see ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[idx - 1]); if (ban_light) { - new_color[3] = (255 - (idx - 1))/255.0f; + new_color[3] = (255 - (idx - 1)) / 255.0f; } m.set_color(new_color); // shader->set_uniform("uniform_color", new_color); - } - else { - //to make black not too hard too see + } else { + // to make black not too hard too see ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[0]); if (ban_light) { new_color[3] = (255 - 0) / 255.0f; @@ -621,21 +613,11 @@ bool GLVolume::is_sinking() const return box.min.z() < SINKING_Z_THRESHOLD && box.max.z() >= SINKING_Z_THRESHOLD; } -bool GLVolume::is_below_printbed() const -{ - return transformed_convex_hull_bounding_box().max.z() < 0.0; -} +bool GLVolume::is_below_printbed() const { return transformed_convex_hull_bounding_box().max.z() < 0.0; } -void GLVolume::render_sinking_contours() -{ - m_sinking_contours.render(); -} +void GLVolume::render_sinking_contours() { m_sinking_contours.render(); } -GLWipeTowerVolume::GLWipeTowerVolume(const std::vector& colors) - : GLVolume() -{ - m_colors = colors; -} +GLWipeTowerVolume::GLWipeTowerVolume(const std::vector& colors) : GLVolume() { m_colors = colors; } void GLWipeTowerVolume::render() { @@ -658,51 +640,50 @@ void GLWipeTowerVolume::render() } this->model_per_colors[i].render(); } - + if (this->is_left_handed()) glFrontFace(GL_CCW); } -bool GLWipeTowerVolume::IsTransparent() { +bool GLWipeTowerVolume::IsTransparent() +{ for (size_t i = 0; i < m_colors.size(); i++) { - if (m_colors[i].is_transparent()) { + if (m_colors[i].is_transparent()) { return true; } } - return false; + return false; } -std::vector GLVolumeCollection::load_object( - const ModelObject *model_object, - int obj_idx, - const std::vector &instance_idxs, - const std::string &color_by, - bool opengl_initialized, - bool need_raycaster) +std::vector GLVolumeCollection::load_object(const ModelObject* model_object, + int obj_idx, + const std::vector& instance_idxs, + const std::string& color_by, + bool opengl_initialized, + bool need_raycaster) { std::vector volumes_idx; for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx) for (int instance_idx : instance_idxs) - volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized, false, false, need_raycaster)); + volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, + opengl_initialized, false, false, need_raycaster)); return volumes_idx; } - -int GLVolumeCollection::load_object_volume( - const ModelObject *model_object, - int obj_idx, - int volume_idx, - int instance_idx, - const std::string &color_by, - bool opengl_initialized, - bool in_assemble_view, - bool use_loaded_id, - bool need_raycaster) +int GLVolumeCollection::load_object_volume(const ModelObject* model_object, + int obj_idx, + int volume_idx, + int instance_idx, + const std::string& color_by, + bool opengl_initialized, + bool in_assemble_view, + bool use_loaded_id, + bool need_raycaster) { - const ModelVolume *model_volume = model_object->volumes[volume_idx]; + const ModelVolume* model_volume = model_object->volumes[volume_idx]; const int extruder_id = model_volume->extruder_id(); - const ModelInstance *instance = model_object->instances[instance_idx]; - auto color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4]; + const ModelInstance* instance = model_object->instances[instance_idx]; + auto color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4]; color.a(model_volume->is_model_part() ? 0.7f : 0.4f); std::shared_ptr mesh = model_volume->mesh_ptr(); @@ -710,32 +691,32 @@ int GLVolumeCollection::load_object_volume( GLVolume& v = *this->volumes.back(); v.set_color(color_from_model_volume(*model_volume)); v.name = model_volume->name; - + #if ENABLE_SMOOTH_NORMALS v.model.init_from(mesh, true); #else v.model.init_from(*mesh); - if (need_raycaster) { v.mesh_raycaster = std::make_unique(mesh); } + if (need_raycaster) { + v.mesh_raycaster = std::make_unique(mesh); + } #endif // ENABLE_SMOOTH_NORMALS v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx); - if (model_volume->is_model_part()) - { + if (model_volume->is_model_part()) { // GLVolume will reference a convex hull from model_volume! v.set_convex_hull(model_volume->get_convex_hull_shared_ptr()); if (extruder_id != -1) v.extruder_id = extruder_id; } - v.is_modifier = !model_volume->is_model_part(); + v.is_modifier = !model_volume->is_model_part(); v.shader_outside_printer_detection_enabled = model_volume->is_model_part(); if (in_assemble_view) { v.set_instance_transformation(instance->get_assemble_transformation()); v.set_offset_to_assembly(instance->get_offset_to_assembly()); - } - else + } else v.set_instance_transformation(instance->get_transformation()); v.set_volume_transformation(model_volume->get_transformation()); - //use object's instance id + // use object's instance id if (use_loaded_id && (instance->loaded_id > 0)) v.model_object_ID = instance->loaded_id; else @@ -747,17 +728,16 @@ int GLVolumeCollection::load_object_volume( // Load SLA auxiliary GLVolumes (for support trees or pad). // This function produces volumes for multiple instances in a single shot, // as some object specific mesh conversions may be expensive. -void GLVolumeCollection::load_object_auxiliary( - const SLAPrintObject* print_object, - int obj_idx, - // pairs of - const std::vector>& instances, - SLAPrintObjectStep milestone, - // Timestamp of the last change of the milestone - size_t timestamp) +void GLVolumeCollection::load_object_auxiliary(const SLAPrintObject* print_object, + int obj_idx, + // pairs of + const std::vector>& instances, + SLAPrintObjectStep milestone, + // Timestamp of the last change of the milestone + size_t timestamp) { assert(print_object->is_step_done(milestone)); - Transform3d mesh_trafo_inv = print_object->trafo().inverse(); + Transform3d mesh_trafo_inv = print_object->trafo().inverse(); // Get the support mesh. TriangleMesh mesh = print_object->get_mesh(milestone); mesh.transform(mesh_trafo_inv); @@ -774,14 +754,14 @@ void GLVolumeCollection::load_object_auxiliary( v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR); v.mesh_raycaster = std::make_unique(std::make_shared(mesh)); #endif // ENABLE_SMOOTH_NORMALS - v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first); - v.geometry_id = std::pair(timestamp, model_instance.id().id); + v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int) instance_idx.first); + v.geometry_id = std::pair(timestamp, model_instance.id().id); // Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance. if (&instance_idx == &instances.back()) v.set_convex_hull(std::move(convex_hull)); else v.set_convex_hull(convex_hull); - v.is_modifier = false; + v.is_modifier = false; v.shader_outside_printer_detection_enabled = (milestone == slaposSupportTree); v.set_instance_transformation(model_instance.get_transformation()); // Leave the volume transformation at identity. @@ -790,8 +770,7 @@ void GLVolumeCollection::load_object_auxiliary( } int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, - float rotation_angle, bool size_unknown, float brim_width) + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) { int plate_idx = obj_idx - 1000; @@ -802,9 +781,9 @@ int GLVolumeCollection::load_wipe_tower_preview( std::vector extruder_colors = get_extruders_colors(); std::vector colors; - GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list(); - std::vector plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true); - TriangleMesh wipe_tower_shell = make_cube(width, depth, height); + GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list(); + std::vector plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true); + TriangleMesh wipe_tower_shell = make_cube(width, depth, height); for (int extruder_id : plate_extruders) { if (extruder_id <= extruder_colors.size()) colors.push_back(extruder_colors[extruder_id - 1]); @@ -813,14 +792,14 @@ int GLVolumeCollection::load_wipe_tower_preview( } // Orca: make it transparent - for(auto& color : colors) + for (auto& color : colors) color.a(0.66f); volumes.emplace_back(new GLWipeTowerVolume(colors)); GLWipeTowerVolume& v = *dynamic_cast(volumes.back()); v.model_per_colors.resize(colors.size()); for (int i = 0; i < colors.size(); i++) { TriangleMesh color_part = make_cube(width, depth / colors.size(), height); - color_part.translate({ 0.f, depth * i / colors.size(), 0. }); + color_part.translate({0.f, depth * i / colors.size(), 0.}); v.model_per_colors[i].init_from(color_part); } v.model.init_from(wipe_tower_shell); @@ -828,45 +807,47 @@ int GLVolumeCollection::load_wipe_tower_preview( 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.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); + GLVolume* out = new_nontoolpath_volume(rgba); out->is_extrusion_path = true; return out; } GLVolume* GLVolumeCollection::new_nontoolpath_volume(const ColorRGBA& rgba) { - GLVolume* out = new GLVolume(rgba); + GLVolume* out = new GLVolume(rgba); out->is_extrusion_path = false; this->volumes.emplace_back(out); return out; } -GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function filter_func) +GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, + GLVolumeCollection::ERenderType type, + const Transform3d& view_matrix, + std::function filter_func) { GLVolumeWithIdAndZList list; list.reserve(volumes.size()); - for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) { - GLVolume* volume = volumes[i]; - bool is_transparent = volume->render_color.is_transparent(); - auto tempGlwipeTowerVolume = dynamic_cast(volume); - if (tempGlwipeTowerVolume) { + for (unsigned int i = 0; i < (unsigned int) volumes.size(); ++i) { + GLVolume* volume = volumes[i]; + bool is_transparent = volume->render_color.is_transparent(); + auto tempGlwipeTowerVolume = dynamic_cast(volume); + if (tempGlwipeTowerVolume) { is_transparent = tempGlwipeTowerVolume->IsTransparent(); } - if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) || - (type == GLVolumeCollection::ERenderType::Transparent && is_transparent) || - type == GLVolumeCollection::ERenderType::All) && - (! filter_func || filter_func(*volume))) + if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) || + (type == GLVolumeCollection::ERenderType::Transparent && is_transparent) || type == GLVolumeCollection::ERenderType::All) && + (!filter_func || filter_func(*volume))) list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0))); } @@ -876,34 +857,32 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo } std::sort(list.begin(), list.end(), - [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.second.second < v2.second.second; } - ); - } - else if (type == GLVolumeCollection::ERenderType::Opaque && list.size() > 1) { - std::sort(list.begin(), list.end(), - [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.first->selected && !v2.first->selected; } - ); + [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.second.second < v2.second.second; }); + } else if (type == GLVolumeCollection::ERenderType::Opaque && list.size() > 1) { + std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { + return v1.first->selected && !v2.first->selected; + }); } return list; } -int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_support) const +int GLVolumeCollection::get_selection_support_threshold_angle(bool& enable_support) const { - const DynamicPrintConfig& glb_cfg = GUI::wxGetApp().preset_bundle->prints.get_edited_preset().config; - enable_support = glb_cfg.opt_bool("enable_support"); - int support_threshold_angle = glb_cfg.opt_int("support_threshold_angle"); - return support_threshold_angle ; + const DynamicPrintConfig& glb_cfg = GUI::wxGetApp().preset_bundle->prints.get_edited_preset().config; + enable_support = glb_cfg.opt_bool("enable_support"); + int support_threshold_angle = glb_cfg.opt_int("support_threshold_angle"); + return support_threshold_angle; } -//BBS: add outline drawing logic -void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, - bool disable_cullface, - const Transform3d & view_matrix, - const Transform3d& projection_matrix, - const GUI::Size& cnv_size, - std::function filter_func, - bool partly_inside_enable) const +// BBS: add outline drawing logic +void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, + bool disable_cullface, + const Transform3d& view_matrix, + const Transform3d& projection_matrix, + const GUI::Size& cnv_size, + std::function filter_func, + bool partly_inside_enable) const { GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func); if (to_render.empty()) @@ -913,7 +892,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, if (shader == nullptr) return; - GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); + GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat"); if (type == ERenderType::Transparent) { @@ -929,10 +908,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, #if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT if (type == ERenderType::Transparent) { volume.first->force_transparent = true; - //BOOST_LOG_TRIVIAL(info) << boost::format("transparent rendering..."); + // BOOST_LOG_TRIVIAL(info) << boost::format("transparent rendering..."); } - //else - // BOOST_LOG_TRIVIAL(info) << boost::format("opaque rendering..."); + // else + // BOOST_LOG_TRIVIAL(info) << boost::format("opaque rendering..."); #endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT volume.first->set_render_color(); #if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT @@ -945,8 +924,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, if (sink_shader != nullptr) { sink_shader->start_using(); if (m_show_sinking_contours) { - if (volume.first->is_sinking() && !volume.first->is_below_printbed() && - volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { + if (volume.first->is_sinking() && !volume.first->is_below_printbed() && volume.first->hover == GLVolume::HS_None && + !volume.first->force_sinking_contours) { volume.first->render_sinking_contours(); } } @@ -962,39 +941,40 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, shader->set_uniform("color_clip_plane", m_color_clip_plane); shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]); shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]); - //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") - // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] - // %with_outline%volume.first->selected; + // BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") + // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] + // %with_outline%volume.first->selected; - //BBS set print_volume to render volume - //shader->set_uniform("print_volume.type", static_cast(m_render_volume.type)); - //shader->set_uniform("print_volume.xy_data", m_render_volume.data); - //shader->set_uniform("print_volume.z_data", m_render_volume.zs); + // BBS set print_volume to render volume + // shader->set_uniform("print_volume.type", static_cast(m_render_volume.type)); + // shader->set_uniform("print_volume.xy_data", m_render_volume.data); + // shader->set_uniform("print_volume.z_data", m_render_volume.zs); if (volume.first->partly_inside && partly_inside_enable) { - //only partly inside volume need to be painted with boundary check + // only partly inside volume need to be painted with boundary check shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); shader->set_uniform("print_volume.xy_data", m_print_volume.data); shader->set_uniform("print_volume.z_data", m_print_volume.zs); - } - else { - //use -1 ad a invalid type + } else { + // use -1 ad a invalid type shader->set_uniform("print_volume.type", -1); } - - bool enable_support; - int support_threshold_angle = get_selection_support_threshold_angle(enable_support); - - float normal_z = -::cos(Geometry::deg2rad((float) support_threshold_angle)); - + + bool enable_support; + int support_threshold_angle = get_selection_support_threshold_angle(enable_support); + + float normal_z = -::cos(Geometry::deg2rad((float) support_threshold_angle)); + shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower); - shader->set_uniform("slope.volume_world_normal_matrix", static_cast(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast())); + shader->set_uniform("slope.volume_world_normal_matrix", + static_cast( + volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast())); shader->set_uniform("slope.normal_z", normal_z); #if ENABLE_ENVIRONMENT_MAP - unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); - bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1"; + unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); + bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1"; shader->set_uniform("use_environment_tex", use_environment_texture); if (use_environment_texture) glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id)); @@ -1005,9 +985,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, 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); - const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * + model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); shader->set_uniform("view_normal_matrix", view_normal_matrix); - //BBS: add outline related logic + // BBS: add outline related logic if (volume.first->selected && GUI::wxGetApp().show_outline()) volume.first->render_with_outline(cnv_size); else @@ -1047,58 +1028,65 @@ 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_outside_state(const BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state) const { - if (GUI::wxGetApp().plater() == NULL) - { + if (GUI::wxGetApp().plater() == NULL) { if (out_state != nullptr) *out_state = ModelInstancePVS_Inside; return false; } - const Model& model = GUI::wxGetApp().plater()->model(); - auto volume_below = [](GLVolume& volume) -> bool - { return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_below_printbed(); }; + const Model& model = GUI::wxGetApp().plater()->model(); + auto volume_below = [](GLVolume& volume) -> bool { + return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_below_printbed(); + }; // Volume is partially below the print bed, thus a pre-calculated convex hull cannot be used. - auto volume_sinking = [](GLVolume& volume) -> bool - { return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_sinking(); }; + auto volume_sinking = [](GLVolume& volume) -> bool { + return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_sinking(); + }; // Cached bounding box of a volume above the print bed. - auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3 - { return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); }; + auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3 { + return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); + }; // Cached 3D convex hull of a volume above the print bed. - 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(); }; + 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; - bool contained_min_one = false; + ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside; + bool contained_min_one = false; - //BBS: add instance judge logic, besides to original volume judge logic + // BBS: add instance judge logic, besides to original volume judge logic std::map 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()); + 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()); const std::vector& exclude_areas = curr_plate->get_exclude_areas(); - 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))) { + for (GLVolume* volume : this->volumes) { + // Snapmaker: 初始化螺旋抬升边界状态(在循环开始时就清除所有标志) + if (volume != nullptr) + volume->near_boundary_for_spiral_lift = false; + + 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)) state = BuildVolume::ObjectState::Below; else { switch (plate_build_volume.type()) { 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); - } - break; + state = plate_build_volume.volume_state_bbox(bb); + } 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. + // 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(), volume_sinking(*volume)); + state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast(), + volume_sinking(*volume)); break; default: // Ignore, don't produce any collision. @@ -1108,49 +1096,46 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo assert(state != BuildVolume::ObjectState::Below); } - int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id); + 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; // Snapmaker: 检测模型是否距离床边界太近(螺旋抬升风险) - volume->near_boundary_for_spiral_lift = false; - // 只对矩形床进行检测(Snapmaker U1) - if (plate_build_volume.type() == BuildVolume_Type::Rectangle && volume->composite_id.volume_id >= 0) { - constexpr double SPIRAL_LIFT_SAFETY_MARGIN = 3.5; // mm - const BoundingBoxf3& bb = volume_bbox(*volume); - const BoundingBoxf3& bed_bb = plate_build_volume.bounding_volume(); + // 只对矩形床进行检测(Snapmaker U1),只检测可打印的对象 + // 只检测完全在床内的对象(state == Inside),避免对跨越边界的对象误报 + if (plate_build_volume.type() == BuildVolume_Type::Rectangle && volume->composite_id.volume_id >= 0 && + state == BuildVolume::ObjectState::Inside && volume->printable) { + constexpr double SPIRAL_LIFT_SAFETY_MARGIN = 3.5; // mm + const BoundingBoxf3& bb = volume_bbox(*volume); + const BoundingBoxf3& bed_bb = plate_build_volume.bounding_volume(); - // 计算模型边界框与床边界的最小距离(使用绝对值处理超出边界的情况) - double min_distance_x = std::min({ - std::abs(bb.min.x() - bed_bb.min.x()), - std::abs(bed_bb.max.x() - bb.max.x()) - }); - double min_distance_y = std::min({ - std::abs(bb.min.y() - bed_bb.min.y()), - std::abs(bed_bb.max.y() - bb.max.y()) - }); + // 计算模型边界框与床边界的最小距离 + double dist_left = std::abs(bb.min.x() - bed_bb.min.x()); + double dist_right = std::abs(bed_bb.max.x() - bb.max.x()); + double dist_bottom = std::abs(bb.min.y() - bed_bb.min.y()); + double dist_top = std::abs(bed_bb.max.y() - bb.max.y()); - double min_distance = std::min({min_distance_x, min_distance_y}); + double min_distance = std::min({dist_left, dist_right, dist_bottom, dist_top}); // 如果最小距离小于安全余量,触发警告 if (min_distance < SPIRAL_LIFT_SAFETY_MARGIN) { volume->near_boundary_for_spiral_lift = true; } } - //volume->partly_inside = (state == BuildVolume::ObjectState::Colliding); + // 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 (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && + (state == BuildVolume::ObjectState::Colliding)) { overall_state = ModelInstancePVS_Partly_Outside; } contained_min_one |= !volume->is_outside; } ModelInstanceEPrintVolumeState volume_state; - //if (volume->is_outside && (plate_build_volume.bounding_volume().intersects(volume->bounding_box()))) + // 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; else if (volume->is_outside) @@ -1158,20 +1143,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo else volume_state = ModelInstancePVS_Inside; - if (model_state.find(comp_id) != model_state.end()) - { - if (model_state[comp_id] != ModelInstancePVS_Partly_Outside) - { + if (model_state.find(comp_id) != model_state.end()) { + if (model_state[comp_id] != ModelInstancePVS_Partly_Outside) { if (volume_state == ModelInstancePVS_Partly_Outside) model_state[comp_id] = ModelInstancePVS_Partly_Outside; - else if (model_state[comp_id] != volume_state) - { + else if (model_state[comp_id] != volume_state) { model_state[comp_id] = ModelInstancePVS_Partly_Outside; } } - } - else - { + } else { model_state[comp_id] = volume_state; } @@ -1182,17 +1162,14 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo } } - 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))) - { - int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id); - if (model_state.find(comp_id) != model_state.end()) - { + 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))) { + int64_t comp_id = ((int64_t) volume->composite_id.object_id << 32) | ((int64_t) volume->composite_id.instance_id); + if (model_state.find(comp_id) != model_state.end()) { if (model_state[comp_id] == ModelInstancePVS_Partly_Outside) { volume->partly_inside = true; - } - else + } else volume->partly_inside = false; } } @@ -1206,12 +1183,11 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo void GLVolumeCollection::reset_outside_state() { - for (GLVolume* volume : this->volumes) - { + for (GLVolume* volume : this->volumes) { if (volume != nullptr) { - volume->is_outside = false; - volume->partly_inside = false; - volume->near_boundary_for_spiral_lift = false; // Snapmaker: 初始化螺旋抬升边界状态 + volume->is_outside = false; + volume->partly_inside = false; + volume->near_boundary_for_spiral_lift = false; // Snapmaker: 初始化螺旋抬升边界状态 } } } @@ -1219,43 +1195,40 @@ void GLVolumeCollection::reset_outside_state() // Snapmaker: 检查是否有任何 volume 靠近边界(螺旋抬升风险) bool GLVolumeCollection::is_any_volume_near_boundary_for_spiral_lift() const { - for (const GLVolume* volume : this->volumes) - { + for (const GLVolume* volume : this->volumes) { if (volume != nullptr && volume->near_boundary_for_spiral_lift) return true; } return false; } -void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig *config, bool is_update_alpha) +void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config, bool is_update_alpha) { - using ColorItem = std::pair; std::vector colors; if (static_cast(config->opt_int("printer_technology")) == ptSLA) { const std::string& txt_color = config->opt_string("material_colour").empty() ? - print_config_def.get("material_colour")->get_default_value()->value : - config->opt_string("material_colour"); - ColorRGBA rgba; + print_config_def.get("material_colour")->get_default_value()->value : + config->opt_string("material_colour"); + ColorRGBA rgba; if (decode_color(txt_color, rgba)) - colors.push_back({ txt_color, rgba }); - } - else { + colors.push_back({txt_color, rgba}); + } else { const ConfigOptionStrings* filamemts_opt = dynamic_cast(config->option("filament_colour")); if (filamemts_opt == nullptr) return; - size_t colors_count = (size_t)filamemts_opt->values.size(); + size_t colors_count = (size_t) filamemts_opt->values.size(); if (colors_count == 0) return; colors.resize(colors_count); for (unsigned int i = 0; i < colors_count; ++i) { - ColorRGBA rgba; + ColorRGBA rgba; const std::string& fil_color = config->opt_string("filament_colour", i); if (decode_color(fil_color, rgba)) - colors[i] = { fil_color, rgba }; + colors[i] = {fil_color, rgba}; } } @@ -1264,7 +1237,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig *con continue; int extruder_id = volume->extruder_id - 1; - if (extruder_id < 0 || (int)colors.size() <= extruder_id) + if (extruder_id < 0 || (int) colors.size() <= extruder_id) extruder_id = 0; const ColorItem& color = colors[extruder_id]; @@ -1282,7 +1255,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig *con void GLVolumeCollection::set_transparency(float alpha) { - for (GLVolume *volume : volumes) { + for (GLVolume* volume : volumes) { if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || (volume->volume_idx() < 0)) continue; @@ -1294,8 +1267,7 @@ std::vector GLVolumeCollection::get_current_print_zs(bool active_only) c { // Collect layer top positions of all volumes. std::vector print_zs; - for (GLVolume *vol : this->volumes) - { + for (GLVolume* vol : this->volumes) { if (!active_only || vol->is_active) append(print_zs, vol->print_zs); } @@ -1305,11 +1277,12 @@ std::vector GLVolumeCollection::get_current_print_zs(bool active_only) c int n = int(print_zs.size()); int k = 0; for (int i = 0; i < n;) { - int j = i + 1; + int j = i + 1; coordf_t zmax = print_zs[i] + EPSILON; - for (; j < n && print_zs[j] <= zmax; ++ j) ; - print_zs[k ++] = (j > i + 1) ? (0.5 * (print_zs[i] + print_zs[j - 1])) : print_zs[i]; - i = j; + for (; j < n && print_zs[j] <= zmax; ++j) + ; + print_zs[k++] = (j > i + 1) ? (0.5 * (print_zs[i] + print_zs[j - 1])) : print_zs[i]; + i = j; } if (k < n) print_zs.erase(print_zs.begin() + k, print_zs.end()); @@ -1319,82 +1292,76 @@ std::vector GLVolumeCollection::get_current_print_zs(bool active_only) c size_t GLVolumeCollection::cpu_memory_used() const { - size_t memsize = sizeof(*this) + this->volumes.capacity() * sizeof(GLVolume); - for (const GLVolume *volume : this->volumes) - memsize += volume->cpu_memory_used(); - return memsize; + size_t memsize = sizeof(*this) + this->volumes.capacity() * sizeof(GLVolume); + for (const GLVolume* volume : this->volumes) + memsize += volume->cpu_memory_used(); + return memsize; } size_t GLVolumeCollection::gpu_memory_used() const { - size_t memsize = 0; - for (const GLVolume *volume : this->volumes) - memsize += volume->gpu_memory_used(); - return memsize; + size_t memsize = 0; + for (const GLVolume* volume : this->volumes) + memsize += volume->gpu_memory_used(); + return memsize; } std::string GLVolumeCollection::log_memory_info() const { - return " (GLVolumeCollection RAM: " + format_memsize_MB(this->cpu_memory_used()) + " GPU: " + format_memsize_MB(this->gpu_memory_used()) + " Both: " + format_memsize_MB(this->gpu_memory_used()) + ")"; + return " (GLVolumeCollection RAM: " + format_memsize_MB(this->cpu_memory_used()) + + " GPU: " + format_memsize_MB(this->gpu_memory_used()) + " Both: " + format_memsize_MB(this->gpu_memory_used()) + ")"; } -static void thick_lines_to_geometry( - const Lines& lines, - const std::vector& widths, - const std::vector& heights, - bool closed, - double top_z, - GUI::GLModel::Geometry& geometry) +static void thick_lines_to_geometry(const Lines& lines, + const std::vector& widths, + const std::vector& heights, + bool closed, + double top_z, + GUI::GLModel::Geometry& geometry) { assert(!lines.empty()); if (lines.empty()) return; - enum Direction : unsigned char - { - Left, - Right, - Top, - Bottom - }; + enum Direction : unsigned char { Left, Right, Top, Bottom }; // right, left, top, bottom - std::array idx_prev = { -1, -1, -1, -1 }; - std::array idx_initial = { -1, -1, -1, -1 }; + std::array idx_prev = {-1, -1, -1, -1}; + std::array idx_initial = {-1, -1, -1, -1}; double bottom_z_prev = 0.0; Vec2d b1_prev(Vec2d::Zero()); Vec2d v_prev(Vec2d::Zero()); - double len_prev = 0.0; - double width_initial = 0.0; + double len_prev = 0.0; + double width_initial = 0.0; double bottom_z_initial = 0.0; // loop once more in case of closed loops const size_t lines_end = closed ? (lines.size() + 1) : lines.size(); for (size_t ii = 0; ii < lines_end; ++ii) { - const size_t i = (ii == lines.size()) ? 0 : ii; - const Line& line = lines[i]; + const size_t i = (ii == lines.size()) ? 0 : ii; + const Line& line = lines[i]; const double bottom_z = top_z - heights[i]; const double middle_z = 0.5 * (top_z + bottom_z); - const double width = widths[i]; + const double width = widths[i]; - const bool is_first = (ii == 0); - const bool is_last = (ii == lines_end - 1); + const bool is_first = (ii == 0); + const bool is_last = (ii == lines_end - 1); const bool is_closing = closed && is_last; - const Vec2d v = unscale(line.vector()).normalized(); + const Vec2d v = unscale(line.vector()).normalized(); const double len = unscale(line.length()); - const Vec2d a = unscale(line.a); - const Vec2d b = unscale(line.b); - Vec2d a1 = a; - Vec2d a2 = a; - Vec2d b1 = b; - Vec2d b2 = b; + const Vec2d a = unscale(line.a); + const Vec2d b = unscale(line.b); + Vec2d a1 = a; + Vec2d a2 = a; + Vec2d b1 = b; + Vec2d b2 = b; { - const double dist = 0.5 * width; // scaled - const double dx = dist * v.x(); - const double dy = dist * v.y(); + const double dist = 0.5 * width; // scaled + const double dx = dist * v.x(); + const double dy = dist * v.y(); a1 += Vec2d(+dy, -dx); a2 += Vec2d(-dy, +dx); b1 += Vec2d(+dy, -dx); @@ -1404,12 +1371,12 @@ static void thick_lines_to_geometry( // calculate new XY normals const Vec2d xy_right_normal = unscale(line.normal()).normalized(); - std::array idx_a = { 0, 0, 0, 0 }; - std::array idx_b = { 0, 0, 0, 0 }; - int idx_last = int(geometry.vertices_count()); + std::array idx_a = {0, 0, 0, 0}; + std::array idx_b = {0, 0, 0, 0}; + int idx_last = int(geometry.vertices_count()); const bool bottom_z_different = bottom_z_prev != bottom_z; - bottom_z_prev = bottom_z; + bottom_z_prev = bottom_z; if (!is_first && bottom_z_different) { // Found a change of the layer thickness -> Add a cap at the end of the previous segment. @@ -1421,8 +1388,7 @@ static void thick_lines_to_geometry( if (is_first) { idx_a[Top] = idx_last++; geometry.add_vertex(Vec3f(a.x(), a.y(), top_z), Vec3f(0.0f, 0.0f, 1.0f)); - } - else + } else idx_a[Top] = idx_prev[Top]; if (is_first || bottom_z_different) { @@ -1433,22 +1399,20 @@ static void thick_lines_to_geometry( geometry.add_vertex(Vec3f(a2.x(), a2.y(), middle_z), Vec3f(-xy_right_normal.x(), -xy_right_normal.y(), 0.0f)); idx_a[Right] = idx_last++; geometry.add_vertex(Vec3f(a1.x(), a1.y(), middle_z), Vec3f(xy_right_normal.x(), xy_right_normal.y(), 0.0f)); - } - else + } else idx_a[Bottom] = idx_prev[Bottom]; if (is_first) { // Start of the 1st line segment. - width_initial = width; + width_initial = width; bottom_z_initial = bottom_z; - idx_initial = idx_a; - } - else { + idx_initial = idx_a; + } else { // Continuing a previous segment. // Share left / right vertices if possible. const double v_dot = v_prev.dot(v); // To reduce gpu memory usage, we try to reuse vertices - // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges + // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges // is longer than a fixed threshold. // The following value is arbitrary, it comes from tests made on a bunch of models showing the visual artifacts const double len_threshold = 2.5; @@ -1457,7 +1421,8 @@ static void thick_lines_to_geometry( const bool sharp = (v_dot < 0.707) || (len_prev > len_threshold) || (len > len_threshold); if (sharp) { if (!bottom_z_different) { - // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. + // Allocate new left / right points for the start of this segment as these points will receive their own normals to + // indicate a sharp turn. idx_a[Right] = idx_last++; geometry.add_vertex(Vec3f(a1.x(), a1.y(), middle_z), Vec3f(xy_right_normal.x(), xy_right_normal.y(), 0.0f)); idx_a[Left] = idx_last++; @@ -1466,15 +1431,13 @@ static void thick_lines_to_geometry( // Right turn. Fill in the right turn wedge. geometry.add_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]); geometry.add_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]); - } - else { + } else { // Left turn. Fill in the left turn wedge. geometry.add_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]); geometry.add_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]); } } - } - else { + } else { if (!bottom_z_different) { // The two successive segments are nearly collinear. idx_a[Left] = idx_prev[Left]; @@ -1485,18 +1448,20 @@ static void thick_lines_to_geometry( if (!sharp) { if (!bottom_z_different) { // Closing a loop with smooth transition. Unify the closing left / right vertices. - geometry.set_vertex(idx_initial[Left], geometry.extract_position_3(idx_prev[Left]), geometry.extract_normal_3(idx_prev[Left])); - geometry.set_vertex(idx_initial[Right], geometry.extract_position_3(idx_prev[Right]), geometry.extract_normal_3(idx_prev[Right])); + geometry.set_vertex(idx_initial[Left], geometry.extract_position_3(idx_prev[Left]), + geometry.extract_normal_3(idx_prev[Left])); + geometry.set_vertex(idx_initial[Right], geometry.extract_position_3(idx_prev[Right]), + geometry.extract_normal_3(idx_prev[Right])); geometry.remove_vertex(geometry.vertices_count() - 1); geometry.remove_vertex(geometry.vertices_count() - 1); // Replace the left / right vertex indices to point to the start of the loop. const size_t indices_count = geometry.indices_count(); for (size_t u = indices_count - 24; u < indices_count; ++u) { const unsigned int id = geometry.extract_index(u); - if (id == (unsigned int)idx_prev[Left]) - geometry.set_index(u, (unsigned int)idx_initial[Left]); - else if (id == (unsigned int)idx_prev[Right]) - geometry.set_index(u, (unsigned int)idx_initial[Right]); + if (id == (unsigned int) idx_prev[Left]) + geometry.set_index(u, (unsigned int) idx_initial[Left]); + else if (id == (unsigned int) idx_prev[Right]) + geometry.set_index(u, (unsigned int) idx_initial[Right]); } } } @@ -1525,11 +1490,11 @@ static void thick_lines_to_geometry( idx_b[Right] = idx_last++; geometry.add_vertex(Vec3f(b1.x(), b1.y(), middle_z), Vec3f(xy_right_normal.x(), xy_right_normal.y(), 0.0f)); - idx_prev = idx_b; + idx_prev = idx_b; bottom_z_prev = bottom_z; - b1_prev = b1; - v_prev = v; - len_prev = len; + b1_prev = b1; + v_prev = v; + len_prev = len; if (bottom_z_different && (closed || (!is_first && !is_last))) { // Found a change of the layer thickness -> Add a cap at the beginning of this segment. @@ -1567,73 +1532,65 @@ static void thick_lines_to_geometry( } // caller is responsible for supplying NO lines with zero length -static void thick_lines_to_geometry( - const Lines3& lines, - const std::vector& widths, - const std::vector& heights, - bool closed, - GUI::GLModel::Geometry& geometry) +static void thick_lines_to_geometry(const Lines3& lines, + const std::vector& widths, + const std::vector& heights, + bool closed, + GUI::GLModel::Geometry& geometry) { assert(!lines.empty()); if (lines.empty()) return; - enum Direction : unsigned char - { - Left, - Right, - Top, - Bottom - }; + enum Direction : unsigned char { Left, Right, Top, Bottom }; // left, right, top, bottom - std::array idx_prev = { -1, -1, -1, -1 }; - std::array idx_initial = { -1, -1, -1, -1 }; + std::array idx_prev = {-1, -1, -1, -1}; + std::array idx_initial = {-1, -1, -1, -1}; - double z_prev = 0.0; - double len_prev = 0.0; - Vec3d n_right_prev = Vec3d::Zero(); - Vec3d n_top_prev = Vec3d::Zero(); - Vec3d unit_v_prev = Vec3d::Zero(); + double z_prev = 0.0; + double len_prev = 0.0; + Vec3d n_right_prev = Vec3d::Zero(); + Vec3d n_top_prev = Vec3d::Zero(); + Vec3d unit_v_prev = Vec3d::Zero(); double width_initial = 0.0; // new vertices around the line endpoints // left, right, top, bottom - std::array a = { Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() }; - std::array b = { Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() }; + std::array a = {Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero()}; + std::array b = {Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero()}; // loop once more in case of closed loops const size_t lines_end = closed ? (lines.size() + 1) : lines.size(); for (size_t ii = 0; ii < lines_end; ++ii) { const size_t i = (ii == lines.size()) ? 0 : ii; - const Line3& line = lines[i]; + const Line3& line = lines[i]; const double height = heights[i]; - const double width = widths[i]; + const double width = widths[i]; - const Vec3d unit_v = unscale(line.vector()).normalized(); - const double len = unscale(line.length()); + const Vec3d unit_v = unscale(line.vector()).normalized(); + const double len = unscale(line.length()); - Vec3d n_top = Vec3d::Zero(); + Vec3d n_top = Vec3d::Zero(); Vec3d n_right = Vec3d::Zero(); if (line.a.x() == line.b.x() && line.a.y() == line.b.y()) { // vertical segment - n_top = Vec3d::UnitY(); + n_top = Vec3d::UnitY(); n_right = Vec3d::UnitX(); if (line.a.z() < line.b.z()) n_right = -n_right; - } - else { + } else { // horizontal segment n_right = unit_v.cross(Vec3d::UnitZ()).normalized(); - n_top = n_right.cross(unit_v).normalized(); + n_top = n_right.cross(unit_v).normalized(); } const Vec3d rl_displacement = 0.5 * width * n_right; const Vec3d tb_displacement = 0.5 * height * n_top; - const Vec3d l_a = unscale(line.a); - const Vec3d l_b = unscale(line.b); + const Vec3d l_a = unscale(line.a); + const Vec3d l_b = unscale(line.b); a[Right] = l_a + rl_displacement; a[Left] = l_a - rl_displacement; @@ -1645,48 +1602,45 @@ static void thick_lines_to_geometry( b[Bottom] = l_b - tb_displacement; const Vec3d n_bottom = -n_top; - const Vec3d n_left = -n_right; + const Vec3d n_left = -n_right; - std::array idx_a = { 0, 0, 0, 0}; - std::array idx_b = { 0, 0, 0, 0 }; - int idx_last = int(geometry.vertices_count()); + std::array idx_a = {0, 0, 0, 0}; + std::array idx_b = {0, 0, 0, 0}; + int idx_last = int(geometry.vertices_count()); const bool z_different = (z_prev != l_a.z()); - z_prev = l_b.z(); + z_prev = l_b.z(); // Share top / bottom vertices if possible. if (ii == 0) { idx_a[Top] = idx_last++; - geometry.add_vertex((Vec3f)a[Top].cast(), (Vec3f)n_top.cast()); - } - else + geometry.add_vertex((Vec3f) a[Top].cast(), (Vec3f) n_top.cast()); + } else idx_a[Top] = idx_prev[Top]; if (ii == 0 || z_different) { // Start of the 1st line segment or a change of the layer thickness while maintaining the print_z. idx_a[Bottom] = idx_last++; - geometry.add_vertex((Vec3f)a[Bottom].cast(), (Vec3f)n_bottom.cast()); + geometry.add_vertex((Vec3f) a[Bottom].cast(), (Vec3f) n_bottom.cast()); idx_a[Left] = idx_last++; - geometry.add_vertex((Vec3f)a[Left].cast(), (Vec3f)n_left.cast()); + geometry.add_vertex((Vec3f) a[Left].cast(), (Vec3f) n_left.cast()); idx_a[Right] = idx_last++; - geometry.add_vertex((Vec3f)a[Right].cast(), (Vec3f)n_right.cast()); - } - else + geometry.add_vertex((Vec3f) a[Right].cast(), (Vec3f) n_right.cast()); + } else idx_a[Bottom] = idx_prev[Bottom]; if (ii == 0) { // Start of the 1st line segment. width_initial = width; - idx_initial = idx_a; - } - else { + idx_initial = idx_a; + } else { // Continuing a previous segment. // Share left / right vertices if possible. - const double v_dot = unit_v_prev.dot(unit_v); - const bool is_right_turn = n_top_prev.dot(unit_v_prev.cross(unit_v)) > 0.0; + const double v_dot = unit_v_prev.dot(unit_v); + const bool is_right_turn = n_top_prev.dot(unit_v_prev.cross(unit_v)) > 0.0; // To reduce gpu memory usage, we try to reuse vertices - // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges + // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges // is longer than a fixed threshold. // The following value is arbitrary, it comes from tests made on a bunch of models showing the visual artifacts const double len_threshold = 2.5; @@ -1694,44 +1648,45 @@ static void thick_lines_to_geometry( // Generate new vertices if the angle between adjacent edges is greater than 45 degrees or thresholds conditions are met const bool is_sharp = v_dot < 0.707 || len_prev > len_threshold || len > len_threshold; if (is_sharp) { - // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. + // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate + // a sharp turn. idx_a[Right] = idx_last++; - geometry.add_vertex((Vec3f)a[Right].cast(), (Vec3f)n_right.cast()); + geometry.add_vertex((Vec3f) a[Right].cast(), (Vec3f) n_right.cast()); idx_a[Left] = idx_last++; - geometry.add_vertex((Vec3f)a[Left].cast(), (Vec3f)n_left.cast()); + geometry.add_vertex((Vec3f) a[Left].cast(), (Vec3f) n_left.cast()); if (is_right_turn) { // Right turn. Fill in the right turn wedge. geometry.add_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]); geometry.add_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]); - } - else { + } else { // Left turn. Fill in the left turn wedge. geometry.add_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]); geometry.add_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]); } - } - else { + } else { // The two successive segments are nearly collinear. - idx_a[Left] = idx_prev[Left]; + idx_a[Left] = idx_prev[Left]; idx_a[Right] = idx_prev[Right]; } if (ii == lines.size()) { if (!is_sharp) { // Closing a loop with smooth transition. Unify the closing left / right vertices. - geometry.set_vertex(idx_initial[Left], geometry.extract_position_3(idx_prev[Left]), geometry.extract_normal_3(idx_prev[Left])); - geometry.set_vertex(idx_initial[Right], geometry.extract_position_3(idx_prev[Right]), geometry.extract_normal_3(idx_prev[Right])); + geometry.set_vertex(idx_initial[Left], geometry.extract_position_3(idx_prev[Left]), + geometry.extract_normal_3(idx_prev[Left])); + geometry.set_vertex(idx_initial[Right], geometry.extract_position_3(idx_prev[Right]), + geometry.extract_normal_3(idx_prev[Right])); geometry.remove_vertex(geometry.vertices_count() - 1); geometry.remove_vertex(geometry.vertices_count() - 1); // Replace the left / right vertex indices to point to the start of the loop. const size_t indices_count = geometry.indices_count(); for (size_t u = indices_count - 24; u < indices_count; ++u) { const unsigned int id = geometry.extract_index(u); - if (id == (unsigned int)idx_prev[Left]) - geometry.set_index(u, (unsigned int)idx_initial[Left]); - else if (id == (unsigned int)idx_prev[Right]) - geometry.set_index(u, (unsigned int)idx_initial[Right]); + if (id == (unsigned int) idx_prev[Left]) + geometry.set_index(u, (unsigned int) idx_initial[Left]); + else if (id == (unsigned int) idx_prev[Right]) + geometry.set_index(u, (unsigned int) idx_initial[Right]); } } @@ -1745,27 +1700,27 @@ static void thick_lines_to_geometry( idx_b[Top] = idx_initial[Top]; else { idx_b[Top] = idx_last++; - geometry.add_vertex((Vec3f)b[Top].cast(), (Vec3f)n_top.cast()); + geometry.add_vertex((Vec3f) b[Top].cast(), (Vec3f) n_top.cast()); } if (closed && ii + 1 == lines.size() && width == width_initial) idx_b[Bottom] = idx_initial[Bottom]; else { idx_b[Bottom] = idx_last++; - geometry.add_vertex((Vec3f)b[Bottom].cast(), (Vec3f)n_bottom.cast()); + geometry.add_vertex((Vec3f) b[Bottom].cast(), (Vec3f) n_bottom.cast()); } // Generate new vertices for the end of this line segment. idx_b[Left] = idx_last++; - geometry.add_vertex((Vec3f)b[Left].cast(), (Vec3f)n_left.cast()); + geometry.add_vertex((Vec3f) b[Left].cast(), (Vec3f) n_left.cast()); idx_b[Right] = idx_last++; - geometry.add_vertex((Vec3f)b[Right].cast(), (Vec3f)n_right.cast()); + geometry.add_vertex((Vec3f) b[Right].cast(), (Vec3f) n_right.cast()); - idx_prev = idx_b; + idx_prev = idx_b; n_right_prev = n_right; - n_top_prev = n_top; - unit_v_prev = unit_v; - len_prev = len; + n_top_prev = n_top; + unit_v_prev = unit_v; + len_prev = len; if (!closed) { // Terminate open paths with caps. @@ -1797,47 +1752,51 @@ static void thick_lines_to_geometry( } } -void _3DScene::thick_lines_to_verts( - const Lines& lines, - const std::vector& widths, - const std::vector& heights, - bool closed, - double top_z, - GUI::GLModel::Geometry& geometry) +void _3DScene::thick_lines_to_verts(const Lines& lines, + const std::vector& widths, + const std::vector& heights, + bool closed, + double top_z, + GUI::GLModel::Geometry& geometry) { thick_lines_to_geometry(lines, widths, heights, closed, top_z, geometry); } -void _3DScene::thick_lines_to_verts( - const Lines3& lines, - const std::vector& widths, - const std::vector& heights, - bool closed, - GUI::GLModel::Geometry& geometry) +void _3DScene::thick_lines_to_verts(const Lines3& lines, + const std::vector& widths, + const std::vector& heights, + bool closed, + GUI::GLModel::Geometry& geometry) { thick_lines_to_geometry(lines, widths, heights, closed, geometry); } // Fill in the qverts and tverts with quads and triangles for the extrusion_path. -void _3DScene::extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry) +void _3DScene::extrusionentity_to_verts(const ExtrusionPath& extrusion_path, + float print_z, + const Point& copy, + GUI::GLModel::Geometry& geometry) { - Polyline polyline = extrusion_path.polyline; + Polyline polyline = extrusion_path.polyline; polyline.remove_duplicate_points(); polyline.translate(copy); - const Lines lines = polyline.lines(); + const Lines lines = polyline.lines(); std::vector widths(lines.size(), extrusion_path.width); std::vector heights(lines.size(), extrusion_path.height); thick_lines_to_verts(lines, widths, heights, false, print_z, geometry); } // Fill in the qverts and tverts with quads and triangles for the extrusion_loop. -void _3DScene::extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry) +void _3DScene::extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, + float print_z, + const Point& copy, + GUI::GLModel::Geometry& geometry) { Lines lines; std::vector widths; std::vector heights; for (const ExtrusionPath& extrusion_path : extrusion_loop.paths) { - Polyline polyline = extrusion_path.polyline; + Polyline polyline = extrusion_path.polyline; polyline.remove_duplicate_points(); polyline.translate(copy); const Lines lines_this = polyline.lines(); @@ -1849,13 +1808,16 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, flo } // Fill in the qverts and tverts with quads and triangles for the extrusion_multi_path. -void _3DScene::extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry) +void _3DScene::extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, + float print_z, + const Point& copy, + GUI::GLModel::Geometry& geometry) { Lines lines; std::vector widths; std::vector heights; for (const ExtrusionPath& extrusion_path : extrusion_multi_path.paths) { - Polyline polyline = extrusion_path.polyline; + Polyline polyline = extrusion_path.polyline; polyline.remove_duplicate_points(); polyline.translate(copy); const Lines lines_this = polyline.lines(); @@ -1866,13 +1828,19 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_mult thick_lines_to_verts(lines, widths, heights, false, print_z, geometry); } -void _3DScene::extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry) +void _3DScene::extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, + float print_z, + const Point& copy, + GUI::GLModel::Geometry& geometry) { for (const ExtrusionEntity* extrusion_entity : extrusion_entity_collection.entities) extrusionentity_to_verts(extrusion_entity, print_z, copy, geometry); } -void _3DScene::extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry) +void _3DScene::extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, + float print_z, + const Point& copy, + GUI::GLModel::Geometry& geometry) { if (extrusion_entity != nullptr) { auto* extrusion_path = dynamic_cast(extrusion_entity); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 40eb928c2b..9a67b0bcce 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -9706,9 +9706,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) break; // Snapmaker: 螺旋抬升靠近边界警告 case EWarning::SpiralLiftNearBoundary: - text = _u8L("An object is too close to the plate boundary. " - "Spiral lift during printing may exceed the bed and cause a crash. " - "Please move the object away from the edge (recommend keeping at least 3mm distance)."); + text = _u8L("Model too close to bed boundary. Disable spiral lifting or keep at least 3.5mm gap to avoid collision."); error = ErrorType::SLICING_SERIOUS_WARNING; break; }