Custom bed model introduced.

This commit is contained in:
H. Gregor Molter 2019-06-10 20:16:16 +02:00 committed by supermerill
parent a2953c31cc
commit c45a6a9e52
4 changed files with 261 additions and 9 deletions

View File

@ -53,6 +53,12 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }); def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) });
def = this->add("custom_bed_view", coString);
def->label = L("Prefix for custom bed rendering");
def->tooltip = L("Filename prefix (filename without extension) of the custom bed .stl and .svg files");
def->set_default_value(new ConfigOptionString());
def->cli = ConfigOptionDef::nocli;
def = this->add("layer_height", coFloat); def = this->add("layer_height", coFloat);
def->label = L("Base Layer height"); def->label = L("Base Layer height");
def->category = L("Layers and Perimeters"); def->category = L("Layers and Perimeters");

View File

@ -273,7 +273,7 @@ void Bed3D::Axes::render_axis(double length) const
} }
Bed3D::Bed3D() Bed3D::Bed3D()
: m_type(Custom) : m_type(Custom), m_bed_view_prefix("")
, m_requires_canvas_update(false) , m_requires_canvas_update(false)
#if ENABLE_TEXTURES_FROM_SVG #if ENABLE_TEXTURES_FROM_SVG
, m_vbo_id(0) , m_vbo_id(0)
@ -284,13 +284,16 @@ Bed3D::Bed3D()
bool Bed3D::set_shape(const Pointfs& shape) bool Bed3D::set_shape(const Pointfs& shape)
{ {
EType new_type = detect_type(shape); std::string new_bed_view_prefix;
if (m_shape == shape && m_type == new_type) EType new_type;
std::tie(new_type, new_bed_view_prefix) = detect_type(shape);
if (m_shape == shape && m_type == new_type && m_bed_view_prefix == new_bed_view_prefix)
// No change, no need to update the UI. // No change, no need to update the UI.
return false; return false;
m_shape = shape; m_shape = shape;
m_type = new_type; m_type = new_type;
m_bed_view_prefix = new_bed_view_prefix;
calc_bounding_boxes(); calc_bounding_boxes();
@ -352,6 +355,11 @@ void Bed3D::render(GLCanvas3D* canvas, float theta, bool useVBOs, float scale_fa
render_prusa(canvas, "sl1", theta > 90.0f); render_prusa(canvas, "sl1", theta > 90.0f);
break; break;
} }
case CustomBedView:
{
render_custom_bed(theta > 90.0f);
break;
}
default: default:
case Custom: case Custom:
{ {
@ -385,6 +393,11 @@ void Bed3D::render(GLCanvas3D* canvas, float theta, bool useVBOs, float scale_fa
render_prusa(canvas, "sl1", theta, useVBOs); render_prusa(canvas, "sl1", theta, useVBOs);
break; break;
} }
case CustomBedView:
{
render_custom_bed(theta, useVBOs);
break;
}
default: default:
case Custom: case Custom:
{ {
@ -457,9 +470,10 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
printf("Unable to create bed grid lines\n"); printf("Unable to create bed grid lines\n");
} }
Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const std::pair<Bed3D::EType, std::string> Bed3D::detect_type(const Pointfs& shape) const
{ {
EType type = Custom; EType type = Custom;
std::string bed_view_prefix = "";
auto bundle = wxGetApp().preset_bundle; auto bundle = wxGetApp().preset_bundle;
if (bundle != nullptr) if (bundle != nullptr)
@ -469,6 +483,23 @@ Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
{ {
if (curr->config.has("bed_shape")) if (curr->config.has("bed_shape"))
{ {
if (curr->config.has("custom_bed_view") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
{
if (!static_cast<const ConfigOptionString*>(curr->config.option("custom_bed_view"))->value.empty()) {
bed_view_prefix = static_cast<const ConfigOptionString*>(curr->config.option("custom_bed_view"))->value;
boost::filesystem::path path = bed_view_prefix + ".stl";
if (!path.is_absolute())
{
bed_view_prefix = (boost::filesystem::path(Slic3r::data_dir()) / "printer" / bed_view_prefix).string();
path = bed_view_prefix + ".stl";
}
type = CustomBedView;
if (!boost::filesystem::exists(path)) {
type = Custom;
}
break;
}
}
if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values)) if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
{ {
if (boost::contains(curr->name, "SL1")) if (boost::contains(curr->name, "SL1"))
@ -493,7 +524,7 @@ Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
} }
} }
return type; return std::make_pair(type, bed_view_prefix);
} }
#if ENABLE_TEXTURES_FROM_SVG #if ENABLE_TEXTURES_FROM_SVG
@ -650,6 +681,86 @@ void Bed3D::render_prusa_shader(bool transparent) const
m_shader.stop_using(); m_shader.stop_using();
} }
} }
void Bed3D::render_custom_bed(bool bottom) const
{
// use anisotropic filter if graphic card allows
GLfloat max_anisotropy = 0.0f;
if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy));
// use higher resolution images if graphic card allows
GLint max_tex_size;
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size));
// clamp or the texture generation becomes too slow
max_tex_size = std::min(max_tex_size, 8192);
std::string filename = m_bed_view_prefix + ".svg";
if ((m_texture.get_id() == 0) || (m_texture.get_source() != filename))
{
if (!m_texture.load_from_svg_file(filename, true, max_tex_size))
{
render_custom();
return;
}
if (max_anisotropy > 0.0f)
{
glsafe(::glBindTexture(GL_TEXTURE_2D, m_texture.get_id()));
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
}
}
if (!bottom)
{
filename = m_bed_view_prefix + ".stl";
if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, true)) {
Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.5 * m_model.get_bounding_box().size()(2));
offset += Vec3d(0.0, 0.0, -0.03);
m_model.center_around(offset);
}
if (!m_model.get_filename().empty())
{
glsafe(::glEnable(GL_LIGHTING));
m_model.render();
glsafe(::glDisable(GL_LIGHTING));
}
}
unsigned int triangles_vcount = m_triangles.get_vertices_count();
if (triangles_vcount > 0)
{
if (m_vbo_id == 0)
{
glsafe(::glGenBuffers(1, &m_vbo_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)m_triangles.get_vertices_data_size(), (const GLvoid*)m_triangles.get_vertices_data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glDepthMask(GL_FALSE));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
if (bottom)
glsafe(::glFrontFace(GL_CW));
render_prusa_shader(bottom);
if (bottom)
glsafe(::glFrontFace(GL_CCW));
glsafe(::glDisable(GL_BLEND));
glsafe(::glDepthMask(GL_TRUE));
}
}
#else #else
void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) const void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) const
{ {
@ -770,10 +881,141 @@ void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) cons
glsafe(::glDepthMask(GL_TRUE)); glsafe(::glDepthMask(GL_TRUE));
} }
} }
void Bed3D::render_custom_bed(float theta, bool useVBOs) const
{
// use higher resolution images if graphic card allows
GLint max_tex_size;
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size));
// temporary set to lowest resolution
max_tex_size = 2048;
if (max_tex_size >= 8192)
tex_path += "_8192";
else if (max_tex_size >= 4096)
tex_path += "_4096";
// use anisotropic filter if graphic card allows
GLfloat max_anisotropy = 0.0f;
if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy));
std::string filename = m_bed_view_prefix + "_top.png";
if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
{
if (!m_top_texture.load_from_file(filename, true))
{
render_custom();
return;
}
if (max_anisotropy > 0.0f)
{
glsafe(::glBindTexture(GL_TEXTURE_2D, m_top_texture.get_id()));
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
}
}
filename = m_bed_view_prefix + "_bottom.png";
if ((m_bottom_texture.get_id() == 0) || (m_bottom_texture.get_source() != filename))
{
if (!m_bottom_texture.load_from_file(filename, true))
{
render_custom();
return;
}
if (max_anisotropy > 0.0f)
{
glsafe(::glBindTexture(GL_TEXTURE_2D, m_bottom_texture.get_id()));
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
}
}
if (theta <= 90.0f)
{
filename = m_bed_view_prefix + ".stl";
if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) {
Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.5 * m_model.get_bounding_box().size()(2));
if (key == "mk2")
// hardcoded value to match the stl model
offset += Vec3d(0.0, 7.5, -0.03);
else if (key == "mk3")
// hardcoded value to match the stl model
offset += Vec3d(0.0, 5.5, 2.43);
else if (key == "sl1")
// hardcoded value to match the stl model
offset += Vec3d(0.0, 0.0, -0.03);
m_model.center_around(offset);
}
if (!m_model.get_filename().empty())
{
glsafe(::glEnable(GL_LIGHTING));
m_model.render();
glsafe(::glDisable(GL_LIGHTING));
}
}
unsigned int triangles_vcount = m_triangles.get_vertices_count();
if (triangles_vcount > 0)
{
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glDepthMask(GL_FALSE));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(::glEnable(GL_TEXTURE_2D));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY));
if (theta > 90.0f)
glsafe(::glFrontFace(GL_CW));
glsafe(::glBindTexture(GL_TEXTURE_2D, (theta <= 90.0f) ? (GLuint)m_top_texture.get_id() : (GLuint)m_bottom_texture.get_id()));
glsafe(::glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)m_triangles.get_vertices()));
glsafe(::glTexCoordPointer(2, GL_FLOAT, 0, (GLvoid*)m_triangles.get_tex_coords()));
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount));
if (theta > 90.0f)
glsafe(::glFrontFace(GL_CCW));
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisable(GL_TEXTURE_2D));
glsafe(::glDisable(GL_BLEND));
glsafe(::glDepthMask(GL_TRUE));
}
}
#endif // ENABLE_TEXTURES_FROM_SVG #endif // ENABLE_TEXTURES_FROM_SVG
void Bed3D::render_custom() const void Bed3D::render_custom() const
{ {
printf("render_custom:\n");
auto bundle = wxGetApp().preset_bundle;
if (bundle != nullptr)
{
const Preset* curr = &bundle->printers.get_selected_preset();
if (curr->config.has("custom_bed_view")) {
printf("Config has custom_bed_view.\n");
const ConfigOptionString *opt = static_cast<const ConfigOptionString*>(curr->config.option("custom_bed_view"));
printf("STL File: %s\n", opt->value.c_str());
} else {
printf("Config does not have custom_bed_view.\n");
}
}
//if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
#if ENABLE_TEXTURES_FROM_SVG #if ENABLE_TEXTURES_FROM_SVG
m_texture.reset(); m_texture.reset();
#else #else

View File

@ -80,6 +80,7 @@ public:
MK2, MK2,
MK3, MK3,
SL1, SL1,
CustomBedView,
Custom, Custom,
Num_Types Num_Types
}; };
@ -106,6 +107,7 @@ private:
#endif // ENABLE_TEXTURES_FROM_SVG #endif // ENABLE_TEXTURES_FROM_SVG
mutable GLBed m_model; mutable GLBed m_model;
Axes m_axes; Axes m_axes;
std::string m_bed_view_prefix;
mutable float m_scale_factor; mutable float m_scale_factor;
@ -135,12 +137,14 @@ private:
void calc_bounding_boxes() const; void calc_bounding_boxes() const;
void calc_triangles(const ExPolygon& poly); void calc_triangles(const ExPolygon& poly);
void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox); void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
EType detect_type(const Pointfs& shape) const; std::pair<Bed3D::EType, std::string> detect_type(const Pointfs& shape) const;
#if ENABLE_TEXTURES_FROM_SVG #if ENABLE_TEXTURES_FROM_SVG
void render_prusa(GLCanvas3D* canvas, const std::string& key, bool bottom) const; void render_prusa(GLCanvas3D* canvas, const std::string& key, bool bottom) const;
void render_prusa_shader(bool transparent) const; void render_prusa_shader(bool transparent) const;
void render_custom_bed(bool bottom) const;
#else #else
void render_prusa(const std::string &key, float theta, bool useVBOs) const; void render_prusa(const std::string &key, float theta, bool useVBOs) const;
void render_custom_bed(float theta, bool useVBOs) const;
#endif // ENABLE_TEXTURES_FROM_SVG #endif // ENABLE_TEXTURES_FROM_SVG
void render_custom() const; void render_custom() const;
#if ENABLE_TEXTURES_FROM_SVG #if ENABLE_TEXTURES_FROM_SVG

View File

@ -458,7 +458,7 @@ const std::vector<std::string>& Preset::printer_options()
if (s_opts.empty()) { if (s_opts.empty()) {
s_opts = { s_opts = {
"printer_technology", "printer_technology",
"bed_shape", "z_offset", "gcode_flavor", "use_relative_e_distances", "serial_port", "serial_speed", "bed_shape", "custom_bed_view", "z_offset", "gcode_flavor", "use_relative_e_distances", "serial_port", "serial_speed",
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
"host_type", "print_host", "printhost_apikey", "printhost_cafile", "host_type", "print_host", "printhost_apikey", "printhost_cafile",
"single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode",
@ -561,7 +561,7 @@ const std::vector<std::string>& Preset::sla_printer_options()
if (s_opts.empty()) { if (s_opts.empty()) {
s_opts = { s_opts = {
"printer_technology", "printer_technology",
"bed_shape", "max_print_height", "bed_shape", "custom_bed_view", "max_print_height",
"display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_width", "display_height", "display_pixels_x", "display_pixels_y",
"display_mirror_x", "display_mirror_y", "display_mirror_x", "display_mirror_y",
"display_orientation", "display_orientation",