Follow-up of d6fdf2d5c2
-> Automatic generation of missing thumbnails
This commit is contained in:
parent
0cdc54b710
commit
44d31f9bf2
@ -25,19 +25,19 @@ std::string Camera::get_type_as_string() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Unknown: return "unknown";
|
||||
case Perspective: return "perspective";
|
||||
case EType::Unknown: return "unknown";
|
||||
case EType::Perspective: return "perspective";
|
||||
default:
|
||||
case Ortho: return "orthographic";
|
||||
case EType::Ortho: return "orthographic";
|
||||
};
|
||||
}
|
||||
|
||||
void Camera::set_type(EType type)
|
||||
{
|
||||
if (m_type != type) {
|
||||
if (m_type != type && (type == EType::Ortho || type == EType::Perspective)) {
|
||||
m_type = type;
|
||||
if (m_update_config_on_type_change_enabled) {
|
||||
wxGetApp().app_config->set("use_perspective_camera", (m_type == Perspective) ? "1" : "0");
|
||||
wxGetApp().app_config->set("use_perspective_camera", (m_type == EType::Perspective) ? "1" : "0");
|
||||
wxGetApp().app_config->save();
|
||||
}
|
||||
}
|
||||
@ -46,7 +46,7 @@ void Camera::set_type(EType type)
|
||||
void Camera::select_next_type()
|
||||
{
|
||||
unsigned char next = (unsigned char)m_type + 1;
|
||||
if (next == (unsigned char)Num_types)
|
||||
if (next == (unsigned char)EType::Num_types)
|
||||
next = 1;
|
||||
|
||||
set_type((EType)next);
|
||||
@ -95,10 +95,10 @@ double Camera::get_fov() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Perspective:
|
||||
case EType::Perspective:
|
||||
return 2.0 * Geometry::rad2deg(std::atan(1.0 / m_projection_matrix.matrix()(1, 1)));
|
||||
default:
|
||||
case Ortho:
|
||||
case EType::Ortho:
|
||||
return 0.0;
|
||||
};
|
||||
}
|
||||
@ -143,12 +143,12 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
||||
switch (m_type)
|
||||
{
|
||||
default:
|
||||
case Ortho:
|
||||
case EType::Ortho:
|
||||
{
|
||||
m_gui_scale = 1.0;
|
||||
break;
|
||||
}
|
||||
case Perspective:
|
||||
case EType::Perspective:
|
||||
{
|
||||
// scale near plane to keep w and h constant on the plane at z = m_distance
|
||||
const double scale = m_frustrum_zs.first / m_distance;
|
||||
@ -165,12 +165,12 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
||||
switch (m_type)
|
||||
{
|
||||
default:
|
||||
case Ortho:
|
||||
case EType::Ortho:
|
||||
{
|
||||
glsafe(::glOrtho(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second));
|
||||
break;
|
||||
}
|
||||
case Perspective:
|
||||
case EType::Perspective:
|
||||
{
|
||||
glsafe(::glFrustum(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second));
|
||||
break;
|
||||
@ -501,7 +501,7 @@ void Camera::set_default_orientation()
|
||||
const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
|
||||
m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ());
|
||||
m_view_rotation.normalize();
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- camera_pos), m_view_rotation, Vec3d(1., 1., 1.));
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
|
||||
}
|
||||
|
||||
Vec3d Camera::validate_target(const Vec3d& target) const
|
||||
|
@ -18,7 +18,7 @@ struct Camera
|
||||
static double FrustrumZMargin;
|
||||
static double MaxFovDeg;
|
||||
|
||||
enum EType : unsigned char
|
||||
enum class EType : unsigned char
|
||||
{
|
||||
Unknown,
|
||||
Ortho,
|
||||
@ -29,7 +29,7 @@ struct Camera
|
||||
bool requires_zoom_to_bed{ false };
|
||||
|
||||
private:
|
||||
EType m_type{ Perspective };
|
||||
EType m_type{ EType::Perspective };
|
||||
bool m_update_config_on_type_change_enabled{ false };
|
||||
Vec3d m_target{ Vec3d::Zero() };
|
||||
float m_zenit{ 45.0f };
|
||||
@ -54,7 +54,7 @@ public:
|
||||
std::string get_type_as_string() const;
|
||||
void set_type(EType type);
|
||||
// valid values for type: "0" -> ortho, "1" -> perspective
|
||||
void set_type(const std::string& type) { set_type((type == "1") ? Perspective : Ortho); }
|
||||
void set_type(const std::string& type) { set_type((type == "1") ? EType::Perspective : EType::Ortho); }
|
||||
void select_next_type();
|
||||
|
||||
void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; }
|
||||
|
@ -2417,7 +2417,7 @@ void GCodeViewer::render_toolpaths() const
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
double zoom = camera.get_zoom();
|
||||
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||
float near_plane_height = camera.get_type() == Camera::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) :
|
||||
float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) :
|
||||
static_cast<float>(viewport[3]) * 0.0005;
|
||||
|
||||
auto set_uniform_color = [](const std::array<float, 3>& color, GLShaderProgram& shader) {
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "slic3r/GUI/GUI_Preview.hpp"
|
||||
#include "slic3r/GUI/OpenGLManager.hpp"
|
||||
#include "slic3r/GUI/3DBed.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
|
||||
@ -697,7 +696,7 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
|
||||
Vec3d screen_box_center = world_to_screen * owner.world_box.center();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
if (camera.get_type() == Camera::Perspective) {
|
||||
if (camera.get_type() == Camera::EType::Perspective) {
|
||||
x = (0.5f + 0.001f * 0.5f * (float)screen_box_center(0)) * viewport[2];
|
||||
y = (0.5f - 0.001f * 0.5f * (float)screen_box_center(1)) * viewport[3];
|
||||
} else {
|
||||
@ -1589,13 +1588,18 @@ void GLCanvas3D::render()
|
||||
#endif // ENABLE_RENDER_STATISTICS
|
||||
}
|
||||
|
||||
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)
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
|
||||
{
|
||||
render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type);
|
||||
}
|
||||
|
||||
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
{
|
||||
switch (OpenGLManager::get_framebuffers_type())
|
||||
{
|
||||
case OpenGLManager::EFramebufferType::Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; }
|
||||
case OpenGLManager::EFramebufferType::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; }
|
||||
case OpenGLManager::EFramebufferType::Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; }
|
||||
case OpenGLManager::EFramebufferType::Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; }
|
||||
default: { _render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params, volumes, camera_type); break; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -4086,7 +4090,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 show_bed, bool transparent_background)
|
||||
void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
{
|
||||
auto is_visible = [](const GLVolume& v) {
|
||||
bool ret = v.printable;
|
||||
@ -4099,9 +4103,9 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
||||
|
||||
GLVolumePtrs visible_volumes;
|
||||
|
||||
for (GLVolume* vol : m_volumes.volumes) {
|
||||
if (!vol->is_modifier && !vol->is_wipe_tower && (!parts_only || (vol->composite_id.volume_id >= 0))) {
|
||||
if (!printable_only || is_visible(*vol))
|
||||
for (GLVolume* vol : volumes.volumes) {
|
||||
if (!vol->is_modifier && !vol->is_wipe_tower && (!thumbnail_params.parts_only || vol->composite_id.volume_id >= 0)) {
|
||||
if (!thumbnail_params.printable_only || is_visible(*vol))
|
||||
visible_volumes.emplace_back(vol);
|
||||
}
|
||||
}
|
||||
@ -4109,37 +4113,37 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
||||
if (visible_volumes.empty())
|
||||
return;
|
||||
|
||||
BoundingBoxf3 box;
|
||||
BoundingBoxf3 volumes_box;
|
||||
for (const GLVolume* vol : visible_volumes) {
|
||||
box.merge(vol->transformed_bounding_box());
|
||||
volumes_box.merge(vol->transformed_bounding_box());
|
||||
}
|
||||
|
||||
Camera camera;
|
||||
camera.set_type(Camera::Ortho);
|
||||
camera.set_type(camera_type);
|
||||
camera.set_scene_box(scene_bounding_box());
|
||||
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||
camera.zoom_to_volumes(visible_volumes);
|
||||
camera.zoom_to_box(volumes_box);
|
||||
camera.apply_view_matrix();
|
||||
|
||||
double near_z = -1.0;
|
||||
double far_z = -1.0;
|
||||
|
||||
if (show_bed) {
|
||||
if (thumbnail_params.show_bed) {
|
||||
// extends the near and far z of the frustrum to avoid the bed being clipped
|
||||
|
||||
// box in eye space
|
||||
BoundingBoxf3 t_bed_box = wxGetApp().plater()->get_bed().get_bounding_box(true).transformed(camera.get_view_matrix());
|
||||
near_z = -t_bed_box.max(2);
|
||||
far_z = -t_bed_box.min(2);
|
||||
near_z = -t_bed_box.max.z();
|
||||
far_z = -t_bed_box.min.z();
|
||||
}
|
||||
|
||||
camera.apply_projection(box, near_z, far_z);
|
||||
camera.apply_projection(volumes_box, near_z, far_z);
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
if (transparent_background)
|
||||
if (thumbnail_params.transparent_background)
|
||||
glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
@ -4161,15 +4165,15 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
if (show_bed)
|
||||
if (thumbnail_params.show_bed)
|
||||
_render_bed(!camera.is_looking_downward(), false);
|
||||
|
||||
// restore background color
|
||||
if (transparent_background)
|
||||
if (thumbnail_params.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 show_bed, bool transparent_background)
|
||||
void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
{
|
||||
thumbnail_data.set(w, h);
|
||||
if (!thumbnail_data.is_valid())
|
||||
@ -4219,7 +4223,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
|
||||
glsafe(::glDrawBuffers(1, drawBufs));
|
||||
|
||||
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
|
||||
_render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background);
|
||||
_render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type);
|
||||
|
||||
if (multisample) {
|
||||
GLuint resolve_fbo;
|
||||
@ -4268,7 +4272,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 show_bed, bool transparent_background)
|
||||
void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
{
|
||||
thumbnail_data.set(w, h);
|
||||
if (!thumbnail_data.is_valid())
|
||||
@ -4318,7 +4322,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data
|
||||
glsafe(::glDrawBuffers(1, drawBufs));
|
||||
|
||||
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_render_thumbnail_internal(thumbnail_data, printable_only, parts_only, show_bed, transparent_background);
|
||||
_render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type);
|
||||
|
||||
if (multisample) {
|
||||
GLuint resolve_fbo;
|
||||
@ -4367,7 +4371,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 show_bed, bool transparent_background)
|
||||
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
|
||||
{
|
||||
// check that thumbnail size does not exceed the default framebuffer size
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
@ -4383,7 +4387,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, show_bed, transparent_background);
|
||||
_render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type);
|
||||
|
||||
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "MeshUtils.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GCodeViewer.hpp"
|
||||
#include "Camera.hpp"
|
||||
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
|
||||
@ -37,9 +38,9 @@ class wxGLContext;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
struct Camera;
|
||||
class BackgroundSlicingProcess;
|
||||
struct ThumbnailData;
|
||||
struct ThumbnailsParams;
|
||||
class ModelObject;
|
||||
class ModelInstance;
|
||||
class PrintObject;
|
||||
@ -622,7 +623,8 @@ public:
|
||||
void render();
|
||||
// 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 show_bed, bool transparent_background);
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
|
||||
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
|
||||
void select_all();
|
||||
void deselect_all();
|
||||
@ -846,13 +848,13 @@ private:
|
||||
bool _render_undo_redo_stack(const bool is_undo, float pos_x);
|
||||
bool _render_search_list(float pos_x);
|
||||
bool _render_arrange_menu(float pos_x);
|
||||
void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background);
|
||||
void _render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
// 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 show_bed, bool transparent_background);
|
||||
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
// 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 show_bed, bool transparent_background);
|
||||
void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
// 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 show_bed, bool transparent_background);
|
||||
void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
|
||||
|
||||
void _update_volumes_hover_state();
|
||||
|
||||
|
@ -3,7 +3,9 @@
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
@ -11,16 +13,22 @@
|
||||
#include <wx/button.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/notebook.h>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "format.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "Notebook.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "3DBed.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include <wx/notebook.h>
|
||||
#include "Notebook.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@ -209,7 +217,7 @@ static void add_lock(wxImage& image)
|
||||
// add_border(image);
|
||||
}
|
||||
|
||||
static void add_def_img(wxImageList* img_list, bool is_system, std::string stl_path)
|
||||
static void add_default_image(wxImageList* img_list, bool is_system, std::string stl_path)
|
||||
{
|
||||
wxBitmap bmp = create_scaled_bitmap("cog", nullptr, IMG_PX_CNT, true);
|
||||
|
||||
@ -243,11 +251,63 @@ static std::string get_dir_path(bool sys_dir)
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string name_from_path(fs::path path)
|
||||
static void generate_thumbnail_from_stl(const std::string& filename)
|
||||
{
|
||||
std::string filename = path.filename().string();
|
||||
filename.erase(filename.size() - 4); // Remove the extention suffix.
|
||||
return filename;
|
||||
if (!boost::algorithm::iends_with(filename, ".stl")) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Found invalid file type in generate_thumbnail_from_stl() [" << filename << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
Model model;
|
||||
try {
|
||||
model = Model::read_from_file(filename);
|
||||
}
|
||||
catch (std::exception&) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Error loading model from " << filename << " in generate_thumbnail_from_stl()";
|
||||
return;
|
||||
}
|
||||
|
||||
assert(model.objects.size() == 1);
|
||||
assert(model.objects[0]->volumes.size() == 1);
|
||||
assert(model.objects[0]->instances.size() == 1);
|
||||
|
||||
model.objects[0]->center_around_origin(false);
|
||||
model.objects[0]->ensure_on_bed(false);
|
||||
|
||||
const Vec3d bed_center_3d = wxGetApp().plater()->get_bed().get_bounding_box(false).center();
|
||||
const Vec2d bed_center_2d = { bed_center_3d.x(), bed_center_3d.y()};
|
||||
model.center_instances_around_point(bed_center_2d);
|
||||
|
||||
GLVolumeCollection volumes;
|
||||
volumes.volumes.push_back(new GLVolume());
|
||||
GLVolume* volume = volumes.volumes[0];
|
||||
volume->indexed_vertex_array.load_mesh(model.mesh());
|
||||
volume->indexed_vertex_array.finalize_geometry(true);
|
||||
volume->set_instance_transformation(model.objects[0]->instances[0]->get_transformation());
|
||||
volume->set_volume_transformation(model.objects[0]->volumes[0]->get_transformation());
|
||||
|
||||
ThumbnailData thumbnail_data;
|
||||
const ThumbnailsParams thumbnail_params = { {}, false, false, false, true };
|
||||
wxGetApp().plater()->canvas3D()->render_thumbnail(thumbnail_data, 256, 256, thumbnail_params, volumes, Camera::EType::Perspective);
|
||||
|
||||
if (thumbnail_data.width == 0 || thumbnail_data.height == 0)
|
||||
return;
|
||||
|
||||
wxImage image(thumbnail_data.width, thumbnail_data.height);
|
||||
image.InitAlpha();
|
||||
|
||||
for (unsigned int r = 0; r < thumbnail_data.height; ++r) {
|
||||
unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width;
|
||||
for (unsigned int c = 0; c < thumbnail_data.width; ++c) {
|
||||
unsigned char* px = (unsigned char*)thumbnail_data.pixels.data() + 4 * (rr + c);
|
||||
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
|
||||
image.SetAlpha((int)c, (int)r, px[3]);
|
||||
}
|
||||
}
|
||||
|
||||
fs::path out_path = fs::path(filename);
|
||||
out_path.replace_extension("png");
|
||||
image.SaveFile(out_path.string(), wxBITMAP_TYPE_PNG);
|
||||
}
|
||||
|
||||
void GalleryDialog::load_label_icon_list()
|
||||
@ -260,12 +320,14 @@ void GalleryDialog::load_label_icon_list()
|
||||
|
||||
for (auto& dir_entry : fs::directory_iterator(dir))
|
||||
if (is_stl_file(dir_entry)) {
|
||||
std::string name = name_from_path(dir_entry.path());
|
||||
std::string name = dir_entry.path().stem().string();
|
||||
Item item = Item{ name, sys_dir };
|
||||
items.push_back(item);
|
||||
}
|
||||
};
|
||||
|
||||
wxBusyCursor busy;
|
||||
|
||||
std::string m_sys_dir_path, m_cust_dir_path;
|
||||
std::vector<Item> list_items;
|
||||
add_files_from_gallery(list_items, true, m_sys_dir_path);
|
||||
@ -282,15 +344,13 @@ void GalleryDialog::load_label_icon_list()
|
||||
for (const auto& item : list_items) {
|
||||
std::string img_name = (item.is_system ? m_sys_dir_path : m_cust_dir_path) + item.name + ext;
|
||||
std::string stl_name = (item.is_system ? m_sys_dir_path : m_cust_dir_path) + item.name + ".stl";
|
||||
if (!fs::exists(img_name)) {
|
||||
add_def_img(m_image_list, item.is_system, stl_name);
|
||||
continue;
|
||||
}
|
||||
if (!fs::exists(img_name))
|
||||
generate_thumbnail_from_stl(stl_name);
|
||||
|
||||
wxImage image;
|
||||
if (!image.LoadFile(from_u8(img_name), wxBITMAP_TYPE_PNG) ||
|
||||
image.GetWidth() == 0 || image.GetHeight() == 0) {
|
||||
add_def_img(m_image_list, item.is_system, stl_name);
|
||||
add_default_image(m_image_list, item.is_system, stl_name);
|
||||
continue;
|
||||
}
|
||||
image.Rescale(px_cnt, px_cnt, wxIMAGE_QUALITY_BILINEAR);
|
||||
@ -435,12 +495,12 @@ bool GalleryDialog::load_files(const wxArrayString& input_files)
|
||||
if (!fs::exists(dest_dir / current.filename()))
|
||||
fs::copy_file(current, dest_dir / current.filename());
|
||||
else {
|
||||
std::string filename = name_from_path(current);
|
||||
std::string filename = current.stem().string();
|
||||
|
||||
int file_idx = 0;
|
||||
for (auto& dir_entry : fs::directory_iterator(dest_dir))
|
||||
if (is_stl_file(dir_entry)) {
|
||||
std::string name = name_from_path(dir_entry.path());
|
||||
std::string name = dir_entry.path().stem().string();
|
||||
if (filename == name) {
|
||||
if (file_idx == 0)
|
||||
file_idx++;
|
||||
|
@ -1788,8 +1788,8 @@ struct Plater::priv
|
||||
bool can_replace_with_stl() const;
|
||||
bool can_split(bool to_objects) const;
|
||||
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background);
|
||||
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params);
|
||||
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
|
||||
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type);
|
||||
|
||||
void bring_instance_forward() const;
|
||||
|
||||
@ -1865,7 +1865,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
background_process.set_fff_print(&fff_print);
|
||||
background_process.set_sla_print(&sla_print);
|
||||
background_process.set_gcode_result(&gcode_result);
|
||||
background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params); });
|
||||
background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); });
|
||||
background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
|
||||
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
|
||||
background_process.set_export_began_event(EVT_EXPORT_BEGAN);
|
||||
@ -4074,18 +4074,18 @@ void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
|
||||
{
|
||||
view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, show_bed, transparent_background);
|
||||
view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type);
|
||||
}
|
||||
|
||||
ThumbnailsList Plater::priv::generate_thumbnails(const ThumbnailsParams& params)
|
||||
ThumbnailsList Plater::priv::generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type)
|
||||
{
|
||||
ThumbnailsList thumbnails;
|
||||
for (const Vec2d& size : params.sizes) {
|
||||
thumbnails.push_back(ThumbnailData());
|
||||
Point isize(size); // round to ints
|
||||
generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), params.printable_only, params.parts_only, params.show_bed, params.transparent_background);
|
||||
generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), params, camera_type);
|
||||
if (!thumbnails.back().is_valid())
|
||||
thumbnails.pop_back();
|
||||
}
|
||||
@ -5630,7 +5630,8 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
||||
wxBusyCursor wait;
|
||||
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
|
||||
ThumbnailData thumbnail_data;
|
||||
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
|
||||
ThumbnailsParams thumbnail_params = { {}, false, true, true, true };
|
||||
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, thumbnail_params, Camera::EType::Ortho);
|
||||
#if ENABLE_PROJECT_DIRTY_STATE
|
||||
bool ret = Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data);
|
||||
if (ret) {
|
||||
|
Loading…
Reference in New Issue
Block a user