From ddd1df155249a92d41fb35dba433b458e227d0fe Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 28 Nov 2019 14:18:24 +0100 Subject: [PATCH] ENABLE_THUMBNAIL_GENERATOR -> render printbed into thumbnails --- src/libslic3r/GCode.cpp | 2 +- src/libslic3r/GCode/ThumbnailData.hpp | 2 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 8 +-- src/slic3r/GUI/Camera.cpp | 10 ++- src/slic3r/GUI/Camera.hpp | 4 +- src/slic3r/GUI/GLCanvas3D.cpp | 68 +++++++++++++++++---- src/slic3r/GUI/GLCanvas3D.hpp | 10 +-- src/slic3r/GUI/Plater.cpp | 22 +++---- 8 files changed, 89 insertions(+), 37 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 358c77f3f..c88760c16 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -992,7 +992,7 @@ void GCode::_do_export(Print& print, FILE* file) { const size_t max_row_length = 78; ThumbnailsList thumbnails; - thumbnail_cb(thumbnails, print.full_print_config().option("thumbnails")->values, true, true, true); + thumbnail_cb(thumbnails, print.full_print_config().option("thumbnails")->values, true, true, true, true); for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) diff --git a/src/libslic3r/GCode/ThumbnailData.hpp b/src/libslic3r/GCode/ThumbnailData.hpp index efe875e15..4acfe4374 100644 --- a/src/libslic3r/GCode/ThumbnailData.hpp +++ b/src/libslic3r/GCode/ThumbnailData.hpp @@ -22,7 +22,7 @@ struct ThumbnailData }; typedef std::vector ThumbnailsList; -typedef std::function ThumbnailsGeneratorCallback; +typedef std::function ThumbnailsGeneratorCallback; } // namespace Slic3r diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 9108fd196..e587509ac 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -148,8 +148,8 @@ void BackgroundSlicingProcess::process_sla() if (m_thumbnail_cb != nullptr) { ThumbnailsList thumbnails; - m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, true); -// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, true); // renders also supports and pad + m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, true, true); +// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, true, true); // renders also supports and pad for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) @@ -473,8 +473,8 @@ void BackgroundSlicingProcess::prepare_upload() if (m_thumbnail_cb != nullptr) { ThumbnailsList thumbnails; - m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, true); -// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, true); // renders also supports and pad + m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, true, true); +// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, true, true); // renders also supports and pad for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index c7cde1bb3..dfb59f119 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -196,7 +196,7 @@ void Camera::apply_view_matrix() const glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, m_view_matrix.data())); } -void Camera::apply_projection(const BoundingBoxf3& box) const +void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) const { set_distance(DefaultDistance); @@ -207,6 +207,12 @@ void Camera::apply_projection(const BoundingBoxf3& box) const { m_frustrum_zs = calc_tight_frustrum_zs_around(box); + if (near_z > 0.0) + m_frustrum_zs.first = std::min(m_frustrum_zs.first, near_z); + + if (far_z > 0.0) + m_frustrum_zs.second = std::max(m_frustrum_zs.second, far_z); + w = 0.5 * (double)m_viewport[2]; h = 0.5 * (double)m_viewport[3]; @@ -539,7 +545,7 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canv double dx = margin_factor * (max_x - min_x); double dy = margin_factor * (max_y - min_y); - if ((dx == 0.0) || (dy == 0.0)) + if ((dx <= 0.0) || (dy <= 0.0)) return -1.0f; return std::min((double)canvas_w / dx, (double)canvas_h / dy); diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 0674409aa..6cd1b75a5 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -95,7 +95,9 @@ public: void apply_viewport(int x, int y, unsigned int w, unsigned int h) const; void apply_view_matrix() const; - void apply_projection(const BoundingBoxf3& box) const; + // Calculates and applies the projection matrix tighting the frustrum z range around the given box. + // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) + void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0) const; #if ENABLE_THUMBNAIL_GENERATOR void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToBoxMarginFactor); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b90f72898..207d5c756 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1924,13 +1924,13 @@ void GLCanvas3D::render() } #if ENABLE_THUMBNAIL_GENERATOR -void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background) +void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { switch (GLCanvas3DManager::get_framebuffers_type()) { - case GLCanvas3DManager::FB_Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; } - case GLCanvas3DManager::FB_Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; } - default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; } + case GLCanvas3DManager::FB_Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } + case GLCanvas3DManager::FB_Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } + default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } } } #endif // ENABLE_THUMBNAIL_GENERATOR @@ -3884,7 +3884,7 @@ static void debug_output_thumbnail(const ThumbnailData& thumbnail_data) } #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT -void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool transparent_background) +void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { auto is_visible = [](const GLVolume& v) -> bool { @@ -3921,7 +3921,48 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool camera.zoom_to_volumes(visible_volumes, thumbnail_data.width, thumbnail_data.height); camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); camera.apply_view_matrix(); - camera.apply_projection(box); + + double near_z = -1.0; + double far_z = -1.0; + + if (show_bed) + { + // extends the near and far z of the frustrum to avoid the bed being clipped + BoundingBoxf3 bed_box = m_bed.get_bounding_box(true); + + // bed box vertices in world space + std::vector vertices; + vertices.reserve(8); + vertices.push_back(bed_box.min); + vertices.emplace_back(bed_box.max(0), bed_box.min(1), bed_box.min(2)); + vertices.emplace_back(bed_box.max(0), bed_box.max(1), bed_box.min(2)); + vertices.emplace_back(bed_box.min(0), bed_box.max(1), bed_box.min(2)); + vertices.emplace_back(bed_box.min(0), bed_box.min(1), bed_box.max(2)); + vertices.emplace_back(bed_box.max(0), bed_box.min(1), bed_box.max(2)); + vertices.push_back(bed_box.max); + vertices.emplace_back(bed_box.min(0), bed_box.max(1), bed_box.max(2)); + + double bed_box_min_z = DBL_MAX; + double bed_box_max_z = -DBL_MAX; + Transform3d view_matrix = camera.get_view_matrix(); + for (const Vec3d& v : vertices) + { + Vec3d eye_v = view_matrix * v; + if (eye_v(2) < 0.0) + { + bed_box_min_z = std::min(bed_box_min_z, -eye_v(2)); + bed_box_max_z = std::max(bed_box_max_z, -eye_v(2)); + } + } + + if (bed_box_min_z != DBL_MAX) + near_z = bed_box_min_z; + + if (bed_box_max_z != -DBL_MAX) + far_z = bed_box_max_z; + } + + camera.apply_projection(box, near_z, far_z); if (transparent_background) glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); @@ -3953,11 +3994,14 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool glsafe(::glDisable(GL_DEPTH_TEST)); + if (show_bed) + _render_bed(camera.get_theta(), false); + if (transparent_background) glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f)); } -void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background) +void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { thumbnail_data.set(w, h); if (!thumbnail_data.is_valid()) @@ -4010,7 +4054,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) { - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, transparent_background); + _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); if (multisample) { @@ -4061,7 +4105,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un glsafe(::glDisable(GL_MULTISAMPLE)); } -void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background) +void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { thumbnail_data.set(w, h); if (!thumbnail_data.is_valid()) @@ -4114,7 +4158,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) { - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, transparent_background); + _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); if (multisample) { @@ -4165,7 +4209,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data glsafe(::glDisable(GL_MULTISAMPLE)); } -void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background) +void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { // check that thumbnail size does not exceed the default framebuffer size const Size& cnv_size = get_canvas_size(); @@ -4182,7 +4226,7 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne if (!thumbnail_data.is_valid()) return; - _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, transparent_background); + _render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background); glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data())); #if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 9574c6640..3b23a74a5 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -571,7 +571,7 @@ public: #if ENABLE_THUMBNAIL_GENERATOR // printable_only == false -> render also non printable volumes as grayed // parts_only == false -> render also sla support and pad - void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); + void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); #endif // ENABLE_THUMBNAIL_GENERATOR void select_all(); @@ -725,13 +725,13 @@ private: void _render_selection_sidebar_hints() const; void _render_undo_redo_stack(const bool is_undo, float pos_x); #if ENABLE_THUMBNAIL_GENERATOR - void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool transparent_background); + void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); // render thumbnail using an off-screen framebuffer - void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); + void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); // render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported - void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); + void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); // render thumbnail using the default framebuffer - void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); + void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); #endif // ENABLE_THUMBNAIL_GENERATOR void _update_volumes_hover_state() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index acfd5d322..2fbe70d5a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1947,8 +1947,8 @@ struct Plater::priv bool can_reload_from_disk() const; #if ENABLE_THUMBNAIL_GENERATOR - void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); - void generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background); + void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); + void generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background); #endif // ENABLE_THUMBNAIL_GENERATOR void msw_rescale_object_menu(); @@ -2019,13 +2019,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) background_process.set_sla_print(&sla_print); background_process.set_gcode_preview_data(&gcode_preview_data); #if ENABLE_THUMBNAIL_GENERATOR - background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) + background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { - std::packaged_task task([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) { - generate_thumbnails(thumbnails, sizes, printable_only, parts_only, transparent_background); + std::packaged_task task([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { + generate_thumbnails(thumbnails, sizes, printable_only, parts_only, show_bed, transparent_background); }); std::future result = task.get_future(); - wxTheApp->CallAfter([&]() { task(thumbnails, sizes, printable_only, parts_only, transparent_background); }); + wxTheApp->CallAfter([&]() { task(thumbnails, sizes, printable_only, parts_only, show_bed, transparent_background); }); result.wait(); }); #endif // ENABLE_THUMBNAIL_GENERATOR @@ -3653,19 +3653,19 @@ bool Plater::priv::init_object_menu() } #if ENABLE_THUMBNAIL_GENERATOR -void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background) +void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { - view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, transparent_background); + view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, show_bed, transparent_background); } -void Plater::priv::generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) +void Plater::priv::generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) { thumbnails.clear(); for (const Vec2d& size : sizes) { thumbnails.push_back(ThumbnailData()); Point isize(size); // round to ints - generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), printable_only, parts_only, transparent_background); + generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), printable_only, parts_only, show_bed, transparent_background); if (!thumbnails.back().is_valid()) thumbnails.pop_back(); } @@ -4713,7 +4713,7 @@ void Plater::export_3mf(const boost::filesystem::path& output_path) wxBusyCursor wait; #if ENABLE_THUMBNAIL_GENERATOR ThumbnailData thumbnail_data; - p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true); + p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true); if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, &thumbnail_data)) { #else if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {