diff --git a/resources/shaders/110/flat_instance.vs b/resources/shaders/110/flat_instance.vs new file mode 100644 index 000000000..e0662e99b --- /dev/null +++ b/resources/shaders/110/flat_instance.vs @@ -0,0 +1,12 @@ +#version 110 + +uniform mat4 view_matrix; +uniform mat4 projection_matrix; + +attribute vec3 v_position; +attribute vec2 v_undefine; +attribute mat4 instanceMatrix; +void main() +{ + gl_Position = projection_matrix * view_matrix * instanceMatrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/flat.fs b/resources/shaders/flat.fs deleted file mode 100644 index ab656998d..000000000 --- a/resources/shaders/flat.fs +++ /dev/null @@ -1,8 +0,0 @@ -#version 110 - -uniform vec4 uniform_color; - -void main() -{ - gl_FragColor = uniform_color; -} diff --git a/resources/shaders/flat.vs b/resources/shaders/flat.vs deleted file mode 100644 index d9063f0c7..000000000 --- a/resources/shaders/flat.vs +++ /dev/null @@ -1,11 +0,0 @@ -#version 110 - -uniform mat4 view_model_matrix; -uniform mat4 projection_matrix; - -attribute vec3 v_position; - -void main() -{ - gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); -} diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 41664964a..e6324e0fe 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -2234,7 +2234,7 @@ std::map> PresetCollection::get_filamen } //BBS: add project embedded preset logic -void PresetCollection::save_current_preset(const std::string &new_name, bool detach, bool save_to_project, Preset* _curr_preset) +void PresetCollection::save_current_preset(const std::string &new_name, bool detach, bool save_to_project, Preset *_curr_preset, std::map *extra_map) { Preset curr_preset = _curr_preset ? *_curr_preset : m_edited_preset; //BBS: add lock logic for sync preset in background @@ -2273,8 +2273,12 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det preset.config.option("print_settings_id", true)->value = new_name; else if (m_type == Preset::TYPE_FILAMENT) preset.config.option("filament_settings_id", true)->values[0] = new_name; - else if (m_type == Preset::TYPE_PRINTER) + else if (m_type == Preset::TYPE_PRINTER) { preset.config.option("printer_settings_id", true)->value = new_name; + for (auto iter : *extra_map) { + preset.config.option(iter.first, true)->value = iter.second; + } + } final_inherits = preset.inherits(); unlock(); // TODO: apply change from custom root to devided presets. @@ -2318,8 +2322,12 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det preset.config.option("print_settings_id", true)->value = new_name; else if (m_type == Preset::TYPE_FILAMENT) preset.config.option("filament_settings_id", true)->values[0] = new_name; - else if (m_type == Preset::TYPE_PRINTER) + else if (m_type == Preset::TYPE_PRINTER) { preset.config.option("printer_settings_id", true)->value = new_name; + for (auto iter : *extra_map) { + preset.config.option(iter.first, true)->value = iter.second; + } + } //BBS: add lock logic for sync preset in background final_inherits = inherits; unlock(); diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 920b887b8..44ad8f2e5 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -506,7 +506,7 @@ public: // a new preset is stored into the list of presets. // All presets are marked as not modified and the new preset is activated. //BBS: add project embedded preset logic - void save_current_preset(const std::string &new_name, bool detach = false, bool save_to_project = false, Preset* _curr_preset = nullptr); + void save_current_preset(const std::string &new_name, bool detach = false, bool save_to_project = false, Preset *_curr_preset = nullptr, std::map* extra_map =nullptr); // Delete the current preset, activate the first visible preset. // returns true if the preset was deleted successfully. diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 1c0574ead..d77ab7ef8 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -897,6 +897,130 @@ void GLModel::render_geometry(int i,const std::pair &range) glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } +void GLModel::create_or_update_mats_vbo(unsigned int &vbo, const std::vector &mats) +{ // first bind + if (vbo>0) { + glsafe(::glDeleteBuffers(1, &vbo)); + } + std::vector out_mats; + out_mats.reserve(mats.size()); + for (size_t i = 0; i < mats.size(); i++) { + out_mats.emplace_back(mats[i].get_matrix().matrix().cast()); + } + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + auto one_mat_all_size = sizeof(float) * 16; + glBufferData(GL_ARRAY_BUFFER, mats.size() * one_mat_all_size, out_mats.data(), GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void GLModel::bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, int location) +{ + auto one_mat_all_size = sizeof(float) * 16; + auto one_mat_col_size = sizeof(float) * 4; + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instance_mats_vbo)); + for (unsigned int i = 0; i < instances_count; i++) { // set attribute pointers for matrix (4 times vec4) + glEnableVertexAttribArray(location); + glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) 0); + glEnableVertexAttribArray(location + 1); + glVertexAttribPointer(location + 1, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (one_mat_col_size)); + glEnableVertexAttribArray(location + 2); + glVertexAttribPointer(location + 2, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (2 * one_mat_col_size)); + glEnableVertexAttribArray(location + 3); + glVertexAttribPointer(location + 3, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (3 * one_mat_col_size)); + // Update the matrix every time after an object is drawn//useful + glVertexAttribDivisor(location, 1); + glVertexAttribDivisor(location + 1, 1); + glVertexAttribDivisor(location + 2, 1); + glVertexAttribDivisor(location + 3, 1); + } +} + +void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count) +{ + render_geometry_instance(instance_mats_vbo, instances_count,std::make_pair(0, indices_count())); +} + +void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count, const std::pair &range) +{ + if (m_render_data.size() != 1) { return; } + GLShaderProgram *shader = wxGetApp().get_current_shader(); + if (shader == nullptr) return; + + auto &render_data = m_render_data[0]; + // sends data to gpu if not done yet + if (render_data.vbo_id == 0 || render_data.ibo_id == 0) { + if (render_data.geometry.vertices_count() > 0 && render_data.geometry.indices_count() > 0 && !send_to_gpu(render_data.geometry)) + return; + } + if (instance_mats_vbo == 0) { + return; + } + const Geometry &data = render_data.geometry; + + const GLenum mode = get_primitive_mode(data.format); + const GLenum index_type = get_index_type(data); + + const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); + const bool position = Geometry::has_position(data.format); + const bool normal = Geometry::has_normal(data.format); + const bool tex_coord = Geometry::has_tex_coord(data.format); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, render_data.vbo_id)); + + int position_id = -1; + int normal_id = -1; + int tex_coord_id = -1; + int instace_mats_id = -1; + if (position) { + position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, + (const void *) Geometry::position_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + } + if (normal) { + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, + (const void *) Geometry::normal_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(normal_id)); + } + } + if (tex_coord) { + tex_coord_id = shader->get_attrib_location("v_tex_coord"); + if (tex_coord_id != -1) { + glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, + (const void *) Geometry::tex_coord_offset_bytes(data.format))); + glsafe(::glEnableVertexAttribArray(tex_coord_id)); + } + } + //glBindAttribLocation(shader->get_id(), 2, "instanceMatrix"); + //glBindAttribLocation(2, "instanceMatrix"); + //shader->bind(shaderProgram, 0, 'position'); + instace_mats_id = shader->get_attrib_location("instanceMatrix"); + if (instace_mats_id != -1) { + bind_mats_vbo(instance_mats_vbo, instances_count, instace_mats_id); + } + else { + return; + } + auto res = shader->set_uniform("uniform_color", render_data.color); + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, render_data.ibo_id)); + glsafe(::glDrawElementsInstanced(mode, range.second - range.first, index_type, (const void *) (range.first * Geometry::index_stride_bytes(data)), instances_count)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (instace_mats_id != -1) glsafe(::glDisableVertexAttribArray(instace_mats_id)); + if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id)); + if (normal_id != -1) glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) glsafe(::glDisableVertexAttribArray(position_id)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); +} + void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const { if (instances_vbo == 0) @@ -974,7 +1098,59 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -bool GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) const +bool GLModel::send_to_gpu(Geometry &geometry) +{ + if (m_render_data.size() != 1) { return false; } + auto& render_data = m_render_data[0]; + if (render_data.vbo_id > 0 || render_data.ibo_id > 0) { + assert(false); + return false; + } + + Geometry &data = render_data.geometry; + if (data.vertices.empty() || data.indices.empty()) { + assert(false); + return false; + } + + // vertices + glsafe(::glGenBuffers(1, &render_data.vbo_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, render_data.vbo_id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, data.vertices_size_bytes(), data.vertices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + render_data.vertices_count = vertices_count(); + data.vertices = std::vector(); + + // indices + glsafe(::glGenBuffers(1, &render_data.ibo_id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, render_data.ibo_id)); + const size_t indices_count = data.indices.size(); + if (render_data.vertices_count <= 256) { + // convert indices to unsigned char to save gpu memory + std::vector reduced_indices(indices_count); + for (size_t i = 0; i < indices_count; ++i) { reduced_indices[i] = (unsigned char) data.indices[i]; } + data.index_type = Geometry::EIndexType::UBYTE; + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_count * sizeof(unsigned char), reduced_indices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } else if (render_data.vertices_count <= 65536) { + // convert indices to unsigned short to save gpu memory + std::vector reduced_indices(indices_count); + for (size_t i = 0; i < data.indices.size(); ++i) { reduced_indices[i] = (unsigned short) data.indices[i]; } + data.index_type = Geometry::EIndexType::USHORT; + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_count * sizeof(unsigned short), reduced_indices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } else { + data.index_type = Geometry::EIndexType::UINT; + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } + render_data.indices_count = indices_count; + data.indices = std::vector(); + + return true; +} + +bool GLModel::send_to_gpu(RenderData &data, const std::vector &vertices, const std::vector &indices) const { if (data.vbo_id > 0 || data.ibo_id > 0) { assert(false); diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index ec375877f..ec6456dd7 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -4,6 +4,7 @@ #include "libslic3r/Point.hpp" #include "libslic3r/Color.hpp" #include "libslic3r/BoundingBox.hpp" +#include "libslic3r/Geometry.hpp" #include #include @@ -194,6 +195,10 @@ namespace GUI { void render() const; void render_geometry(); void render_geometry(int i,const std::pair &range); + static void create_or_update_mats_vbo(unsigned int &vbo, const std::vector &mats); + void bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, int location); + void render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count); + void render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count, const std::pair &range); void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; bool is_initialized() const { return !m_render_data.empty(); } @@ -202,6 +207,7 @@ namespace GUI { const std::string& get_filename() const { return m_filename; } private: + bool send_to_gpu(Geometry& geometry); bool send_to_gpu(RenderData &data, const std::vector &vertices, const std::vector &indices) const; }; diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index 9c1e93652..083e91934 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -59,7 +59,7 @@ bool GLShaderProgram::init_from_files(const std::string& name, const ShaderFilen // Create a block of C "defines" from list of symbols. std::string defines_program; for (std::string_view def : defines) - // Our shaders are stored with "\r\n", thus replicate the same here for consistency. Likely "\n" would suffice, + // Our shaders are stored with "\r\n", thus replicate the same here for consistency. Likely "\n" would suffice, // but we don't know all the OpenGL shader compilers around. defines_program += format("#define %s\r\n", def); @@ -69,7 +69,7 @@ bool GLShaderProgram::init_from_files(const std::string& name, const ShaderFilen } bool valid = !sources[static_cast(EShaderType::Vertex)].empty() && !sources[static_cast(EShaderType::Fragment)].empty() && sources[static_cast(EShaderType::Compute)].empty(); - valid |= !sources[static_cast(EShaderType::Compute)].empty() && sources[static_cast(EShaderType::Vertex)].empty() && sources[static_cast(EShaderType::Fragment)].empty() && + valid |= !sources[static_cast(EShaderType::Compute)].empty() && sources[static_cast(EShaderType::Vertex)].empty() && sources[static_cast(EShaderType::Fragment)].empty() && sources[static_cast(EShaderType::Geometry)].empty() && sources[static_cast(EShaderType::TessEvaluation)].empty() && sources[static_cast(EShaderType::TessControl)].empty(); return valid ? init_from_texts(name, sources) : false; @@ -102,7 +102,7 @@ bool GLShaderProgram::init_from_texts(const std::string& name, const ShaderSourc case EShaderType::Compute: { id = ::glCreateShader(GL_COMPUTE_SHADER); glcheck(); break; } default: { break; } } - + return (id == 0) ? std::make_pair(false, GLuint(0)) : std::make_pair(true, id); }; @@ -141,7 +141,7 @@ bool GLShaderProgram::init_from_texts(const std::string& name, const ShaderSourc GLint params; glsafe(::glGetShaderiv(id, GL_COMPILE_STATUS, ¶ms)); if (params == GL_FALSE) { - // Compilation failed. + // Compilation failed. glsafe(::glGetShaderiv(id, GL_INFO_LOG_LENGTH, ¶ms)); std::vector msg(params); glsafe(::glGetShaderInfoLog(id, params, ¶ms, msg.data())); @@ -168,12 +168,15 @@ bool GLShaderProgram::init_from_texts(const std::string& name, const ShaderSourc if (shader_ids[i] > 0) glsafe(::glAttachShader(m_id, shader_ids[i])); } + if (boost::ends_with(name,"_instance")) { + glBindAttribLocation(m_id, 3, "instanceMatrix"); + } glsafe(::glLinkProgram(m_id)); GLint params; glsafe(::glGetProgramiv(m_id, GL_LINK_STATUS, ¶ms)); if (params == GL_FALSE) { - // Linking failed. + // Linking failed. glsafe(::glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, ¶ms)); std::vector msg(params); glsafe(::glGetProgramInfoLog(m_id, params, ¶ms, msg.data())); @@ -364,13 +367,13 @@ int GLShaderProgram::get_attrib_location(const char* name) const // Shader program not loaded. This should not happen. return -1; - auto it = std::find_if(m_attrib_location_cache.begin(), m_attrib_location_cache.end(), [name](const auto& p) { return p.first == name; }); - if (it != m_attrib_location_cache.end()) - // Attrib ID cached. - return it->second; + //auto it = std::find_if(m_attrib_location_cache.begin(), m_attrib_location_cache.end(), [name](const auto& p) { return p.first == name; }); + //if (it != m_attrib_location_cache.end()) + // // Attrib ID cached. + // return it->second; int id = ::glGetAttribLocation(m_id, name); - const_cast(this)->m_attrib_location_cache.push_back({ name, id }); + //const_cast(this)->m_attrib_location_cache.push_back({ name, id }); return id; } diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index ddf081f24..9b2c59288 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -39,7 +39,8 @@ std::pair GLShadersManager::init() valid &= append_shader("thumbnail", { "thumbnail.vs", "thumbnail.fs" }); // used to render first layer for calibration valid &= append_shader("cali", { "cali.vs", "cali.fs"}); - valid &= append_shader("flat", {"flat.vs", "flat.fs"}); + valid &= append_shader("flat", {"110/flat.vs", "110/flat.fs"}); + valid &= append_shader("flat_instance", {"110/flat_instance.vs", "110/flat.fs"}); // used to render printbed valid &= append_shader("printbed", {"110/printbed.vs", "110/printbed.fs"}); // used to render options in gcode preview diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 1398071bd..2a6ff4511 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -346,66 +346,6 @@ void PartPlate::calc_bounding_boxes() const { } } -void PartPlate::calc_triangles(const ExPolygon& poly) -{ - auto triangles =triangulate_expolygon_2f(poly, NORMALS_UP); - m_triangles.reset(); - if (!m_triangles.init_model_from_poly(triangles, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; -} - -void PartPlate::calc_exclude_triangles(const ExPolygon& poly) { - if (poly.empty()) { return; } - auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); - m_exclude_triangles.reset(); - if (!m_exclude_triangles.init_model_from_poly(triangles, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; -} - -void PartPlate::calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox) { - Polylines axes_lines, axes_lines_bolder; - int count = 0; - for (coord_t x = pp_bbox.min(0); x <= pp_bbox.max(0); x += scale_(10.0)) { - Polyline line; - line.append(Point(x, pp_bbox.min(1))); - line.append(Point(x, pp_bbox.max(1))); - - if ( (count % 5) == 0 ) - axes_lines_bolder.push_back(line); - else - axes_lines.push_back(line); - count ++; - } - count = 0; - for (coord_t y = pp_bbox.min(1); y <= pp_bbox.max(1); y += scale_(10.0)) { - Polyline line; - line.append(Point(pp_bbox.min(0), y)); - line.append(Point(pp_bbox.max(0), y)); - axes_lines.push_back(line); - - if ( (count % 5) == 0 ) - axes_lines_bolder.push_back(line); - else - axes_lines.push_back(line); - count ++; - } - - // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped - Lines gridlines = to_lines(intersection_pl(axes_lines, offset(poly, (float)SCALED_EPSILON))); - Lines gridlines_bolder = to_lines(intersection_pl(axes_lines_bolder, offset(poly, (float)SCALED_EPSILON))); - - // append bed contours - Lines contour_lines = to_lines(poly); - std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines)); - - m_gridlines.reset(); - if (!m_gridlines.init_model_from_lines(gridlines, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; - m_gridlines_bolder.reset(); - if (!m_gridlines_bolder.init_model_from_lines(gridlines_bolder, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; -} - void PartPlate::calc_height_limit() { Lines3 bottom_h_lines, top_lines, top_h_lines, common_lines; int shape_count = m_shape.size(); @@ -448,37 +388,11 @@ void PartPlate::calc_height_limit() { BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create height limit top lines\n"; } -void PartPlate::calc_vertex_for_number(int index, bool one_number, GLModel &gl_model) -{ - ExPolygon poly; -#if 0 //in the up area - Vec2d& p = m_shape[2]; - float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2; - - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP) - PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y)}); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y) }); -#else //in the bottom - Vec2d& p = m_shape[1]; - float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2; - - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y) }); -#endif - auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); - gl_model.reset(); - if (!gl_model.init_model_from_poly(triangles, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; -} - void PartPlate::calc_vertex_for_plate_name(GLTexture &texture, GLModel &gl_model) { if (texture.get_width() > 0 && texture.get_height()) { wxCoord w, h; - auto bed_ext = get_extents(m_shape); + auto bed_ext = get_extents(m_partplate_list->m_shape); auto factor = bed_ext.size()(1) / 200.0; ExPolygon poly; float offset_x = 1; @@ -494,13 +408,12 @@ void PartPlate::calc_vertex_for_plate_name(GLTexture &texture, GLModel &gl_model gl_model.reset(); if (!gl_model.init_model_from_poly(triangles, GROUND_Z)) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; - } } void PartPlate::calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, GLModel &gl_model) { - auto bed_ext = get_extents(m_shape); + auto bed_ext = get_extents(m_partplate_list->m_shape); auto factor = bed_ext.size()(1) / 200.0; wxCoord w, h; h = int(factor * 16); @@ -533,26 +446,10 @@ void PartPlate::calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int ind BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; } -void PartPlate::calc_vertex_for_icons(int index, GLModel &gl_model) -{ - ExPolygon poly; - Vec2d& p = m_shape[2]; - - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP)}); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP) }); - - auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); - gl_model.reset(); - if (!gl_model.init_model_from_poly(triangles, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; -} - void PartPlate::calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer) { ExPolygon poly; - Vec2d& p = m_shape[2]; + Vec2d & p = m_partplate_list->m_shape[2]; poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP) }); poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP) }); @@ -564,27 +461,21 @@ void PartPlate::calc_vertex_for_icons_background(int icon_count, GeometryBuffer BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; } -void PartPlate::render_background(bool force_default_color) { - //return directly for current plate - if (m_selected && !force_default_color) return; - - // draw background - glsafe(::glDepthMask(GL_FALSE)); - ColorRGBA color; - if (!force_default_color) { - if (m_selected) { - color = PartPlate::SELECT_COLOR; - } - else { - color = m_partplate_list->m_is_dark ? PartPlate::UNSELECT_DARK_COLOR : PartPlate::UNSELECT_COLOR; - } - } - else { - color = PartPlate::DEFAULT_COLOR; - } - m_triangles.set_color(color); - m_triangles.render_geometry(); - glsafe(::glDepthMask(GL_TRUE)); +bool PartPlate::calc_bed_3d_boundingbox(BoundingBoxf3 &box_in_plate_origin) { + if (m_partplate_list && m_partplate_list->m_bed3d && !m_partplate_list->m_bed3d->get_model_filename().empty()) { + auto cur_bed = m_partplate_list->m_bed3d; + auto cur_box = cur_bed->get_cur_bed_model_box(); + if (cur_box.size().x() > 1.0f) { + Vec3d min_ = cur_box.min - m_origin; + Vec3d max_ = cur_box.max - m_origin; + cur_box.reset(); + cur_box.merge(min_); + cur_box.merge(max_); + box_in_plate_origin = cur_box; + return true; + } + } + return false; } void PartPlate::render_logo_texture(GLTexture &logo_texture, GLModel &logo_buffer, bool bottom) @@ -657,13 +548,11 @@ void PartPlate::render_logo(bool bottom, bool render_cali) // canvas.request_extra_frame(); } - - if (m_partplate_list && m_partplate_list->m_bed3d && !m_partplate_list->m_bed3d->get_model_filename().empty()) { - auto cur_bed = m_partplate_list->m_bed3d; - auto cur_box = cur_bed->get_cur_bed_model_box(); - if ((m_cur_bed_boundingbox.center() - cur_box.center()).norm() > 1.0f) { - set_logo_box_by_bed(cur_box); - } + BoundingBoxf3 box_in_plate_origin; + if (calc_bed_3d_boundingbox(box_in_plate_origin)) { + if ((m_cur_bed_boundingbox.center() - box_in_plate_origin.center()).norm() > 1.0f) { + set_logo_box_by_bed(box_in_plate_origin); + } } if (m_logo_triangles.is_initialized()) { render_logo_texture(m_partplate_list->m_logo_texture, m_logo_triangles, bottom); @@ -692,7 +581,7 @@ void PartPlate::render_logo(bool bottom, bool render_cali) ) { if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) { part.offset = Vec2d(m_origin.x(), m_origin.y()); - part.update_buffer(); + //part.update_buffer(); } render_logo_texture(*(part.texture), *(part.buffer), @@ -708,7 +597,7 @@ void PartPlate::render_logo(bool bottom, bool render_cali) if (part.buffer && part.buffer->is_initialized()) { if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) { part.offset = Vec2d(m_origin.x(), m_origin.y()); - part.update_buffer(); + //part.update_buffer(); } render_logo_texture(*(part.texture), *(part.buffer), @@ -719,43 +608,6 @@ void PartPlate::render_logo(bool bottom, bool render_cali) } } -void PartPlate::render_exclude_area(bool force_default_color) -{ - if (force_default_color || !m_exclude_triangles.is_initialized()) // for thumbnail case - return; - - ColorRGBA select_color{0.765f, 0.7686f, 0.7686f, 1.0f}; - ColorRGBA unselect_color{0.9f, 0.9f, 0.9f, 1.0f}; - //std::array default_color{ 0.9f, 0.9f, 0.9f, 1.0f }; - - // draw exclude area - glsafe(::glDepthMask(GL_FALSE)); - m_exclude_triangles.set_color(m_selected ? select_color : unselect_color); - m_exclude_triangles.render_geometry(); - glsafe(::glDepthMask(GL_TRUE)); -} - -void PartPlate::render_grid(bool bottom) { - //glsafe(::glEnable(GL_MULTISAMPLE)); - // draw grid - glsafe(::glLineWidth(1.0f * m_scale_factor)); - ColorRGBA color; - if (bottom) - color = LINE_BOTTOM_COLOR; - else { - if (m_selected) - color = m_partplate_list->m_is_dark ? LINE_TOP_SEL_DARK_COLOR : LINE_TOP_SEL_COLOR; - else - color = m_partplate_list->m_is_dark ? LINE_TOP_DARK_COLOR : LINE_TOP_COLOR; - } - m_gridlines.set_color(color); - m_gridlines.render_geometry(); - - glsafe(::glLineWidth(2.0f * m_scale_factor)); - m_gridlines_bolder.set_color(color); - m_gridlines_bolder.render_geometry(); -} - void PartPlate::render_height_limit(PartPlate::HeightLimitMode mode) { if (m_print && m_print->config().print_sequence == PrintSequence::ByObject && mode != HEIGHT_LIMIT_NONE) @@ -809,33 +661,33 @@ void PartPlate::render_icons(bool bottom, bool only_body, int hover_id) { if (!only_body) { if (hover_id == 1) - render_icon_texture(m_del_icon, m_partplate_list->m_del_hovered_texture); + render_icon_texture(m_partplate_list->m_del_icon, m_partplate_list->m_del_hovered_texture); else - render_icon_texture(m_del_icon, m_partplate_list->m_del_texture); + render_icon_texture(m_partplate_list->m_del_icon, m_partplate_list->m_del_texture); if (hover_id == 2) - render_icon_texture(m_orient_icon, m_partplate_list->m_orient_hovered_texture); + render_icon_texture(m_partplate_list->m_orient_icon, m_partplate_list->m_orient_hovered_texture); else - render_icon_texture(m_orient_icon, m_partplate_list->m_orient_texture); + render_icon_texture(m_partplate_list->m_orient_icon, m_partplate_list->m_orient_texture); if (hover_id == 3) - render_icon_texture(m_arrange_icon, m_partplate_list->m_arrange_hovered_texture); + render_icon_texture(m_partplate_list->m_arrange_icon, m_partplate_list->m_arrange_hovered_texture); else - render_icon_texture(m_arrange_icon, m_partplate_list->m_arrange_texture); + render_icon_texture(m_partplate_list->m_arrange_icon, m_partplate_list->m_arrange_texture); if (hover_id == 4) { if (this->is_locked()) - render_icon_texture(m_lock_icon, m_partplate_list->m_locked_hovered_texture); + render_icon_texture(m_partplate_list->m_lock_icon, m_partplate_list->m_locked_hovered_texture); else - render_icon_texture(m_lock_icon, m_partplate_list->m_lockopen_hovered_texture); + render_icon_texture(m_partplate_list->m_lock_icon, m_partplate_list->m_lockopen_hovered_texture); } else { if (this->is_locked()) - render_icon_texture(m_lock_icon, m_partplate_list->m_locked_texture); + render_icon_texture(m_partplate_list->m_lock_icon, m_partplate_list->m_locked_texture); else - render_icon_texture(m_lock_icon, m_partplate_list->m_lockopen_texture); + render_icon_texture(m_partplate_list->m_lock_icon, m_partplate_list->m_lockopen_texture); } - if (hover_id == PLATE_NAME_ID) + if (hover_id == PLATE_NAME_ID) render_icon_texture(m_plate_name_edit_icon, m_partplate_list->m_plate_name_edit_hovered_texture); else render_icon_texture(m_plate_name_edit_icon, m_partplate_list->m_plate_name_edit_texture); @@ -845,26 +697,24 @@ void PartPlate::render_icons(bool bottom, bool only_body, int hover_id) !get_other_layers_print_sequence().empty() || has_spiral_mode_config(); if (hover_id == 5) { if (!has_plate_settings) - render_icon_texture(m_plate_settings_icon, m_partplate_list->m_plate_settings_hovered_texture); + render_icon_texture(m_partplate_list->m_plate_settings_icon, m_partplate_list->m_plate_settings_hovered_texture); else - render_icon_texture(m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_hovered_texture); + render_icon_texture(m_partplate_list->m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_hovered_texture); } else { if (!has_plate_settings) - render_icon_texture(m_plate_settings_icon, m_partplate_list->m_plate_settings_texture); + render_icon_texture(m_partplate_list->m_plate_settings_icon, m_partplate_list->m_plate_settings_texture); else - render_icon_texture(m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_texture); + render_icon_texture(m_partplate_list->m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_texture); } } - - if (m_plate_index >= 0 && m_plate_index < MAX_PLATE_COUNT) { render_icon_texture(m_plate_idx_icon, m_partplate_list->m_idx_textures[m_plate_index]); } } render_plate_name_texture(); } -void PartPlate::render_only_numbers(bool bottom) +void PartPlate::render_numbers(bool bottom) { if (m_plate_index >=0 && m_plate_index < MAX_PLATE_COUNT) { - render_icon_texture(m_plate_idx_icon, m_partplate_list->m_idx_textures[m_plate_index]); + render_icon_texture(m_partplate_list->m_plate_idx_icon, m_partplate_list->m_idx_textures[m_plate_index]); } } @@ -1092,12 +942,15 @@ void PartPlate::on_render_for_picking() { GLShaderProgram *shader = wxGetApp().get_shader("flat"); shader->start_using(); - shader->set_uniform("view_model_matrix", view_mat); + auto model_mat = m_partplate_list->m_plate_trans[m_plate_index].get_matrix(); + shader->set_uniform("view_model_matrix", view_mat * model_mat); shader->set_uniform("projection_matrix", proj_mat); - std::vector gl_models = {&m_triangles, &m_del_icon, &m_orient_icon, &m_arrange_icon, &m_lock_icon, &m_plate_settings_icon, + + std::vector gl_models = {&m_partplate_list->m_triangles, &m_partplate_list->m_del_icon, &m_partplate_list->m_orient_icon, &m_partplate_list->m_arrange_icon, + &m_partplate_list->m_lock_icon, &m_partplate_list->m_plate_settings_icon, &m_plate_name_edit_icon}; for (size_t i = 0; i < gl_models.size(); i++) { - int hover_id = i; + int hover_id = i; std::array color = picking_color_component(hover_id); gl_models[i]->set_color(-1, color); gl_models[i]->render_geometry(); @@ -1119,42 +972,6 @@ std::array PartPlate::picking_color_component(int idx) const void PartPlate::release_opengl_resource() { - if (m_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_vbo_id)); - m_vbo_id = 0; - } - if (m_del_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_del_vbo_id)); - m_del_vbo_id = 0; - } - if (m_orient_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_orient_vbo_id)); - m_orient_vbo_id = 0; - } - if (m_arrange_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_arrange_vbo_id)); - m_arrange_vbo_id = 0; - } - if (m_lock_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_lock_vbo_id)); - m_lock_vbo_id = 0; - } - if (m_plate_settings_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_plate_settings_vbo_id)); - m_plate_settings_vbo_id = 0; - } - if (m_plate_idx_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_plate_idx_vbo_id)); - m_plate_idx_vbo_id = 0; - } - if (m_plate_name_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_plate_name_vbo_id)); - m_plate_name_vbo_id = 0; - } - if (m_plate_name_edit_vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &m_plate_name_edit_vbo_id)); - m_plate_name_edit_vbo_id = 0; - } } std::vector PartPlate::get_extruders(bool conside_custom_gcode) const @@ -1651,7 +1468,12 @@ bool PartPlate::generate_plate_name_texture() } limitTextWidth = wxControl::Ellipsize(cur_plate_name, dc, wxELLIPSIZE_END, bed_width); } - if (limitTextWidth.Length()==0) { + if (limitTextWidth.Length() == 0) { + if (m_name_texture.get_width() > 0) { + m_name_texture.reset(); + m_plate_name_icon.reset(); + calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon); + } return false; } // generate m_name_texture texture from m_name with generate_from_text_string @@ -2263,12 +2085,10 @@ void PartPlate::move_instances_to(PartPlate& left_plate, PartPlate& right_plate, void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon) { - if (m_shape.size() == 4) - { - //rectangle case - for (int i = 0; i < 4; i++) - { - const Vec2d& p = m_shape[i]; + auto &cur_shape = m_partplate_list->m_shape; + if (cur_shape.size() == 4) { // rectangle case + for (int i = 0; i < 4; i++){ + const Vec2d &p = cur_shape[i]; if ((i == 0) || (i == 1)) { logo_polygon.contour.append({ scale_(p(0)), scale_(p(1) - 10.f) }); } @@ -2278,7 +2098,7 @@ void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon) } } else { - for (const Vec2d& p : m_shape) { + for (const Vec2d &p : cur_shape) { logo_polygon.contour.append({ scale_(p(0)), scale_(p(1)) }); } } @@ -2493,37 +2313,13 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve else { ; } - if (m_partplate_list && m_partplate_list->m_bed3d && !m_partplate_list->m_bed3d->get_model_filename().empty()) { - auto cur_bed = m_partplate_list->m_bed3d; - set_logo_box_by_bed(cur_bed->get_cur_bed_model_box()); - } + BoundingBoxf3 box_in_plate_origin; + if (calc_bed_3d_boundingbox(box_in_plate_origin)) { + if ((m_cur_bed_boundingbox.center() - box_in_plate_origin.center()).norm() > 1.0f) { + set_logo_box_by_bed(box_in_plate_origin); + } + } - ExPolygon poly; - /*for (const Vec2d& p : m_shape) { - poly.contour.append({ scale_(p(0)), scale_(p(1)) }); - }*/ - generate_print_polygon(poly); - calc_triangles(poly); - - ExPolygon exclude_poly; - /*for (const Vec2d& p : m_exclude_area) { - exclude_poly.contour.append({ scale_(p(0)), scale_(p(1)) }); - }*/ - generate_exclude_polygon(exclude_poly); - calc_exclude_triangles(exclude_poly); - - const BoundingBox& pp_bbox = poly.contour.bounding_box(); - calc_gridlines(poly, pp_bbox); - - //calc_vertex_for_icons_background(5, m_del_and_background_icon); - //calc_vertex_for_icons(4, m_del_icon); - calc_vertex_for_icons(0, m_del_icon); - calc_vertex_for_icons(1, m_orient_icon); - calc_vertex_for_icons(2, m_arrange_icon); - calc_vertex_for_icons(3, m_lock_icon); - calc_vertex_for_icons(4, m_plate_settings_icon); - //calc_vertex_for_number(0, (m_plate_index < 9), m_plate_idx_icon); - calc_vertex_for_number(0, false, m_plate_idx_icon); calc_vertex_for_plate_name(m_name_texture, m_plate_name_icon);//if (generate_plate_name_texture()) calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon); } @@ -2577,10 +2373,6 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const void PartPlate::render(bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali) { - glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glEnable(GL_BLEND)); - glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glsafe(::glDepthMask(GL_FALSE)); const Camera &camera = wxGetApp().plater()->get_camera(); auto view_mat = camera.get_view_matrix(); auto proj_mat = camera.get_projection_matrix(); @@ -2589,21 +2381,14 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color, shader->start_using(); shader->set_uniform("view_model_matrix", view_mat); shader->set_uniform("projection_matrix", proj_mat); - - if (!bottom) { - // draw background - render_background(force_background_color); - render_exclude_area(force_background_color); - } - render_grid(bottom); render_height_limit(mode); - shader->stop_using(); } { GLShaderProgram *shader = wxGetApp().get_shader("printbed"); shader->start_using(); - shader->set_uniform("view_model_matrix", view_mat); + auto model_mat = m_partplate_list->m_plate_trans[m_plate_index].get_matrix(); + shader->set_uniform("view_model_matrix", view_mat * model_mat); shader->set_uniform("projection_matrix", proj_mat); shader->set_uniform("svg_source", 0); shader->set_uniform("transparent_background", 0); @@ -2617,18 +2402,11 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color, shader->set_uniform("transparent_background", bottom); render_icons(bottom, only_body, hover_id); if (!force_background_color) { - render_only_numbers(bottom); + render_numbers(bottom); } } shader->stop_using(); } - glsafe(::glDepthMask(GL_TRUE)); - glsafe(::glDisable(GL_BLEND)); - - //if (with_label) { - // render_label(canvas); - //} - glsafe(::glDisable(GL_DEPTH_TEST)); } void PartPlate::set_selected() { @@ -3028,6 +2806,7 @@ void PartPlateList::init() first_plate = new PartPlate(this, Vec3d(0.0, 0.0, 0.0), m_plate_width, m_plate_depth, m_plate_height, m_plater, m_model, true, printer_technology); assert(first_plate != NULL); m_plate_list.push_back(first_plate); + update_plate_trans(1); m_print_index = 0; if (printer_technology == ptFFF) @@ -3056,6 +2835,250 @@ void PartPlateList::init() m_intialized = true; } +void PartPlateList::update_plate_trans(int count) +{ + m_update_plate_mats_vbo = true; + m_plate_trans.resize(count); + int cols = compute_colum_count(count); + for (size_t i = 0; i < count; i++) { + Vec2d pos = compute_shape_position(i, cols); + Vec3d plate_origin= Vec3d(pos.x(), pos.y(), 0); + m_plate_trans[i].set_offset(plate_origin); + } +} + +void PartPlateList::update_unselected_plate_trans(int count) { + m_update_unselected_plate_mats_vbo = true; + m_unselected_plate_trans.resize(count - 1); + int cols = compute_colum_count(count); + int index = 0; + for (size_t i = 0; i < count; i++) { + if (i == m_current_plate) { continue; } + Vec2d pos = compute_shape_position(i, cols); + Vec3d plate_origin = Vec3d(pos.x(), pos.y(), 0); + m_unselected_plate_trans[index].set_offset(plate_origin); + index++; + } +} + +void PartPlateList::generate_print_polygon(ExPolygon &print_polygon) +{ + auto compute_points = [&print_polygon](Vec2d ¢er, double radius, double start_angle, double stop_angle, int count) { + double angle_steps; + angle_steps = (stop_angle - start_angle) / (count - 1); + for (int j = 0; j < count; j++) { + double angle = start_angle + j * angle_steps; + double x = center(0) + ::cos(angle) * radius; + double y = center(1) + ::sin(angle) * radius; + print_polygon.contour.append({scale_(x), scale_(y)}); + } + }; + + int points_count = 8; + if (m_shape.size() == 4) { + // rectangle case + for (int i = 0; i < 4; i++) { + const Vec2d &p = m_shape[i]; + Vec2d center; + double start_angle, stop_angle, radius_x, radius_y, radius; + switch (i) { + case 0: + radius = 5.f; + center(0) = p(0) + radius; + center(1) = p(1) + radius; + start_angle = PI; + stop_angle = 1.5 * PI; + compute_points(center, radius, start_angle, stop_angle, points_count); + break; + case 1: print_polygon.contour.append({scale_(p(0)), scale_(p(1))}); break; + case 2: + radius_x = (int) (p(0)) % 10; + radius_y = (int) (p(1)) % 10; + radius = (radius_x > radius_y) ? radius_y : radius_x; + if (radius < 5.0) radius = 5.f; + center(0) = p(0) - radius; + center(1) = p(1) - radius; + start_angle = 0; + stop_angle = 0.5 * PI; + compute_points(center, radius, start_angle, stop_angle, points_count); + break; + case 3: + radius_x = (int) (p(0)) % 10; + radius_y = (int) (p(1)) % 10; + radius = (radius_x > radius_y) ? radius_y : radius_x; + if (radius < 5.0) radius = 5.f; + center(0) = p(0) + radius; + center(1) = p(1) - radius; + start_angle = 0.5 * PI; + stop_angle = PI; + compute_points(center, radius, start_angle, stop_angle, points_count); + break; + } + } + } else { + for (const Vec2d &p : m_shape) { + print_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + } +} + +void PartPlateList::generate_exclude_polygon(ExPolygon &exclude_polygon) +{ + auto compute_exclude_points = [&exclude_polygon](Vec2d ¢er, double radius, double start_angle, double stop_angle, int count) { + double angle_steps; + angle_steps = (stop_angle - start_angle) / (count - 1); + for (int j = 0; j < count; j++) { + double angle = start_angle + j * angle_steps; + double x = center(0) + ::cos(angle) * radius; + double y = center(1) + ::sin(angle) * radius; + exclude_polygon.contour.append({scale_(x), scale_(y)}); + } + }; + + int points_count = 8; + if (m_exclude_areas.size() == 4) { + // rectangle case + for (int i = 0; i < 4; i++) { + const Vec2d &p = m_exclude_areas[i]; + Vec2d center; + double start_angle, stop_angle, radius; + switch (i) { + case 0: + radius = 5.f; + center(0) = p(0) + radius; + center(1) = p(1) + radius; + start_angle = PI; + stop_angle = 1.5 * PI; + compute_exclude_points(center, radius, start_angle, stop_angle, points_count); + break; + case 1: exclude_polygon.contour.append({scale_(p(0)), scale_(p(1))}); break; + case 2: + radius = 3.f; + center(0) = p(0) - radius; + center(1) = p(1) - radius; + start_angle = 0; + stop_angle = 0.5 * PI; + compute_exclude_points(center, radius, start_angle, stop_angle, points_count); + break; + case 3: exclude_polygon.contour.append({scale_(p(0)), scale_(p(1))}); break; + } + } + } else { + for (const Vec2d &p : m_exclude_areas) { + exclude_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + } +} + +void PartPlateList::calc_triangles(const ExPolygon &poly) +{ + auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); + m_triangles.reset(); + if (!m_triangles.init_model_from_poly(triangles, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; +} + +void PartPlateList::calc_exclude_triangles(const ExPolygon &poly) +{ + if (poly.empty()) { + m_exclude_triangles.reset(); + return; + } + auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); + m_exclude_triangles.reset(); + if (!m_exclude_triangles.init_model_from_poly(triangles, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; +} + +void PartPlateList::calc_gridlines(const ExPolygon &poly, const BoundingBox &pp_bbox) +{ + Polylines axes_lines, axes_lines_bolder; + int count = 0; + for (coord_t x = pp_bbox.min(0); x <= pp_bbox.max(0); x += scale_(10.0)) { + Polyline line; + line.append(Point(x, pp_bbox.min(1))); + line.append(Point(x, pp_bbox.max(1))); + + if ((count % 5) == 0) + axes_lines_bolder.push_back(line); + else + axes_lines.push_back(line); + count++; + } + count = 0; + for (coord_t y = pp_bbox.min(1); y <= pp_bbox.max(1); y += scale_(10.0)) { + Polyline line; + line.append(Point(pp_bbox.min(0), y)); + line.append(Point(pp_bbox.max(0), y)); + axes_lines.push_back(line); + + if ((count % 5) == 0) + axes_lines_bolder.push_back(line); + else + axes_lines.push_back(line); + count++; + } + + // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped + Lines gridlines = to_lines(intersection_pl(axes_lines, offset(poly, (float) SCALED_EPSILON))); + Lines gridlines_bolder = to_lines(intersection_pl(axes_lines_bolder, offset(poly, (float) SCALED_EPSILON))); + + // append bed contours + Lines contour_lines = to_lines(poly); + std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines)); + + m_gridlines.reset(); + if (!m_gridlines.init_model_from_lines(gridlines, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; + m_gridlines_bolder.reset(); + if (!m_gridlines_bolder.init_model_from_lines(gridlines_bolder, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; +} + +void PartPlateList::calc_vertex_for_number(int index, bool one_number, GLModel &gl_model) +{ + ExPolygon poly; +#if 0 // in the up area + Vec2d& p = m_shape[2]; + float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2; + + poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP) - PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) }); + poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) }); + poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y) }); +#else // in the bottom + Vec2d &p = m_shape[1]; + float offset_x = one_number ? PARTPLATE_TEXT_OFFSET_X1 : PARTPLATE_TEXT_OFFSET_X2; + + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); +#endif + auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); + gl_model.reset(); + if (!gl_model.init_model_from_poly(triangles, GROUND_Z)) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; +} + +void PartPlateList::calc_vertex_for_icons(int index, GLModel &gl_model) +{ + ExPolygon poly; + Vec2d & p = m_shape[2]; + + poly.contour.append( + {scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), + scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); + poly.contour.append( + {scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); + + auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); + gl_model.reset(); + if (!gl_model.init_model_from_poly(triangles, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; +} + //compute the origin for printable plate with index i Vec3d PartPlateList::compute_origin(int i, int cols) { @@ -3571,6 +3594,14 @@ int PartPlateList::destroy_print(int print_index) return result; } +void PartPlateList::add_plate() { + if (m_plater) m_plater->take_snapshot("add partplate"); + create_plate(); + int new_plate = get_plate_count() - 1; + select_plate(new_plate); + update_plate_trans(get_plate_count()); +} + //delete a plate by index //keep its instance at origin position and add them into next plate if have //update the plate index and position after it @@ -3678,7 +3709,7 @@ int PartPlateList::delete_plate(int index) destroy_print(print_index); delete plate; - + update_plate_trans(get_plate_count()); // FIX: context of BackgroundSliceProcess and gcode preview need to be updated before ObjectList::reload_all_plates(). #if 0 if (m_plater != nullptr) { @@ -3775,6 +3806,7 @@ int PartPlateList::select_plate(int index) m_current_plate = index; m_plate_list[m_current_plate]->set_selected(); + update_unselected_plate_trans(get_plate_count()); //BBS if(m_model) m_model->curr_plate_index = index; @@ -4645,18 +4677,150 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr } /*rendering related functions*/ +void PartPlateList::render_instance(bool bottom, bool only_current, bool only_body, bool force_background_color, int hover_id) +{ + if (m_update_plate_mats_vbo) { + m_update_plate_mats_vbo = false; + GLModel::create_or_update_mats_vbo(m_plate_mats_vbo, m_plate_trans); + } + if (m_update_unselected_plate_mats_vbo) { + m_update_unselected_plate_mats_vbo = false; + GLModel::create_or_update_mats_vbo(m_unselected_plate_mats_vbo, m_unselected_plate_trans); + } + + const Camera &camera = wxGetApp().plater()->get_camera(); + auto view_mat = camera.get_view_matrix(); + auto proj_mat = camera.get_projection_matrix(); + { + auto cur_shader = wxGetApp().get_current_shader(); + if (cur_shader) { + cur_shader->stop_using(); + } + {//for selected + GLShaderProgram *shader = wxGetApp().get_shader("flat"); + shader->start_using(); + shader->set_uniform("view_model_matrix", view_mat * m_plate_trans[m_current_plate].get_matrix()); + shader->set_uniform("projection_matrix", proj_mat); + if (!bottom) { // draw background + render_background(force_background_color); // for selected_plate + render_exclude_area(force_background_color); // for selected_plate + } + render_grid(bottom); // for selected_plate + + shader->stop_using(); + + } + if (!only_current) { + GLShaderProgram *shader = wxGetApp().get_shader("flat_instance"); + shader->start_using(); + auto res =shader->set_uniform("view_matrix", view_mat); + res = shader->set_uniform("projection_matrix", proj_mat); + if (!bottom) {// draw background + render_instance_background(force_background_color);//for unselected_plate + render_instance_exclude_area(force_background_color);//for unselected_plate + } + render_instance_grid(bottom);//for unselected_plate + + shader->stop_using(); + } + } + +} + +void PartPlateList::render_grid(bool bottom) +{ + // glsafe(::glEnable(GL_MULTISAMPLE)); + // draw grid + glsafe(::glLineWidth(1.0f * m_scale_factor)); + ColorRGBA color; + if (bottom) + color = PartPlate::LINE_BOTTOM_COLOR; + else { + color = m_is_dark ? PartPlate::LINE_TOP_SEL_DARK_COLOR : PartPlate::LINE_TOP_SEL_COLOR; + } + m_gridlines.set_color(color); + m_gridlines.render_geometry(); + + glsafe(::glLineWidth(2.0f * m_scale_factor)); + m_gridlines_bolder.set_color(color); + m_gridlines_bolder.render_geometry(); +} + +void PartPlateList::render_instance_grid(bool bottom) +{ + // draw grid + if (m_unselected_plate_trans.size() == 0) { return; } + glsafe(::glLineWidth(1.0f * m_scale_factor)); + ColorRGBA color; + if (bottom) + color = PartPlate::LINE_BOTTOM_COLOR; + else { + color = m_is_dark ? PartPlate::LINE_TOP_DARK_COLOR : PartPlate::LINE_TOP_COLOR; + } + m_gridlines.set_color(color); + m_gridlines.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); + glsafe(::glLineWidth(2.0f * m_scale_factor)); + m_gridlines_bolder.set_color(color); + m_gridlines_bolder.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); +} + +void PartPlateList::render_instance_background(bool force_default_color) +{ + // draw background + ColorRGBA color; + if (!force_default_color) { + color = m_is_dark ? PartPlate::UNSELECT_DARK_COLOR : PartPlate::UNSELECT_COLOR; + } else { + color = PartPlate::DEFAULT_COLOR; + } + m_triangles.set_color(color); + m_triangles.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); +} + +void PartPlateList::render_background(bool force_default_color) { + ColorRGBA color; + if (!force_default_color) { + color = PartPlate::SELECT_COLOR; + } else { + color = PartPlate::DEFAULT_COLOR; + } + m_triangles.set_color(color); + m_triangles.render_geometry(); +} + +void PartPlateList::render_exclude_area(bool force_default_color) +{ + if (force_default_color || !m_exclude_triangles.is_initialized()) // for thumbnail case + return; + ColorRGBA select_color{0.765f, 0.7686f, 0.7686f, 1.0f}; + // draw exclude area + m_exclude_triangles.set_color(select_color); + m_exclude_triangles.render_geometry(); +} + +void PartPlateList::render_instance_exclude_area(bool force_default_color) +{ + if (force_default_color || !m_exclude_triangles.is_initialized()) // for thumbnail case + return; + if (m_unselected_plate_trans.size() == 0) { return; } + ColorRGBA unselect_color{0.9f, 0.9f, 0.9f, 1.0f}; + // draw exclude area + m_exclude_triangles.set_color(unselect_color); + m_exclude_triangles.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); +} + //render void PartPlateList::render(bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali) { const std::lock_guard local_lock(m_plates_mutex); std::vector::iterator it = m_plate_list.begin(); - int plate_hover_index = -1; - int plate_hover_action = -1; - if (hover_id != -1) { - plate_hover_index = hover_id / PartPlate::GRABBER_COUNT; - plate_hover_action = hover_id % PartPlate::GRABBER_COUNT; - } + m_plate_hover_index = -1; + m_plate_hover_action = -1; + if (hover_id != -1) { + m_plate_hover_index = hover_id / PartPlate::GRABBER_COUNT; + m_plate_hover_action = hover_id % PartPlate::GRABBER_COUNT; + } static bool last_dark_mode_status = m_is_dark; if (m_is_dark != last_dark_mode_status) { @@ -4664,24 +4828,35 @@ void PartPlateList::render(bool bottom, bool only_current, bool only_body, int h generate_icon_textures(); }else if(m_del_texture.get_id() == 0) generate_icon_textures(); + + glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + glsafe(::glDepthMask(GL_FALSE)); + + render_instance(bottom, only_current, only_body, false, m_plate_hover_action); + for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) { int current_index = (*it)->get_index(); if (only_current && (current_index != m_current_plate)) continue; if (current_index == m_current_plate) { PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode; - if (plate_hover_index == current_index) - (*it)->render(bottom, only_body, false, height_mode, plate_hover_action, render_cali); + if (m_plate_hover_index == current_index) + (*it)->render(bottom, only_body, false, height_mode, m_plate_hover_action, render_cali); else (*it)->render(bottom, only_body, false, height_mode, -1, render_cali); } else { - if (plate_hover_index == current_index) - (*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali); + if (m_plate_hover_index == current_index) + (*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, m_plate_hover_action, render_cali); else (*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali); } } + glsafe(::glDepthMask(GL_TRUE)); + glsafe(::glDisable(GL_BLEND)); + glsafe(::glDisable(GL_DEPTH_TEST)); } void PartPlateList::render_for_picking_pass() @@ -4689,7 +4864,7 @@ void PartPlateList::render_for_picking_pass() const std::lock_guard local_lock(m_plates_mutex); std::vector::iterator it = m_plate_list.begin(); for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) { - (*it)->render_for_picking(); + (*it)->on_render_for_picking(); } } @@ -4788,7 +4963,29 @@ bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_area calc_bounding_boxes(); update_logo_texture_filename(texture_filename); + update_plate_trans(get_plate_count()); + update_unselected_plate_trans(get_plate_count()); + { // prepare render data + ExPolygon poly; + generate_print_polygon(poly); + calc_triangles(poly); + ExPolygon exclude_poly; + generate_exclude_polygon(exclude_poly); + calc_exclude_triangles(exclude_poly); + + const BoundingBox &pp_bbox = poly.contour.bounding_box(); + calc_gridlines(poly, pp_bbox); + + // calc_vertex_for_icons(4, m_del_icon); + calc_vertex_for_icons(0, m_del_icon); + calc_vertex_for_icons(1, m_orient_icon); + calc_vertex_for_icons(2, m_arrange_icon); + calc_vertex_for_icons(3, m_lock_icon); + calc_vertex_for_icons(4, m_plate_settings_icon); + calc_vertex_for_icons(5, m_plate_filament_map_icon); + calc_vertex_for_number(0, false, m_plate_idx_icon); + } return true; } @@ -4953,12 +5150,13 @@ int PartPlateList::rebuild_plates_after_deserialize(std::vector& previous_ BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plates count %1%") % m_plate_list.size(); update_plate_cols(); update_all_plates_pos_and_size(false, false, false, false); + for (unsigned int i = 0; i < (unsigned int) m_plate_list.size(); ++i) { + m_plate_list[i]->m_partplate_list = this; + }//set_shapes api: every plate use m_partplate_list set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); - for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i) - { + for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i){ bool need_reset_print = false; m_plate_list[i]->m_plater = this->m_plater; - m_plate_list[i]->m_partplate_list = this; m_plate_list[i]->m_model = this->m_model; m_plate_list[i]->printer_technology = this->printer_technology; //check the previous sliced result diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 32c792973..a95d2d860 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -125,36 +125,12 @@ private: mutable std::vector m_exclude_bounding_box; mutable BoundingBoxf3 m_grabber_box; Transform3d m_grabber_trans_matrix; - Slic3r::Geometry::Transformation position; - std::vector positions; - unsigned int m_vbo_id{ 0 }; - GLModel m_triangles; - GLModel m_exclude_triangles; + GLModel m_logo_triangles; - GLModel m_gridlines; - GLModel m_gridlines_bolder; GLModel m_height_limit_common; GLModel m_height_limit_bottom; GLModel m_height_limit_top; - GLModel m_del_icon; GLModel m_plate_name_edit_icon; - //GeometryBuffer m_del_and_background_icon; - mutable unsigned int m_del_vbo_id{ 0 }; - GLModel m_arrange_icon; - mutable unsigned int m_arrange_vbo_id{ 0 }; - GLModel m_orient_icon; - mutable unsigned int m_orient_vbo_id{ 0 }; - GLModel m_lock_icon; - mutable unsigned int m_lock_vbo_id{ 0 }; - GLModel m_plate_settings_icon; - mutable unsigned int m_plate_settings_vbo_id{ 0 }; - GLModel m_plate_filament_map_icon; - mutable unsigned int m_plate_filament_map_vbo_id{0}; - GLModel m_plate_idx_icon; - - mutable unsigned int m_plate_idx_vbo_id{ 0 }; - mutable unsigned int m_plate_name_edit_vbo_id{0}; - GLTexture m_texture; float m_scale_factor{ 1.0f }; GLUquadricObject* m_quadric; @@ -179,24 +155,15 @@ private: void generate_logo_polygon(ExPolygon &logo_polygon); void generate_logo_polygon(ExPolygon &logo_polygon,const BoundingBoxf3& box); void calc_bounding_boxes() const; - void calc_triangles(const ExPolygon& poly); - void calc_exclude_triangles(const ExPolygon& poly); - void calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox); void calc_height_limit(); - void calc_vertex_for_number(int index, bool one_number, GLModel &gl_model); void calc_vertex_for_plate_name(GLTexture &texture, GLModel &buffer); void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, GLModel &buffer); - void calc_vertex_for_icons(int index, GLModel &gl_model); void calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer); - - void render_background(bool force_default_color = false); + bool calc_bed_3d_boundingbox(BoundingBoxf3 & box_in_plate_origin); void render_logo(bool bottom, bool render_cali = true); void render_logo_texture(GLTexture &logo_texture, GLModel &logo_buffer, bool bottom); - void render_exclude_area(bool force_default_color); - //void render_background_for_picking(const float* render_color) const; - void render_grid(bool bottom); void render_height_limit(PartPlate::HeightLimitMode mode = HEIGHT_LIMIT_BOTH); void render_label(GLCanvas3D& canvas) const; void render_grabber(const float* render_color, bool use_lighting) const; @@ -209,7 +176,7 @@ private: void render_plate_name_texture(); void render_icons(bool bottom, bool only_body = false, int hover_id = -1); - void render_only_numbers(bool bottom); + void render_numbers(bool bottom); void on_render_for_picking(); std::array picking_color_component(int idx) const; void release_opengl_resource(); @@ -382,7 +349,6 @@ public: bool intersects(const BoundingBoxf3& bb) const; void render(bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false); - void render_for_picking() { on_render_for_picking(); } void set_selected(); void set_unselected(); void set_hover_id(int id) { m_hover_id = id; } @@ -611,6 +577,39 @@ class PartPlateList : public ObjectBase friend class cereal::access; friend class UndoRedo::StackImpl; friend class PartPlate; +//render plate repetitive object and so on +private: + void generate_print_polygon(ExPolygon &print_polygon); + void generate_exclude_polygon(ExPolygon &exclude_polygon); + void calc_triangles(const ExPolygon &poly); + void calc_vertex_for_icons(int index, GLModel &gl_model); + void calc_exclude_triangles(const ExPolygon &poly); + void calc_gridlines(const ExPolygon &poly, const BoundingBox &pp_bbox); + void calc_vertex_for_number(int index, bool one_number, GLModel &gl_model); +private: + int m_plate_hover_index{-1}; + int m_plate_hover_action{-1}; + + std::vector m_plate_trans; // MAX_PLATE_COUNT + unsigned int m_plate_mats_vbo{0}; + bool m_update_plate_mats_vbo{true}; + + std::vector m_unselected_plate_trans; + unsigned int m_unselected_plate_mats_vbo{0}; + bool m_update_unselected_plate_mats_vbo{true}; + + GLModel m_triangles; + GLModel m_exclude_triangles; + GLModel m_gridlines; + GLModel m_gridlines_bolder; + GLModel m_del_icon; + GLModel m_arrange_icon; + GLModel m_orient_icon; + GLModel m_lock_icon; + GLModel m_plate_settings_icon; + GLModel m_plate_filament_map_icon; + GLModel m_plate_idx_icon; + float m_scale_factor{1.0f}; public: class BedTextureInfo { @@ -676,9 +675,12 @@ public: //compute the origin for printable plate with index i using new width Vec3d compute_origin_using_new_size(int i, int new_width, int new_depth); + void update_plate_trans(int count); + void update_unselected_plate_trans(int count); //reset partplate to init states void reinit(); void set_bed3d(Bed3D* _bed3d); + Bed3D *get_bed3d() { return m_bed3d; } //get the plate stride double plate_stride_x(); double plate_stride_y(); @@ -695,6 +697,7 @@ public: //destroy print which has the index of print_index int destroy_print(int print_index); + void add_plate(); //delete a plate by index int delete_plate(int index); @@ -804,6 +807,18 @@ public: void postprocess_arrange_polygon(arrangement::ArrangePolygon& arrange_polygon, bool selected); /*rendering related functions*/ + void render_instance(bool bottom, + bool only_current = false, + bool only_body = false, + bool force_background_color = false, + int hover_id = -1); + void render_instance_grid(bool bottom); + void render_instance_background(bool force_default_color = false); + void render_grid(bool bottom); + void render_background(bool force_default_color = false); + void render_exclude_area(bool force_default_color); + void render_instance_exclude_area(bool force_default_color); + void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; } void render(bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false); void render_for_picking_pass(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 34b1a94d8..a3967c8c6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6939,10 +6939,7 @@ void Plater::priv::on_action_add(SimpleEvent&) void Plater::priv::on_action_add_plate(SimpleEvent&) { if (q != nullptr) { - take_snapshot("add partplate"); - this->partplate_list.create_plate(); - int new_plate = this->partplate_list.get_plate_count() - 1; - this->partplate_list.select_plate(new_plate); + partplate_list.add_plate(); update(); // BBS set default view diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ef66c03ec..f7d06fc64 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -5070,7 +5070,21 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_proje //BBS record current preset name std::string curr_preset_name = m_presets->get_edited_preset().name; - + auto curr_preset = m_presets->get_edited_preset(); + std::map extra_map; + { + bool is_configed_by_BBL = PresetUtils::system_printer_bed_model(curr_preset).size() > 0; + if (is_configed_by_BBL && wxGetApp().app_config->has_section("user_bbl_svg_list")) { + auto user_bbl_svg_list = wxGetApp().app_config->get_section("user_bbl_svg_list"); + if (user_bbl_svg_list.size() > 0 && user_bbl_svg_list[curr_preset_name].size() > 0) { + extra_map["bed_custom_texture"] = ConfigOptionString(user_bbl_svg_list[curr_preset_name]); + } + } + auto bed_model_path = wxGetApp().plater()->get_partplate_list().get_bed3d()->get_model_filename(); + if (!bed_model_path.empty()) { + extra_map["bed_custom_model"] = bed_model_path; + } + } bool exist_preset = false; Preset* new_preset = m_presets->find_preset(name, false); if (new_preset) { @@ -5078,7 +5092,7 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_proje } // Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini - m_presets->save_current_preset(name, detach, save_to_project); + m_presets->save_current_preset(name, detach, save_to_project, nullptr, &extra_map); //BBS create new settings new_preset = m_presets->find_preset(name, false, true);