diff --git a/resources/icons/legend_cog.svg b/resources/icons/legend_cog.svg new file mode 100644 index 000000000..9a55fb7f5 --- /dev/null +++ b/resources/icons/legend_cog.svg @@ -0,0 +1,50 @@ + + + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon + + diff --git a/resources/shaders/toolpaths_cog.fs b/resources/shaders/toolpaths_cog.fs new file mode 100644 index 000000000..f88d79b96 --- /dev/null +++ b/resources/shaders/toolpaths_cog.fs @@ -0,0 +1,18 @@ +#version 110 + +const vec4 BLACK = vec4(vec3(0.1), 1.0); +const vec4 WHITE = vec4(vec3(1.0), 1.0); + +const float emission_factor = 0.25; + +// x = tainted, y = specular; +varying vec2 intensity; +varying vec3 world_position; +uniform vec3 world_center; + +void main() +{ + vec3 delta = world_position - world_center; + vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE; + gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0); +} diff --git a/resources/shaders/toolpaths_cog.vs b/resources/shaders/toolpaths_cog.vs new file mode 100644 index 000000000..c7b1abfdb --- /dev/null +++ b/resources/shaders/toolpaths_cog.vs @@ -0,0 +1,40 @@ +#version 110 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +// x = tainted, y = specular; +varying vec2 intensity; +varying vec3 world_position; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(gl_NormalMatrix * gl_Normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + world_position = gl_Vertex.xyz; + gl_Position = ftransform(); +} diff --git a/src/imgui/imconfig.h b/src/imgui/imconfig.h index db0e54e60..f2c3ef083 100644 --- a/src/imgui/imconfig.h +++ b/src/imgui/imconfig.h @@ -165,8 +165,9 @@ namespace ImGui const wchar_t LegendColorChanges = 0x2612; const wchar_t LegendPausePrints = 0x2613; const wchar_t LegendCustomGCodes = 0x2614; - const wchar_t LegendShells = 0x2615; - const wchar_t LegendToolMarker = 0x2616; + const wchar_t LegendCOG = 0x2615; + const wchar_t LegendShells = 0x2616; + const wchar_t LegendToolMarker = 0x2617; // void MyFunction(const char* name, const MyMatrix44& v); } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index da55ae4ff..6b4274b11 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -68,10 +68,14 @@ #define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable removal of old OpenGL render calls #define ENABLE_GLBEGIN_GLEND_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) +// Enable replace GLIndexedVertexArray with GLModel +#define ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL (1 && ENABLE_GLBEGIN_GLEND_REMOVAL) // Enable show non-manifold edges #define ENABLE_SHOW_NON_MANIFOLD_EDGES (1 && ENABLE_2_5_0_ALPHA1) // Enable rework of Reload from disk command #define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_5_0_ALPHA1) +// Enable showing toolpaths center of gravity +#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index c8ca2397b..8488c1148 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -311,10 +311,11 @@ void Bed3D::init_triangles() if (triangles.empty() || triangles.size() % 3 != 0) return; - const GLModel::Geometry::EIndexType index_type = (triangles.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; - GLModel::Geometry init_data; + const GLModel::Geometry::EIndexType index_type = (triangles.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2, index_type }; + init_data.reserve_vertices(triangles.size()); + init_data.reserve_indices(triangles.size() / 3); Vec2f min = triangles.front(); Vec2f max = min; @@ -330,6 +331,7 @@ void Bed3D::init_triangles() Vec2f inv_size = size.cwiseInverse(); inv_size.y() *= -1.0f; + // vertices + indices unsigned int vertices_counter = 0; for (const Vec2f& v : triangles) { const Vec3f p = { v.x(), v.y(), GROUND_Z }; @@ -378,10 +380,11 @@ void Bed3D::init_gridlines() Lines contour_lines = to_lines(m_contour); std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines)); - const GLModel::Geometry::EIndexType index_type = (gridlines.size() < 65536 / 2) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; - GLModel::Geometry init_data; + const GLModel::Geometry::EIndexType index_type = (2 * gridlines.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, index_type }; + init_data.reserve_vertices(2 * gridlines.size()); + init_data.reserve_indices(2 * gridlines.size()); for (const Line& l : gridlines) { init_data.add_vertex(Vec3f(unscale(l.a.x()), unscale(l.a.y()), GROUND_Z)); @@ -701,7 +704,9 @@ void Bed3D::render_default(bool bottom, bool picking) glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - if (m_model.get_filename().empty() && !bottom) { + const bool has_model = !m_model.get_filename().empty(); + + if (!has_model && !bottom) { // draw background glsafe(::glDepthMask(GL_FALSE)); m_triangles.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); @@ -712,7 +717,7 @@ void Bed3D::render_default(bool bottom, bool picking) if (!picking) { // draw grid glsafe(::glLineWidth(1.5f * m_scale_factor)); - m_gridlines.set_color(picking ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR); + m_gridlines.set_color(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR); m_gridlines.render(); } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 4e929d060..339754790 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -326,8 +326,8 @@ void GLVolume::SinkingContours::update() for (const ExPolygon& expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) { #if ENABLE_GLBEGIN_GLEND_REMOVAL const std::vector triangulation = triangulate_expolygon_3d(expoly); - init_data.vertices.reserve(init_data.vertices.size() + triangulation.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(init_data.indices.size() + triangulation.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format)); + 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 ++vertices_counter; @@ -400,9 +400,10 @@ void GLVolume::NonManifoldEdges::update() if (!edges.empty()) { GUI::GLModel::Geometry init_data; #if ENABLE_GLBEGIN_GLEND_REMOVAL - init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Lines, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::EIndexType::UINT }; - init_data.vertices.reserve(2 * edges.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * edges.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format)); + const GUI::GLModel::Geometry::EIndexType index_type = (2 * edges.size() < 65536) ? GUI::GLModel::Geometry::EIndexType::USHORT : GUI::GLModel::Geometry::EIndexType::UINT; + init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Lines, GUI::GLModel::Geometry::EVertexLayout::P3, index_type }; + init_data.reserve_vertices(2 * edges.size()); + init_data.reserve_indices(2 * edges.size()); // vertices + indices unsigned int vertices_count = 0; @@ -410,7 +411,10 @@ void GLVolume::NonManifoldEdges::update() init_data.add_vertex((Vec3f)mesh.its.vertices[edge.first].cast()); init_data.add_vertex((Vec3f)mesh.its.vertices[edge.second].cast()); vertices_count += 2; - init_data.add_uint_line(vertices_count - 2, vertices_count - 1); + if (index_type == GUI::GLModel::Geometry::EIndexType::USHORT) + init_data.add_ushort_line((unsigned short)vertices_count - 2, (unsigned short)vertices_count - 1); + else + init_data.add_uint_line(vertices_count - 2, vertices_count - 1); } m_model.init_from(std::move(init_data)); #else diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 367846f0c..a4808a0cf 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -160,6 +160,66 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move move.volumetric_rate(), move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } }); } +#if ENABLE_SHOW_TOOLPATHS_COG +void GCodeViewer::COG::render() +{ + if (!m_visible) + return; + + init(); + + GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog"); + if (shader == nullptr) + return; + + shader->start_using(); + + glsafe(::glDisable(GL_DEPTH_TEST)); + + glsafe(::glPushMatrix()); + const Vec3d position = cog(); + glsafe(::glTranslated(position.x(), position.y(), position.z())); + if (m_fixed_size) { + const double inv_zoom = wxGetApp().plater()->get_camera().get_inv_zoom(); + glsafe(::glScaled(inv_zoom, inv_zoom, inv_zoom)); + } + m_model.render(); + + glsafe(::glPopMatrix()); + + shader->stop_using(); + + ////Show ImGui window + //static float last_window_width = 0.0f; + //static size_t last_text_length = 0; + + //ImGuiWrapper& imgui = *wxGetApp().imgui(); + //const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); + //imgui.set_next_window_pos(0.5f * static_cast(cnv_size.get_width()), 0.0f, ImGuiCond_Always, 0.5f, 0.0f); + //ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + //ImGui::SetNextWindowBgAlpha(0.25f); + //imgui.begin(std::string("COG"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); + //imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Center of mass") + ":"); + //ImGui::SameLine(); + //char buf[1024]; + //const Vec3d position = cog(); + //sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", position.x(), position.y(), position.z()); + //imgui.text(std::string(buf)); + + //// force extra frame to automatically update window size + //const float width = ImGui::GetWindowWidth(); + //const size_t length = strlen(buf); + //if (width != last_window_width || length != last_text_length) { + // last_window_width = width; + // last_text_length = length; + // imgui.set_requires_extra_frame(); + //} + + //imgui.end(); + //ImGui::PopStyleVar(); +} +#endif // ENABLE_SHOW_TOOLPATHS_COG + #if ENABLE_PREVIEW_LAYER_TIME float GCodeViewer::Extrusions::Range::step_size(EType type) const { @@ -955,6 +1015,9 @@ unsigned int GCodeViewer::get_options_visibility_flags() const flags = set_flag(flags, static_cast(Preview::OptionType::ColorChanges), is_toolpath_move_type_visible(EMoveType::Color_change)); flags = set_flag(flags, static_cast(Preview::OptionType::PausePrints), is_toolpath_move_type_visible(EMoveType::Pause_Print)); flags = set_flag(flags, static_cast(Preview::OptionType::CustomGCodes), is_toolpath_move_type_visible(EMoveType::Custom_GCode)); +#if ENABLE_SHOW_TOOLPATHS_COG + flags = set_flag(flags, static_cast(Preview::OptionType::CenterOfGravity), m_cog.is_visible()); +#endif // ENABLE_SHOW_TOOLPATHS_COG flags = set_flag(flags, static_cast(Preview::OptionType::Shells), m_shells.visible); flags = set_flag(flags, static_cast(Preview::OptionType::ToolMarker), m_sequential_view.marker.is_visible()); #if !ENABLE_PREVIEW_LAYOUT @@ -978,6 +1041,9 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags) set_toolpath_move_type_visible(EMoveType::Color_change, is_flag_set(static_cast(Preview::OptionType::ColorChanges))); set_toolpath_move_type_visible(EMoveType::Pause_Print, is_flag_set(static_cast(Preview::OptionType::PausePrints))); set_toolpath_move_type_visible(EMoveType::Custom_GCode, is_flag_set(static_cast(Preview::OptionType::CustomGCodes))); +#if ENABLE_SHOW_TOOLPATHS_COG + m_cog.set_visible(is_flag_set(static_cast(Preview::OptionType::CenterOfGravity))); +#endif // ENABLE_SHOW_TOOLPATHS_COG m_shells.visible = is_flag_set(static_cast(Preview::OptionType::Shells)); m_sequential_view.marker.set_visible(is_flag_set(static_cast(Preview::OptionType::ToolMarker))); #if !ENABLE_PREVIEW_LAYOUT @@ -1537,6 +1603,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) if (wxGetApp().is_editor()) m_contained_in_bed = wxGetApp().plater()->build_volume().all_paths_inside(gcode_result, m_paths_bounding_box); +#if ENABLE_SHOW_TOOLPATHS_COG + m_cog.reset(); +#endif // ENABLE_SHOW_TOOLPATHS_COG + m_sequential_view.gcode_ids.clear(); for (size_t i = 0; i < gcode_result.moves.size(); ++i) { const GCodeProcessorResult::MoveVertex& move = gcode_result.moves[i]; @@ -1551,18 +1621,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) std::vector instances_offsets(m_buffers.size()); std::vector options_zs; - size_t seams_count = 0; std::vector biased_seams_ids; // toolpaths data -> extract vertices from result for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i]; - if (curr.type == EMoveType::Seam) { - ++seams_count; + if (curr.type == EMoveType::Seam) biased_seams_ids.push_back(i - biased_seams_ids.size() - 1); - } - size_t move_id = i - seams_count; + const size_t move_id = i - biased_seams_ids.size(); // skip first vertex if (i == 0) @@ -1570,6 +1637,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) const GCodeProcessorResult::MoveVertex& prev = gcode_result.moves[i - 1]; +#if ENABLE_SHOW_TOOLPATHS_COG + if (curr.type == EMoveType::Extrude && + curr.extrusion_role != erSkirt && + curr.extrusion_role != erSupportMaterial && + curr.extrusion_role != erSupportMaterialInterface && + curr.extrusion_role != erWipeTower && + curr.extrusion_role != erCustom && + curr.extrusion_role != erMixed) { + const Vec3d curr_pos = curr.position.cast(); + const Vec3d prev_pos = prev.position.cast(); + m_cog.add_segment(curr_pos, prev_pos, curr.mm3_per_mm * (curr_pos - prev_pos).norm()); + } +#endif // ENABLE_SHOW_TOOLPATHS_COG + // update progress dialog ++progress_count; if (progress_dialog != nullptr && progress_count % progress_threshold == 0) { @@ -1893,14 +1974,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) using VboIndexList = std::vector; std::vector vbo_indices(m_buffers.size()); - seams_count = 0; + size_t seams_count = 0; for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i]; if (curr.type == EMoveType::Seam) ++seams_count; - size_t move_id = i - seams_count; + const size_t move_id = i - seams_count; // skip first vertex if (i == 0) @@ -4074,15 +4155,6 @@ void GCodeViewer::render_legend(float& legend_height) }; #if ENABLE_LEGEND_TOOLBAR_ICONS -// auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { -// const float margin = 3.0f; -// const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); -// window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); -// }; -// auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { -// const float margin = 3.0f; -// window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); -// }; auto image_icon = [&imgui](ImGuiWindow& window, const ImVec2& pos, float size, const wchar_t& icon_id) { ImGuiIO& io = ImGui::GetIO(); const ImTextureID tex_id = io.Fonts->TexID; @@ -4091,17 +4163,17 @@ void GCodeViewer::render_legend(float& legend_height) const ImFontAtlas::CustomRect* const rect = imgui.GetTextureCustomRect(icon_id); const ImVec2 uv0 = { static_cast(rect->X) / tex_w, static_cast(rect->Y) / tex_h }; const ImVec2 uv1 = { static_cast(rect->X + rect->Width) / tex_w, static_cast(rect->Y + rect->Height) / tex_h }; - window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f })); + window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f })); }; #else - auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { - const float margin = 3.0f; + auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const ColorRGBA& color) { + const float margin = 3.0f; const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); - window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); + window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGuiWrapper::to_ImU32(color), 16); }; - auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { + auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const ColorRGBA& color) { const float margin = 3.0f; - window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); + window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGuiWrapper::to_ImU32(color), 3.0f); }; #endif // ENABLE_LEGEND_TOOLBAR_ICONS @@ -4190,12 +4262,41 @@ void GCodeViewer::render_legend(float& legend_height) #endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_SHOW_TOOLPATHS_COG +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::CenterOfGravity, _u8L("Center of gravity"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendCOG); + }); +#else + toggle_button(Preview::OptionType::CenterOfGravity, _u8L("Center of gravity"), [](ImGuiWindow& window, const ImVec2& pos, float size) { + const ImU32 black = ImGuiWrapper::to_ImU32({ 0.0f, 0.0f, 0.0f, 1.0f }); + const ImU32 white = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f }); + const float margin = 3.0f; + const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); + const float radius = 0.5f * (size - 2.0f * margin); + window.DrawList->PathArcToFast(center, radius, 0, 3); + window.DrawList->PathLineTo(center); + window.DrawList->PathFillConvex(black); + window.DrawList->PathArcToFast(center, radius, 3, 6); + window.DrawList->PathLineTo(center); + window.DrawList->PathFillConvex(white); + window.DrawList->PathArcToFast(center, radius, 6, 9); + window.DrawList->PathLineTo(center); + window.DrawList->PathFillConvex(black); + window.DrawList->PathArcToFast(center, radius, 9, 12); + window.DrawList->PathLineTo(center); + window.DrawList->PathFillConvex(white); + window.DrawList->AddCircle(center, radius, black, 16); + }); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS + ImGui::SameLine(); +#endif // ENABLE_SHOW_TOOLPATHS_COG #if ENABLE_LEGEND_TOOLBAR_ICONS toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { image_icon(window, pos, size, ImGui::LegendShells); #else toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) { - const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f }); + const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f }); const float margin = 3.0f; const float proj = 0.25f * size; window.DrawList->AddRect({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin - proj, pos.y + margin + proj }, color); @@ -4212,11 +4313,11 @@ void GCodeViewer::render_legend(float& legend_height) image_icon(window, pos, size, ImGui::LegendToolMarker); #else toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [](ImGuiWindow& window, const ImVec2& pos, float size) { - const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.8f }); + const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 0.8f }); const float margin = 3.0f; const ImVec2 p1(0.5f * (pos.x + pos.x + size), pos.y + size - margin); - const ImVec2 p2 = ImVec2(p1.x + 0.25f * size, p1.y - 0.25f * size); - const ImVec2 p3 = ImVec2(p1.x - 0.25f * size, p1.y - 0.25f * size); + const ImVec2 p2(p1.x + 0.25f * size, p1.y - 0.25f * size); + const ImVec2 p3(p1.x - 0.25f * size, p1.y - 0.25f * size); window.DrawList->AddTriangleFilled(p1, p2, p3, color); const float mid_x = 0.5f * (pos.x + pos.x + size); window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index ecebb2641..22e866fe6 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -380,6 +380,52 @@ class GCodeViewer bool visible{ false }; }; +#if ENABLE_SHOW_TOOLPATHS_COG + // helper to render center of gravity + class COG + { + GLModel m_model; + bool m_visible{ false }; + // whether or not to render the model with fixed screen size + bool m_fixed_size{ true }; + double m_total_mass{ 0.0 }; + Vec3d m_position{ Vec3d::Zero() }; + + public: + void render(); + + void reset() { + m_position = Vec3d::Zero(); + m_total_mass = 0.0; + } + + bool is_visible() const { return m_visible; } + void set_visible(bool visible) { m_visible = visible; } + + void add_segment(const Vec3d& v1, const Vec3d& v2, double mass) { + assert(mass > 0.0); + m_position += mass * 0.5 * (v1 + v2); + m_total_mass += mass; + } + + Vec3d cog() const { return (m_total_mass > 0.0) ? (Vec3d)(m_position / m_total_mass) : Vec3d::Zero(); } + + private: + void init() { + if (m_model.is_initialized()) + return; + + const float radius = m_fixed_size ? 10.0f : 1.0f; + +#if ENABLE_GLBEGIN_GLEND_REMOVAL + m_model.init_from(smooth_sphere(32, radius)); +#else + m_model.init_from(its_make_sphere(radius, PI / 32.0)); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + } + }; +#endif // ENABLE_SHOW_TOOLPATHS_COG + // helper to render extrusion paths struct Extrusions { @@ -734,6 +780,9 @@ private: Extrusions m_extrusions; SequentialView m_sequential_view; Shells m_shells; +#if ENABLE_SHOW_TOOLPATHS_COG + COG m_cog; +#endif // ENABLE_SHOW_TOOLPATHS_COG EViewType m_view_type{ EViewType::FeatureType }; bool m_legend_enabled{ true }; #if ENABLE_PREVIEW_LAYOUT @@ -779,6 +828,9 @@ public: void reset(); void render(); +#if ENABLE_SHOW_TOOLPATHS_COG + void render_cog() { m_cog.render(); } +#endif // ENABLE_SHOW_TOOLPATHS_COG bool has_data() const { return !m_roles.empty(); } bool can_export_toolpaths() const; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 84cc2e555..95600c074 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -368,8 +368,8 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3 GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices const float l = bar_rect.get_left(); @@ -428,8 +428,8 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; init_data.color = ColorRGBA::BLACK(); - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; @@ -447,16 +447,20 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) m_profile.profile.reset(); GLModel::Geometry init_data; - init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::UINT }; + const GLModel::Geometry::EIndexType index_type = (m_layer_height_profile.size() / 2 < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2, index_type }; init_data.color = ColorRGBA::BLUE(); - init_data.vertices.reserve(m_layer_height_profile.size() * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(m_layer_height_profile.size() * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(m_layer_height_profile.size() / 2); + init_data.reserve_indices(m_layer_height_profile.size() / 2); // vertices + indices for (unsigned int i = 0; i < (unsigned int)m_layer_height_profile.size(); i += 2) { init_data.add_vertex(Vec2f(bar_rect.get_left() + float(m_layer_height_profile[i + 1]) * scale_x, bar_rect.get_bottom() + float(m_layer_height_profile[i]) * scale_y)); - init_data.add_uint_index(i / 2); + if (index_type == GLModel::Geometry::EIndexType::USHORT) + init_data.add_ushort_index((unsigned short)i / 2); + else + init_data.add_uint_index(i / 2); } m_profile.profile.init_from(std::move(init_data)); @@ -898,6 +902,8 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons unsigned int vertices_counter = 0; for (const ExPolygon& poly : polygons_union) { const std::vector triangulation = triangulate_expolygon_3d(poly); + fill_data.reserve_vertices(fill_data.vertices_count() + triangulation.size()); + fill_data.reserve_indices(fill_data.indices_count() + triangulation.size()); for (const Vec3d& v : triangulation) { fill_data.add_vertex((Vec3f)(v.cast() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting ++vertices_counter; @@ -1600,6 +1606,10 @@ void GLCanvas3D::render() #if ENABLE_RENDER_SELECTION_CENTER _render_selection_center(); #endif // ENABLE_RENDER_SELECTION_CENTER +#if ENABLE_SHOW_TOOLPATHS_COG + if (!m_main_toolbar.is_enabled()) + _render_gcode_cog(); +#endif // ENABLE_SHOW_TOOLPATHS_COG // we need to set the mouse's scene position here because the depth buffer // could be invalidated by the following gizmo render methods @@ -5234,8 +5244,8 @@ void GLCanvas3D::_render_background() GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices init_data.add_vertex(Vec2f(-1.0f, -1.0f), Vec2f(0.0f, 0.0f)); @@ -5415,6 +5425,13 @@ void GLCanvas3D::_render_gcode() m_gcode_viewer.render(); } +#if ENABLE_SHOW_TOOLPATHS_COG +void GLCanvas3D::_render_gcode_cog() +{ + m_gcode_viewer.render_cog(); +} +#endif // ENABLE_SHOW_TOOLPATHS_COG + void GLCanvas3D::_render_selection() { float scale_factor = 1.0; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 93cd8f424..33e17d5dd 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -938,6 +938,9 @@ private: void _render_bed_for_picking(bool bottom); void _render_objects(GLVolumeCollection::ERenderType type); void _render_gcode(); +#if ENABLE_SHOW_TOOLPATHS_COG + void _render_gcode_cog(); +#endif // ENABLE_SHOW_TOOLPATHS_COG void _render_selection(); void _render_sequential_clearance(); #if ENABLE_RENDER_SELECTION_CENTER diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 8ac1e5534..e1dc3305c 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -18,6 +18,16 @@ namespace Slic3r { namespace GUI { #if ENABLE_GLBEGIN_GLEND_REMOVAL +void GLModel::Geometry::reserve_vertices(size_t vertices_count) +{ + vertices.reserve(vertices_count * vertex_stride_floats(format)); +} + +void GLModel::Geometry::reserve_indices(size_t indices_count) +{ + indices.reserve(indices_count * index_stride_bytes(format)); +} + void GLModel::Geometry::add_vertex(const Vec2f& position) { assert(format.vertex_layout == EVertexLayout::P2); @@ -470,8 +480,8 @@ void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bb Geometry& data = m_render_data.geometry; data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, Geometry::EIndexType::UINT }; - data.vertices.reserve(3 * its.indices.size() * Geometry::vertex_stride_floats(data.format)); - data.indices.reserve(3 * its.indices.size() * Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(3 * its.indices.size()); + data.reserve_indices(3 * its.indices.size()); // vertices + indices unsigned int vertices_counter = 0; @@ -552,8 +562,8 @@ void GLModel::init_from(const Polygons& polygons, float z) segments_count += polygon.points.size(); } - data.vertices.reserve(2 * segments_count * Geometry::vertex_stride_floats(data.format)); - data.indices.reserve(2 * segments_count * Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(2 * segments_count); + data.reserve_indices(2 * segments_count); // vertices + indices unsigned int vertices_counter = 0; @@ -720,8 +730,8 @@ void GLModel::render() const const Geometry& data = m_render_data.geometry; - GLenum mode = get_primitive_mode(data.format); - GLenum index_type = get_index_type(data.format); + const GLenum mode = get_primitive_mode(data.format); + const GLenum index_type = get_index_type(data.format); const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); const bool position = Geometry::has_position(data.format); @@ -1034,8 +1044,8 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl GLModel::Geometry data; #if ENABLE_GLBEGIN_GLEND_REMOVAL data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; - data.vertices.reserve((6 * resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format)); - data.indices.reserve((6 * resolution * 3) * GLModel::Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(6 * resolution + 2); + data.reserve_indices(6 * resolution * 3); #else GLModel::Geometry::Entity entity; entity.type = GLModel::EPrimitiveType::Triangles; @@ -1175,6 +1185,7 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl data.entities.emplace_back(entity); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + return data; } @@ -1200,8 +1211,8 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float GLModel::Geometry data; #if ENABLE_GLBEGIN_GLEND_REMOVAL data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; - data.vertices.reserve((8 * (resolution + 1) + 30) * GLModel::Geometry::vertex_stride_floats(data.format)); - data.indices.reserve(((8 * resolution + 16) * 3) * GLModel::Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(8 * (resolution + 1) + 30); + data.reserve_indices((8 * resolution + 16) * 3); #else GLModel::Geometry::Entity entity; entity.type = GLModel::EPrimitiveType::Triangles; @@ -1506,6 +1517,7 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float data.entities.emplace_back(entity); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + return data; } @@ -1526,8 +1538,8 @@ GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_w GLModel::Geometry data; #if ENABLE_GLBEGIN_GLEND_REMOVAL data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; - data.vertices.reserve(42 * GLModel::Geometry::vertex_stride_floats(data.format)); - data.indices.reserve((24 * 3) * GLModel::Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(42); + data.reserve_indices(72); #else GLModel::Geometry::Entity entity; entity.type = GLModel::EPrimitiveType::Triangles; @@ -1699,6 +1711,7 @@ GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_w data.entities.emplace_back(entity); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + return data; } @@ -1712,8 +1725,8 @@ GLModel::Geometry diamond(unsigned short resolution) GLModel::Geometry data; #if ENABLE_GLBEGIN_GLEND_REMOVAL data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; - data.vertices.reserve((resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format)); - data.indices.reserve(((2 * (resolution + 1)) * 3) * GLModel::Geometry::index_stride_bytes(data.format)); + data.reserve_vertices(resolution + 2); + data.reserve_indices((2 * (resolution + 1)) * 3); #else GLModel::Geometry::Entity entity; entity.type = GLModel::EPrimitiveType::Triangles; @@ -1724,7 +1737,7 @@ GLModel::Geometry diamond(unsigned short resolution) #if ENABLE_GLBEGIN_GLEND_REMOVAL // vertices for (unsigned short i = 0; i < resolution; ++i) { - float ii = float(i) * step; + const float ii = float(i) * step; const Vec3f p = { 0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f }; append_vertex(data, p, p.normalized()); } @@ -1782,8 +1795,77 @@ GLModel::Geometry diamond(unsigned short resolution) data.entities.emplace_back(entity); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL + return data; } +#if ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_SHOW_TOOLPATHS_COG +GLModel::Geometry smooth_sphere(unsigned short resolution, float radius) +{ + resolution = std::max(4, resolution); + resolution = std::min(256, resolution); // ensure no unsigned short overflow of indices + + const unsigned short sectorCount = /*2 **/ resolution; + const unsigned short stackCount = resolution; + + const float sectorStep = float(2.0 * M_PI / sectorCount); + const float stackStep = float(M_PI / stackCount); + + GLModel::Geometry data; + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; + data.reserve_vertices((stackCount - 1) * sectorCount + 2); + data.reserve_indices((2 * (stackCount - 1) * sectorCount) * 3); + + // vertices + for (unsigned short i = 0; i <= stackCount; ++i) { + // from pi/2 to -pi/2 + const double stackAngle = 0.5 * M_PI - stackStep * i; + const double xy = double(radius) * ::cos(stackAngle); + const double z = double(radius) * ::sin(stackAngle); + if (i == 0 || i == stackCount) { + const Vec3f v(float(xy), 0.0f, float(z)); + data.add_vertex(v, (Vec3f)v.normalized()); + } + else { + for (unsigned short j = 0; j < sectorCount; ++j) { + // from 0 to 2pi + const double sectorAngle = sectorStep * j; + const Vec3f v(float(xy * std::cos(sectorAngle)), float(xy * std::sin(sectorAngle)), float(z)); + data.add_vertex(v, (Vec3f)v.normalized()); + } + } + } + + // triangles + for (unsigned short i = 0; i < stackCount; ++i) { + // Beginning of current stack. + unsigned short k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount); + const unsigned short k1_first = k1; + // Beginning of next stack. + unsigned short k2 = (i == 0) ? 1 : (k1 + sectorCount); + const unsigned short k2_first = k2; + for (unsigned short j = 0; j < sectorCount; ++j) { + // 2 triangles per sector excluding first and last stacks + unsigned short k1_next = k1; + unsigned short k2_next = k2; + if (i != 0) { + k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1); + data.add_ushort_triangle(k1, k2, k1_next); + } + if (i + 1 != stackCount) { + k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1); + data.add_ushort_triangle(k1_next, k2, k2_next); + } + k1 = k1_next; + k2 = k2_next; + } + } + + return data; +} +#endif // ENABLE_SHOW_TOOLPATHS_COG +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index c02f5186c..70220a75c 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -80,6 +80,9 @@ namespace GUI { std::vector indices; ColorRGBA color{ ColorRGBA::BLACK() }; + void reserve_vertices(size_t vertices_count); + void reserve_indices(size_t indices_count); + void add_vertex(const Vec2f& position); void add_vertex(const Vec2f& position, const Vec2f& tex_coord); void add_vertex(const Vec3f& position); @@ -103,6 +106,8 @@ namespace GUI { unsigned int extract_uint_index(size_t id) const; unsigned short extract_ushort_index(size_t id) const; + bool is_empty() const { return vertices.empty() || indices.empty(); } + size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); } size_t indices_count() const { return indices.size() / index_stride_bytes(format); } @@ -256,6 +261,14 @@ namespace GUI { // the diamond is contained into a box with size [1, 1, 1] GLModel::Geometry diamond(unsigned short resolution); +#if ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_SHOW_TOOLPATHS_COG + // create a sphere with the given resolution and smooth normals + // the origin of the sphere is in its center + GLModel::Geometry smooth_sphere(unsigned short resolution, float radius); +#endif // ENABLE_SHOW_TOOLPATHS_COG +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index 5331d517d..515da6de3 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -126,8 +126,8 @@ namespace GUI { GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(4 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(4); // vertices init_data.add_vertex(Vec2f(left, bottom)); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index ae71e90af..33ac9b6bc 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -41,6 +41,10 @@ std::pair GLShadersManager::init() // used to render 3D scene background valid &= append_shader("background", { "background.vs", "background.fs" }); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_SHOW_TOOLPATHS_COG + // used to render toolpaths center of gravity + valid &= append_shader("toolpaths_cog", { "toolpaths_cog.vs", "toolpaths_cog.fs" }); +#endif // ENABLE_SHOW_TOOLPATHS_COG // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); // used to render printbed diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 3b99397ad..340bb78c3 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -342,8 +342,8 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, #if ENABLE_GLBEGIN_GLEND_REMOVAL GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices init_data.add_vertex(Vec2f(left, bottom), Vec2f(uvs.left_bottom.u, uvs.left_bottom.v)); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a33742d14..b55ba0d75 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -871,8 +871,8 @@ void GUI_App::init_app_config() { // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. // SetAppName(SLIC3R_APP_KEY); -// SetAppName(SLIC3R_APP_KEY "-alpha"); - SetAppName(SLIC3R_APP_KEY "-beta"); + SetAppName(SLIC3R_APP_KEY "-alpha"); +// SetAppName(SLIC3R_APP_KEY "-beta"); // SetAppDisplayName(SLIC3R_APP_NAME); // Set the Slic3r data directory at the Slic3r XS module. diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index d9c32e829..97f8edde3 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -126,6 +126,9 @@ public: ColorChanges, PausePrints, CustomGCodes, +#if ENABLE_SHOW_TOOLPATHS_COG + CenterOfGravity, +#endif // ENABLE_SHOW_TOOLPATHS_COG Shells, ToolMarker, #if !ENABLE_PREVIEW_LAYOUT diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index ab29e9026..ff5d89f5e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -115,8 +115,8 @@ void GLGizmoCut::on_render() GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices init_data.add_vertex(Vec3f(min_x, min_y, plane_center.z())); @@ -160,8 +160,8 @@ void GLGizmoCut::on_render() GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.color = ColorRGBA::YELLOW(); - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices init_data.add_vertex((Vec3f)plane_center.cast()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index fd32c68fc..0956a9047 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -1,6 +1,9 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoFlatten.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL +#include "slic3r/GUI/GUI_App.hpp" +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "libslic3r/Geometry/ConvexHull.hpp" @@ -63,6 +66,14 @@ void GLGizmoFlatten::on_render() { const Selection& selection = m_parent.get_selection(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + shader->start_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -76,21 +87,38 @@ void GLGizmoFlatten::on_render() if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + m_planes[i].vbo.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR); + m_planes[i].vbo.render(); +#else glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data())); if (m_planes[i].vbo.has_VBOs()) m_planes[i].vbo.render(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } glsafe(::glPopMatrix()); } glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glDisable(GL_BLEND)); + +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + shader->stop_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } void GLGizmoFlatten::on_render_for_picking() { const Selection& selection = m_parent.get_selection(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + shader->start_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_BLEND)); @@ -102,13 +130,21 @@ void GLGizmoFlatten::on_render_for_picking() if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + m_planes[i].vbo.set_color(picking_color_component(i)); +#else glsafe(::glColor4fv(picking_color_component(i).data())); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); } glsafe(::glEnable(GL_CULL_FACE)); + +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + shader->stop_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) @@ -324,12 +360,29 @@ void GLGizmoFlatten::update_planes() // And finally create respective VBOs. The polygon is convex with // the vertices in order, so triangulation is trivial. for (auto& plane : m_planes) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLModel::Geometry init_data; + const GLModel::Geometry::EIndexType index_type = (plane.vertices.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; + init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3, index_type }; + init_data.reserve_vertices(plane.vertices.size()); + init_data.reserve_indices(plane.vertices.size()); + // vertices + indices + for (size_t i = 0; i < plane.vertices.size(); ++i) { + init_data.add_vertex((Vec3f)plane.vertices[i].cast(), (Vec3f)plane.normal.cast()); + if (index_type == GLModel::Geometry::EIndexType::USHORT) + init_data.add_ushort_index((unsigned short)i); + else + init_data.add_uint_index((unsigned int)i); + } + plane.vbo.init_from(std::move(init_data)); +#else plane.vbo.reserve(plane.vertices.size()); for (const auto& vert : plane.vertices) plane.vbo.push_geometry(vert, plane.normal); for (size_t i=1; i vertices; // should be in fact local in update_planes() +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLModel vbo; +#else GLIndexedVertexArray vbo; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL Vec3d normal; float area; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 4c204d0d4..dd9cf0de2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -589,6 +589,9 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) m_gizmo_scene.render(color_idx); } +#if ENABLE_GLBEGIN_GLEND_REMOVAL + render_paint_contour(); +#else if (m_paint_contour.has_VBO()) { ScopeGuard guard_mm_gouraud([shader]() { shader->start_using(); }); shader->stop_using(); @@ -602,6 +605,7 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) contour_shader->stop_using(); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_update_render_data = false; } @@ -636,6 +640,9 @@ void TriangleSelectorMmGui::update_render_data() m_gizmo_scene.finalize_triangle_indices(); +#if ENABLE_GLBEGIN_GLEND_REMOVAL + update_paint_contour(); +#else m_paint_contour.release_geometry(); std::vector contour_edges = this->get_seed_fill_contour(); m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); @@ -654,6 +661,7 @@ void TriangleSelectorMmGui::update_render_data() m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); m_paint_contour.finalize_geometry(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index fbbcb3256..ff921ea7c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -117,8 +117,8 @@ void GLGizmoMove3D::on_render() GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.color = AXES_COLOR[id]; - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices init_data.add_vertex((Vec3f)center.cast()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 4c76767bd..0fc57c909 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -18,7 +18,11 @@ namespace Slic3r::GUI { - std::shared_ptr GLGizmoPainterBase::s_sphere = nullptr; +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL +std::shared_ptr GLGizmoPainterBase::s_sphere = nullptr; +#else +std::shared_ptr GLGizmoPainterBase::s_sphere = nullptr; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -27,8 +31,13 @@ GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& ic GLGizmoPainterBase::~GLGizmoPainterBase() { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + if (s_sphere != nullptr) + s_sphere.reset(); +#else if (s_sphere != nullptr && s_sphere->has_VBOs()) s_sphere->release_geometry(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection) @@ -185,8 +194,8 @@ void GLGizmoPainterBase::render_cursor_circle() static const float StepSize = 2.0f * float(PI) / float(StepsCount); init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; - init_data.vertices.reserve(StepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(StepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(StepsCount); + init_data.reserve_indices(StepsCount); // vertices + indices for (unsigned short i = 0; i < StepsCount; ++i) { @@ -220,18 +229,27 @@ void GLGizmoPainterBase::render_cursor_circle() void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const { if (s_sphere == nullptr) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + s_sphere = std::make_shared(); + s_sphere->init_from(its_make_sphere(1.0, double(PI) / 12.0)); +#else s_sphere = std::make_shared(); s_sphere->load_its_flat_shading(its_make_sphere(1.0, double(PI) / 12.0)); s_sphere->finalize_geometry(true); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse(); const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed(); glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(trafo.data())); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glTranslatef(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2))); + glsafe(::glTranslatef(m_rr.hit.x(), m_rr.hit.y(), m_rr.hit.z())); glsafe(::glMultMatrixd(complete_scaling_matrix_inverse.data())); glsafe(::glScaled(m_cursor_radius, m_cursor_radius, m_cursor_radius)); @@ -243,11 +261,22 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const render_color = this->get_cursor_sphere_left_button_color(); else if (m_button_down == Button::Right) render_color = this->get_cursor_sphere_right_button_color(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + shader->start_using(); + + assert(s_sphere != nullptr); + s_sphere->set_color(render_color); +#else glsafe(::glColor4fv(render_color.data())); assert(s_sphere != nullptr); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL s_sphere->render(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + shader->stop_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + if (is_left_handed) glFrontFace(GL_CCW); @@ -763,13 +792,28 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) shader->set_uniform("offset_depth_buffer", true); for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), std::make_pair(&m_iva_blockers, blockers_color)}) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + iva.first->set_color(iva.second); + iva.first->render(); +#else if (iva.first->has_VBOs()) { shader->set_uniform("uniform_color", iva.second); iva.first->render(); } +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } - for (auto &iva : m_iva_seed_fills) +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + for (auto& iva : m_iva_seed_fills) { + size_t color_idx = &iva - &m_iva_seed_fills.front(); + const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : + color_idx == 2 ? blockers_color : + GLVolume::NEUTRAL_COLOR); + iva.set_color(color); + iva.render(); + } +#else + for (auto& iva : m_iva_seed_fills) if (iva.has_VBOs()) { size_t color_idx = &iva - &m_iva_seed_fills.front(); const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : @@ -778,7 +822,11 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) shader->set_uniform("uniform_color", color); iva.render(); } +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL +#if ENABLE_GLBEGIN_GLEND_REMOVAL + render_paint_contour(); +#else if (m_paint_contour.has_VBO()) { ScopeGuard guard_gouraud([shader]() { shader->start_using(); }); shader->stop_using(); @@ -792,13 +840,14 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) contour_shader->stop_using(); } +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG if (imgui) render_debug(imgui); else assert(false); // If you want debug output, pass ptr to ImGuiWrapper. -#endif +#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG } void TriangleSelectorGUI::update_render_data() @@ -807,20 +856,44 @@ void TriangleSelectorGUI::update_render_data() int blc_cnt = 0; std::vector seed_fill_cnt(m_iva_seed_fills.size(), 0); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + for (auto* iva : { &m_iva_enforcers, &m_iva_blockers }) { + iva->reset(); + } + + for (auto& iva : m_iva_seed_fills) { + iva.reset(); + } + + GLModel::Geometry iva_enforcers_data; + iva_enforcers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; + GLModel::Geometry iva_blockers_data; + iva_blockers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; + std::array iva_seed_fills_data; + for (auto& data : iva_seed_fills_data) + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; +#else for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) iva->release_geometry(); for (auto &iva : m_iva_seed_fills) iva.release_geometry(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL for (const Triangle &tr : m_triangles) { if (!tr.valid() || tr.is_split() || (tr.get_state() == EnforcerBlockerType::NONE && !tr.is_selected_by_seed_fill())) continue; int tr_state = int(tr.get_state()); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLModel::Geometry &iva = tr.is_selected_by_seed_fill() ? iva_seed_fills_data[tr_state] : + tr.get_state() == EnforcerBlockerType::ENFORCER ? iva_enforcers_data : + iva_blockers_data; +#else GLIndexedVertexArray &iva = tr.is_selected_by_seed_fill() ? m_iva_seed_fills[tr_state] : tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] : tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; @@ -830,19 +903,40 @@ void TriangleSelectorGUI::update_render_data() //FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort // or the current implementation may be more cache friendly. const Vec3f n = (v1 - v0).cross(v2 - v1).normalized(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + iva.add_vertex(v0, n); + iva.add_vertex(v1, n); + iva.add_vertex(v2, n); + iva.add_uint_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2); +#else iva.push_geometry(v0, n); iva.push_geometry(v1, n); iva.push_geometry(v2, n); iva.push_triangle(cnt, cnt + 1, cnt + 2); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL cnt += 3; } +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + if (!iva_enforcers_data.is_empty()) + m_iva_enforcers.init_from(std::move(iva_enforcers_data)); + if (!iva_blockers_data.is_empty()) + m_iva_blockers.init_from(std::move(iva_blockers_data)); + for (size_t i = 0; i < m_iva_seed_fills.size(); ++i) { + if (!iva_seed_fills_data[i].is_empty()) + m_iva_seed_fills[i].init_from(std::move(iva_seed_fills_data[i])); + } +#else for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) iva->finalize_geometry(true); for (auto &iva : m_iva_seed_fills) iva.finalize_geometry(true); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL +#if ENABLE_GLBEGIN_GLEND_REMOVAL + update_paint_contour(); +#else m_paint_contour.release_geometry(); std::vector contour_edges = this->get_seed_fill_contour(); m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); @@ -861,8 +955,10 @@ void TriangleSelectorGUI::update_render_data() m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); m_paint_contour.finalize_geometry(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } +#if !ENABLE_GLBEGIN_GLEND_REMOVAL void GLPaintContour::render() const { assert(this->m_contour_VBO_id != 0); @@ -920,6 +1016,7 @@ void GLPaintContour::release_geometry() } this->clear(); } +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) @@ -956,45 +1053,111 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) INVALID }; +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + for (auto& va : m_varrays) + va.reset(); +#else for (auto& va : m_varrays) va.release_geometry(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL std::array cnts; ::glScalef(1.01f, 1.01f, 1.01f); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + std::array varrays_data; + for (auto& data : varrays_data) + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + for (int tr_id=0; tr_idadd_vertex(m_vertices[tr.verts_idxs[i]].v, Vec3f(0.0f, 0.0f, 1.0f)); + } + va->add_uint_triangle((unsigned int)*cnt, (unsigned int)*cnt + 1, (unsigned int)*cnt + 2); +#else + for (int i = 0; i < 3; ++i) va->push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]), double(m_vertices[tr.verts_idxs[i]].v[1]), double(m_vertices[tr.verts_idxs[i]].v[2]), 0., 0., 1.); va->push_triangle(*cnt, - *cnt+1, - *cnt+2); + *cnt + 1, + *cnt + 2); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL *cnt += 3; } +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + for (int i = 0; i < 3; ++i) { + if (!varrays_data[i].is_empty()) + m_varrays[i].init_from(std::move(varrays_data[i])); + } +#else + for (auto* iva : { &m_iva_enforcers, &m_iva_blockers }) + iva->finalize_geometry(true); + + for (auto& iva : m_iva_seed_fills) + iva.finalize_geometry(true); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLShaderProgram* curr_shader = wxGetApp().get_current_shader(); + if (curr_shader != nullptr) + curr_shader->stop_using(); + + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + shader->start_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + ::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); for (vtype i : {ORIGINAL, SPLIT, INVALID}) { +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLModel& va = m_varrays[i]; + switch (i) { + case ORIGINAL: va.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); break; + case SPLIT: va.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); break; + case INVALID: va.set_color({ 1.0f, 1.0f, 0.0f, 1.0f }); break; + } + va.render(); +#else GLIndexedVertexArray& va = m_varrays[i]; va.finalize_geometry(true); if (va.has_VBOs()) { @@ -1005,11 +1168,67 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) } va.render(); } +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } ::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + shader->stop_using(); + } + + if (curr_shader != nullptr) + curr_shader->start_using(); +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL } -#endif +#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG +#if ENABLE_GLBEGIN_GLEND_REMOVAL +void TriangleSelectorGUI::update_paint_contour() +{ + m_paint_contour.reset(); + GLModel::Geometry init_data; + const std::vector contour_edges = this->get_seed_fill_contour(); + const GLModel::Geometry::EIndexType index_type = (2 * contour_edges.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, index_type }; + init_data.reserve_vertices(2 * contour_edges.size()); + init_data.reserve_indices(2 * contour_edges.size()); + // vertices + indices + unsigned int vertices_count = 0; + for (const Vec2i& edge : contour_edges) { + init_data.add_vertex(m_vertices[edge(0)].v); + init_data.add_vertex(m_vertices[edge(1)].v); + vertices_count += 2; + if (index_type == GLModel::Geometry::EIndexType::USHORT) + init_data.add_ushort_line((unsigned short)vertices_count - 2, (unsigned short)vertices_count - 1); + else + init_data.add_uint_line(vertices_count - 2, vertices_count - 1); + } + + if (!init_data.is_empty()) + m_paint_contour.init_from(std::move(init_data)); +} + +void TriangleSelectorGUI::render_paint_contour() +{ + auto* curr_shader = wxGetApp().get_current_shader(); + if (curr_shader != nullptr) + curr_shader->stop_using(); + + auto* contour_shader = wxGetApp().get_shader("mm_contour"); + if (contour_shader != nullptr) { + contour_shader->start_using(); + + glsafe(::glDepthFunc(GL_LEQUAL)); + m_paint_contour.render(); + glsafe(::glDepthFunc(GL_LESS)); + + contour_shader->stop_using(); + } + + if (curr_shader != nullptr) + curr_shader->start_using(); +} +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 079f3f08e..37c7163e2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -3,7 +3,11 @@ #include "GLGizmoBase.hpp" +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL +#include "slic3r/GUI/GLModel.hpp" +#else #include "slic3r/GUI/3DScene.hpp" +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL #include "libslic3r/ObjectID.hpp" #include "libslic3r/TriangleSelector.hpp" @@ -28,6 +32,7 @@ enum class PainterGizmoType { MMU_SEGMENTATION }; +#if !ENABLE_GLBEGIN_GLEND_REMOVAL class GLPaintContour { public: @@ -63,6 +68,7 @@ public: GLuint m_contour_VBO_id{0}; GLuint m_contour_EBO_id{0}; }; +#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL class TriangleSelectorGUI : public TriangleSelector { public: @@ -75,13 +81,13 @@ public: virtual void render(ImGuiWrapper *imgui); void render() { this->render(nullptr); } - void request_update_render_data() { m_update_render_data = true; }; + void request_update_render_data() { m_update_render_data = true; } #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG void render_debug(ImGuiWrapper* imgui); bool m_show_triangles{false}; bool m_show_invalid{false}; -#endif +#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG protected: bool m_update_render_data = false; @@ -91,13 +97,29 @@ protected: private: void update_render_data(); +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + GLModel m_iva_enforcers; + GLModel m_iva_blockers; + std::array m_iva_seed_fills; +#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG + std::array m_varrays; +#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG +#else GLIndexedVertexArray m_iva_enforcers; GLIndexedVertexArray m_iva_blockers; std::array m_iva_seed_fills; std::array m_varrays; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL protected: +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLModel m_paint_contour; + + void update_paint_contour(); + void render_paint_contour(); +#else GLPaintContour m_paint_contour; +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL }; @@ -209,7 +231,11 @@ private: const Camera& camera, const std::vector& trafo_matrices) const; +#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL + static std::shared_ptr s_sphere; +#else static std::shared_ptr s_sphere; +#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL bool m_internal_stack_active = false; bool m_schedule_update = false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 9bedc86cc..362e25309 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -235,8 +235,8 @@ void GLGizmoRotate::render_circle() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(ScaleStepsCount); + init_data.reserve_indices(ScaleStepsCount); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -278,8 +278,8 @@ void GLGizmoRotate::render_scale() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2 * ScaleStepsCount); + init_data.reserve_indices(2 * ScaleStepsCount); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -337,8 +337,8 @@ void GLGizmoRotate::render_snap_radii() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2 * ScaleStepsCount); + init_data.reserve_indices(2 * ScaleStepsCount); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -388,8 +388,8 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_ GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); @@ -429,8 +429,8 @@ void GLGizmoRotate::render_angle() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve((1 + AngleResolution) * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve((1 + AngleResolution) * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(1 + AngleResolution); + init_data.reserve_indices(1 + AngleResolution); // vertices + indices for (unsigned short i = 0; i <= AngleResolution; ++i) { @@ -466,8 +466,8 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 7d0e3ec34..ce7d4705b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -403,8 +403,8 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(2); + init_data.reserve_indices(2); // vertices init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast()); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 4616eee85..e70c1111b 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -64,6 +64,9 @@ static const std::map font_icons = { {ImGui::LegendColorChanges , "legend_colorchanges" }, {ImGui::LegendPausePrints , "legend_pauseprints" }, {ImGui::LegendCustomGCodes , "legend_customgcodes" }, +#if ENABLE_SHOW_TOOLPATHS_COG + {ImGui::LegendCOG , "legend_cog" }, +#endif // ENABLE_SHOW_TOOLPATHS_COG {ImGui::LegendShells , "legend_shells" }, {ImGui::LegendToolMarker , "legend_toolmarker" }, #endif // ENABLE_LEGEND_TOOLBAR_ICONS diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c680f6e09..89fd43acb 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1261,10 +1261,10 @@ void Selection::render(float scale_factor) return; m_scale_factor = scale_factor; + // render cumulative bounding box of selected volumes #if ENABLE_GLBEGIN_GLEND_REMOVAL render_bounding_box(get_bounding_box(), ColorRGB::WHITE()); #else - // render cumulative bounding box of selected volumes render_selected_volumes(); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL render_synchronized_volumes(); @@ -1276,6 +1276,14 @@ void Selection::render_center(bool gizmo_is_dragging) if (!m_valid || is_empty()) return; +#if ENABLE_GLBEGIN_GLEND_REMOVAL + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + shader->start_using(); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + const Vec3d center = gizmo_is_dragging ? m_cache.dragging_center : get_bounding_box().center(); glsafe(::glDisable(GL_DEPTH_TEST)); @@ -1284,19 +1292,17 @@ void Selection::render_center(bool gizmo_is_dragging) glsafe(::glTranslated(center.x(), center.y(), center.z())); #if ENABLE_GLBEGIN_GLEND_REMOVAL - GLShaderProgram* shader = wxGetApp().get_shader("flat"); - if (shader == nullptr) - return; - - shader->start_using(); -#endif // ENABLE_GLBEGIN_GLEND_REMOVAL + m_vbo_sphere.set_color(ColorRGBA::WHITE()); +#else m_vbo_sphere.set_color(-1, ColorRGBA::WHITE()); +#endif // ENABLE_GLBEGIN_GLEND_REMOVAL m_vbo_sphere.render(); + + glsafe(::glPopMatrix()); + #if ENABLE_GLBEGIN_GLEND_REMOVAL shader->stop_using(); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL - - glsafe(::glPopMatrix()); } #endif // ENABLE_RENDER_SELECTION_CENTER @@ -1894,8 +1900,8 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(48 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(48 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(48); + init_data.reserve_indices(48); // vertices init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z())); @@ -2203,8 +2209,8 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices init_data.add_vertex(Vec3f(p1.x(), p1.y(), z1)); @@ -2225,8 +2231,8 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format)); - init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format)); + init_data.reserve_vertices(4); + init_data.reserve_indices(6); // vertices init_data.add_vertex(Vec3f(p1.x(), p1.y(), z2)); diff --git a/version.inc b/version.inc index b976d7d67..93b376323 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.4.1-beta1") +set(SLIC3R_VERSION "2.5.0-alpha0") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") -set(SLIC3R_RC_VERSION "2,4,1,0") -set(SLIC3R_RC_VERSION_DOTS "2.4.1.0") +set(SLIC3R_RC_VERSION "2,5,0,0") +set(SLIC3R_RC_VERSION_DOTS "2.5.0.0") diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index cfadaf878..06fc98322 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -210,15 +210,24 @@ else () endif () set(PERL_ENV_VARS "") -if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) +if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_CROSSCOMPILING AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) if (SLIC3R_ASAN OR SLIC3R_UBSAN) set(PERL_ENV_VARS env) endif () if (SLIC3R_ASAN) # Find the location of libasan.so for passing it into LD_PRELOAD. It works with GCC and Clang on Linux. - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libasan.so OUTPUT_VARIABLE LIBASAN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PERL_ENV_VARS ${PERL_ENV_VARS} "LD_PRELOAD=${LIBASAN_PATH}") + # On Centos 7 calling "gcc -print-file-name=libasan.so" returns path to "ld script" instead of path to shared library. + set(_asan_compiled_bin ${CMAKE_CURRENT_BINARY_DIR}/detect_libasan) + set(_asan_source_file ${_asan_compiled_bin}.c) + # Compile and link simple C application with enabled address sanitizer. + file(WRITE ${_asan_source_file} "int main(){}") + include(GetPrerequisites) + execute_process(COMMAND ${CMAKE_C_COMPILER} ${_asan_source_file} -fsanitize=address -lasan -o ${_asan_compiled_bin}) + # Extract from the compiled application absolute path of libasan. + get_prerequisites(${_asan_compiled_bin} _asan_shared_libraries_list 0 0 "" "") + list(FILTER _asan_shared_libraries_list INCLUDE REGEX libasan) + set(PERL_ENV_VARS ${PERL_ENV_VARS} "LD_PRELOAD=${_asan_shared_libraries_list}") # Suppressed memory leak reports that come from Perl. set(PERL_LEAK_SUPPRESSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/leak_suppression.txt)