update slic3r

This commit is contained in:
QIDI TECH
2025-05-08 15:05:30 +08:00
parent 126534997a
commit 011619cf23
307 changed files with 55594 additions and 19386 deletions

View File

@@ -70,25 +70,6 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char
}
#endif // HAS_GLSAFE
// QDS
std::vector<std::array<float, 4>> get_extruders_colors()
{
unsigned char rgba_color[4] = {};
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<std::array<float, 4>> colors_out(colors.size());
for (const std::string &color : colors) {
Slic3r::GUI::BitmapCache::parse_color4(color, rgba_color);
size_t color_idx = &color - &colors.front();
colors_out[color_idx] = {
float(rgba_color[0]) / 255.f,
float(rgba_color[1]) / 255.f,
float(rgba_color[2]) / 255.f,
float(rgba_color[3]) / 255.f,
};
}
return colors_out;
}
float FullyTransparentMaterialThreshold = 0.1f;
float FullTransparentModdifiedToFixAlpha = 0.3f;
const float BlackThreshold = 0.2f;
@@ -273,17 +254,26 @@ void GLIndexedVertexArray::release_geometry()
this->clear();
}
void GLIndexedVertexArray::render() const
void GLIndexedVertexArray::render(const std::shared_ptr<GLShaderProgram>& shader) const
{
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
int position_id = -1;
int normal_id = -1;
position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glEnableVertexAttribArray(position_id));
}
normal_id = shader->get_attrib_location("v_normal");
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr));
glsafe(::glEnableVertexAttribArray(normal_id));
}
// Render using the Vertex Buffer Objects.
if (this->triangle_indices_size > 0) {
@@ -297,30 +287,50 @@ void GLIndexedVertexArray::render() const
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (position_id != -1) {
glsafe(::glDisableVertexAttribArray(position_id));
}
if (normal_id != -1) {
glsafe(::glDisableVertexAttribArray(normal_id));
}
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLIndexedVertexArray::render(
const std::shared_ptr<GLShaderProgram>& shader,
const std::pair<size_t, size_t>& tverts_range,
const std::pair<size_t, size_t>& qverts_range) const
{
// this method has been called before calling finalize() ?
if (this->vertices_and_normals_interleaved_VBO_id == 0 && !this->vertices_and_normals_interleaved.empty())
if (0 == vertices_and_normals_interleaved_VBO_id) {
if (!vertices_and_normals_interleaved.empty()) {
BOOST_LOG_TRIVIAL(info) << boost::format("finalize_geometry");
const_cast<GLIndexedVertexArray*>(this)->finalize_geometry(true);
}
}
if (0 == vertices_and_normals_interleaved_VBO_id) {
return;
}
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
if (0 == triangle_indices_VBO_id && 0 == quad_indices_VBO_id) {
return;
}
// Render using the Vertex Buffer Objects.
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
int position_id = -1;
int normal_id = -1;
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glEnableVertexAttribArray(position_id));
}
normal_id = shader->get_attrib_location("v_normal");
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr));
glsafe(::glEnableVertexAttribArray(normal_id));
}
if (this->triangle_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
@@ -333,8 +343,12 @@ void GLIndexedVertexArray::render(
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (position_id != -1) {
glsafe(::glDisableVertexAttribArray(position_id));
}
if (normal_id != -1) {
glsafe(::glDisableVertexAttribArray(normal_id));
}
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
@@ -343,12 +357,21 @@ const float GLVolume::SinkingContours::HalfWidth = 0.25f;
void GLVolume::SinkingContours::render()
{
const auto& shader = GUI::wxGetApp().get_shader("flat");
if (!shader) {
return;
}
GUI::wxGetApp().bind_shader(shader);
update();
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_shift.x(), m_shift.y(), m_shift.z()));
m_model.render();
glsafe(::glPopMatrix());
const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_shift));
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_model.render_geometry();
GUI::wxGetApp().unbind_shader();
}
void GLVolume::SinkingContours::update()
@@ -495,12 +518,14 @@ GLVolume::GLVolume(float r, float g, float b, float a, bool create_index_data)
, partly_inside(false)
, hover(HS_None)
, is_modifier(false)
, slice_error(false)
, is_wipe_tower(false)
, is_extrusion_path(false)
, force_transparent(false)
, force_native_color(false)
, force_neutral_color(false)
, force_sinking_contours(false)
, picking(false)
, tverts_range(0, size_t(-1))
, qverts_range(0, size_t(-1))
, tverts_range_lod(0, size_t(-1))
@@ -537,7 +562,7 @@ void GLVolume::set_render_color()
bool outside = is_outside || is_below_printbed();
if (force_native_color || force_neutral_color) {
#ifdef ENABLE_OUTSIDE_COLOR
#ifdef ENABBLE_OUTSIDE_COLOR
if (outside && shader_outside_printer_detection_enabled)
set_render_color(OUTSIDE_COLOR);
else {
@@ -722,9 +747,15 @@ Transform3d GLVolume::world_matrix() const
bool GLVolume::is_left_handed() const
{
const Vec3d &m1 = m_instance_transformation.get_mirror();
const Vec3d &m2 = m_volume_transformation.get_mirror();
return m1.x() * m1.y() * m1.z() * m2.x() * m2.y() * m2.z() < 0.;
// reference <Real-Time Rendering Fourth Edition> page 84
// link: https://www.realtimerendering.com/
const auto model_matrix = world_matrix().matrix();
Eigen::Matrix3d subMatrix = model_matrix.block<3, 3>(0, 0);
const auto det = subMatrix.determinant();
if (det < 1e-6f) {
return true;
}
return false;
}
const BoundingBoxf3& GLVolume::transformed_bounding_box() const
@@ -795,7 +826,7 @@ void GLVolume::set_range(double min_z, double max_z)
this->qverts_range.first = this->offsets[i * 2];
this->tverts_range.first = this->offsets[i * 2 + 1];
// Some layers are above $min_z. Which?
for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i);
for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i);
if (i < this->print_zs.size()) {
this->qverts_range.second = this->offsets[i * 2];
this->tverts_range.second = this->offsets[i * 2 + 1];
@@ -807,7 +838,7 @@ void GLVolume::set_range(double min_z, double max_z)
//QDS: add outline related logic
//static unsigned char stencil_data[1284][2944];
void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color) const
void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const std::array<float, 4>& body_color) const
{
if (!is_active)
return;
@@ -815,14 +846,11 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
if (this->is_left_handed())
glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix());
auto camera = GUI::wxGetApp().plater()->get_camera();
auto zoom = camera.get_zoom();
Transform3d vier_mat = camera.get_view_matrix();
Matrix4d vier_proj_mat = camera.get_projection_matrix().matrix() * vier_mat.matrix();
const std::array<int, 4> &viewport = camera.get_viewport();
// QDS: add logic for mmu segmentation rendering
auto render_body = [&]() {
bool color_volume = false;
@@ -839,7 +867,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
if (mv->mmu_segmentation_facets.empty())
break;
std::vector<std::array<float, 4>> colors = get_extruders_colors();
std::vector<std::array<float, 4>> colors = GUI::wxGetApp().plater()->get_extruders_colors();
if (colors.size() == 1) {
break;
}
@@ -852,6 +880,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
std::vector<indexed_triangle_set> its_per_color;
mv->mmu_segmentation_facets.get_facets(*mv, its_per_color);
mmuseg_ivas.resize(its_per_color.size());
for (int idx = 0; idx < its_per_color.size(); idx++) {
if (its_per_color[idx].indices.size() > 0) {
mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]);
@@ -864,16 +893,15 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
}
} while (0);
if (color_volume) {
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
std::vector<std::array<float, 4>> colors = get_extruders_colors();
const auto shader = GUI::wxGetApp().get_current_shader();
if (color_volume && !picking) {
std::vector<std::array<float, 4>> colors = GUI::wxGetApp().plater()->get_extruders_colors();
//when force_transparent, we need to keep the alpha
if (force_native_color && (render_color[3] < 1.0)) {
for (int index = 0; index < colors.size(); index ++)
colors[index][3] = render_color[3];
}
glsafe(::glMultMatrixd(world_matrix().data()));
for (int idx = 0; idx < mmuseg_ivas.size(); idx++) {
GLIndexedVertexArray* iva = &mmuseg_ivas[idx];
if (iva->triangle_indices_size == 0 && iva->quad_indices_size == 0)
@@ -905,7 +933,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
}
}
}
iva->render(this->tverts_range, this->qverts_range);
iva->render(shader, this->tverts_range, this->qverts_range);
/*if (force_native_color && (render_color[3] < 1.0)) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}")
%this %this->name %this->tverts_range.first %this->tverts_range.second
@@ -914,20 +942,18 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
}
}
else {
glsafe(::glMultMatrixd(world_matrix().data()));
auto render_which = [this](std::shared_ptr<GLIndexedVertexArray> cur) {
auto render_which = [this](std::shared_ptr<GLIndexedVertexArray> cur, const std::shared_ptr<GLShaderProgram>& shader) {
if (cur->vertices_and_normals_interleaved_VBO_id > 0) {
cur->render(tverts_range_lod, qverts_range_lod);
cur->render(shader, tverts_range_lod, qverts_range_lod);
} else {// if (cur->vertices_and_normals_interleaved_VBO_id == 0)
if (cur->triangle_indices.size() > 0) {
cur->finalize_geometry(true);
cur->render(tverts_range_lod, qverts_range_lod);
cur->render(shader, tverts_range_lod, qverts_range_lod);
} else {
indexed_vertex_array->render(this->tverts_range, this->qverts_range);
indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range);
}
}
};
Transform3d world_tran = world_matrix();
m_lod_update_index++;
if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY){
m_lod_update_index = 0;
@@ -935,17 +961,17 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]);
}
if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small) {
render_which(indexed_vertex_array_small);
render_which(indexed_vertex_array_small, shader);
} else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle) {
render_which(indexed_vertex_array_middle);
render_which(indexed_vertex_array_middle, shader);
} else {
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range);
}
}
};
//QDS: add logic of outline rendering
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
const auto shader = GUI::wxGetApp().get_current_shader();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader;
if (with_outline && shader != nullptr)
{
@@ -1050,13 +1076,11 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
shader->set_uniform("uniform_color", body_color);
shader->set_uniform("is_outline", true);
glsafe(::glPopMatrix());
glsafe(::glPushMatrix());
Transform3d matrix = world_matrix();
Transform3d world_tran = matrix;
matrix.scale(scale);
glsafe(::glMultMatrixd(matrix.data()));
shader->set_uniform("view_model_matrix", view_matrix * matrix);
m_lod_update_index++;
if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY) {
m_lod_update_index = 0;
@@ -1064,11 +1088,11 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]);
}
if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small && indexed_vertex_array_small->vertices_and_normals_interleaved_VBO_id > 0) {
this->indexed_vertex_array_small->render(this->tverts_range_lod, this->qverts_range_lod);
this->indexed_vertex_array_small->render(shader, this->tverts_range_lod, this->qverts_range_lod);
} else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle && indexed_vertex_array_middle->vertices_and_normals_interleaved_VBO_id > 0) {
this->indexed_vertex_array_middle->render(this->tverts_range_lod, this->qverts_range_lod);
this->indexed_vertex_array_middle->render(shader, this->tverts_range_lod, this->qverts_range_lod);
} else {
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range);
}
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name();
shader->set_uniform("is_outline", false);
@@ -1085,18 +1109,16 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
render_body();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__;
}
glsafe(::glPopMatrix());
if (this->is_left_handed())
glFrontFace(GL_CCW);
}
//QDS add render for simple case
void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_objects, std::vector<std::array<float, 4>> &extruder_colors, bool ban_light) const
void GLVolume::simple_render(const std::shared_ptr<GLShaderProgram>& shader, ModelObjectPtrs &model_objects, std::vector<std::array<float, 4>> &extruder_colors, bool ban_light) const
{
if (this->is_left_handed())
glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix());
bool color_volume = false;
ModelObject* model_object = nullptr;
@@ -1127,8 +1149,7 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj
}
} while (0);
if (color_volume) {
glsafe(::glMultMatrixd(world_matrix().data()));
if (color_volume && !picking) {
for (int idx = 0; idx < mmuseg_ivas.size(); idx++) {
GLIndexedVertexArray& iva = mmuseg_ivas[idx];
if (iva.triangle_indices_size == 0 && iva.quad_indices_size == 0)
@@ -1166,15 +1187,13 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj
}
}
}
iva.render(this->tverts_range, this->qverts_range);
iva.render(shader, this->tverts_range, this->qverts_range);
}
}
else {
glsafe(::glMultMatrixd(world_matrix().data()));
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range);
}
glsafe(::glPopMatrix());
if (this->is_left_handed())
glFrontFace(GL_CCW);
}
@@ -1214,7 +1233,7 @@ GLWipeTowerVolume::GLWipeTowerVolume(const std::vector<std::array<float, 4>>& co
m_colors = colors;
}
void GLWipeTowerVolume::render(bool with_outline,const std::array<float, 4> &body_color) const
void GLWipeTowerVolume::render(const Transform3d& view_matrix, bool with_outline,const std::array<float, 4> &body_color) const
{
if (!is_active)
return;
@@ -1222,22 +1241,28 @@ void GLWipeTowerVolume::render(bool with_outline,const std::array<float, 4> &bod
if (m_colors.size() == 0 || m_colors.size() != iva_per_colors.size())
return;
const auto shader = GUI::wxGetApp().get_current_shader();
if (!shader) {
return;
}
if (this->is_left_handed())
glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(world_matrix().data()));
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
for (int i = 0; i < m_colors.size(); i++) {
if (shader) {
std::array<float, 4> new_color = adjust_color_for_rendering(m_colors[i]);
shader->set_uniform("uniform_color", new_color);
if (!picking) {
ColorRGBA new_color = adjust_color_for_rendering(m_colors[i]);
std::array<float, 4> final_color;
final_color[0] = new_color.r();
final_color[1] = new_color.g();
final_color[2] = new_color.b();
final_color[3] = new_color.a();
shader->set_uniform("uniform_color", final_color);
}
this->iva_per_colors[i].render();
this->iva_per_colors[i].render(shader);
}
glsafe(::glPopMatrix());
if (this->is_left_handed())
glFrontFace(GL_CCW);
}
@@ -1288,7 +1313,7 @@ int GLVolumeCollection::load_object_volume(
GLVolume& v = *new_volume;
v.set_color(color_from_model_volume(*model_volume));
v.name = model_volume->name;
v.is_text_shape = model_volume->get_text_info().m_text.empty();
v.is_text_shape = model_volume->is_text();
const TriangleMesh* mesh_ptr = model_volume->mesh_ptr();
new_volume->ori_mesh = mesh_ptr;
@@ -1448,7 +1473,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
if (height == 0.0f)
height = 0.1f;
std::vector<std::array<float, 4>> extruder_colors = get_extruders_colors();
std::vector<std::array<float, 4>> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors();
std::vector<std::array<float, 4>> colors;
GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list();
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true);
@@ -1489,6 +1514,49 @@ int GLVolumeCollection::load_wipe_tower_preview(
return int(volumes.size() - 1);
}
int GLVolumeCollection::load_real_wipe_tower_preview(
int obj_idx, float pos_x, float pos_y, const TriangleMesh& wt_mesh,const TriangleMesh &brim_mesh,bool render_brim, float rotation_angle, bool size_unknown, bool opengl_initialized)
{
int plate_idx = obj_idx - 1000;
if (wt_mesh.its.vertices.empty()) return int(this->volumes.size() - 1);
std::vector<std::array<float, 4>> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors();
GUI::PartPlateList &ppl = GUI::wxGetApp().plater()->get_partplate_list();
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true);
std::vector<std::array<float, 4>> colors;
if (!plate_extruders.empty()) {
if (plate_extruders.front() <= extruder_colors.size())
colors.push_back(extruder_colors[plate_extruders.front() - 1]);
else
colors.push_back(extruder_colors[0]);
}
if (colors.empty()) return int(this->volumes.size() - 1);
volumes.emplace_back(new GLWipeTowerVolume({colors}));
GLWipeTowerVolume &v = *dynamic_cast<GLWipeTowerVolume *>(volumes.back());
auto mesh = wt_mesh;
if (render_brim) {
mesh.merge(brim_mesh);
}
if (!colors.empty()) {
v.iva_per_colors.resize(1);
v.iva_per_colors[0].load_mesh(mesh);
v.iva_per_colors[0].finalize_geometry(opengl_initialized);
}
TriangleMesh wipe_tower_shell = mesh.convex_hull_3d();
v.indexed_vertex_array->load_mesh(wipe_tower_shell);
v.indexed_vertex_array->finalize_geometry(opengl_initialized);
v.set_convex_hull(wipe_tower_shell);
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0);
v.geometry_id.first = 0;
v.geometry_id.second = wipe_tower_instance_id().id + (obj_idx - 1000);
v.is_wipe_tower = true;
v.shader_outside_printer_detection_enabled = !size_unknown;
return int(volumes.size() - 1);
}
GLVolume* GLVolumeCollection::new_toolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats)
{
GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats);
@@ -1552,19 +1620,22 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
}
//QDS: add outline drawing logic
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pipeline_stage,
GLVolumeCollection::ERenderType type,
bool disable_cullface,
const Transform3d & view_matrix,
const Transform3d& projection_matrix,
std::function<bool(const GLVolume &)> filter_func,
bool with_outline,
const std::array<float, 4> & body_color,
bool partly_inside_enable) const
const std::array<float, 4> & body_color,
bool partly_inside_enable,
std::vector<double> * printable_heights) const
{
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
if (to_render.empty())
return;
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
const auto shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr)
return;
@@ -1574,13 +1645,17 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
}
glsafe(::glCullFace(GL_BACK));
if (disable_cullface)
if (disable_cullface) {
glsafe(::glDisable(GL_CULL_FACE));
}
else {
glsafe(::glEnable(GL_CULL_FACE));
}
auto camera = GUI::wxGetApp().plater()->get_camera();
for (GLVolumeWithIdAndZ& volume : to_render) {
auto world_box = volume.first->transformed_bounding_box();
if (!camera.getFrustum().intersects(world_box, camera.get_type_as_string() == "perspective")) {
if (!camera.getFrustum().intersects(world_box)) {
continue;
}
#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
@@ -1598,62 +1673,90 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
// render sinking contours of non-hovered volumes
if (m_show_sinking_contours)
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) {
shader->stop_using();
volume.first->render_sinking_contours();
shader->start_using();
if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) {
if (m_show_sinking_contours)
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) {
GUI::wxGetApp().unbind_shader();
volume.first->render_sinking_contours();
GUI::wxGetApp().bind_shader(shader);
}
}
if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) {
shader->set_uniform("is_text_shape", volume.first->is_text_shape);
shader->set_uniform("uniform_color", volume.first->render_color);
shader->set_uniform("z_range", m_z_range, 2);
shader->set_uniform("clipping_plane", m_clipping_plane, 4);
//BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%")
// %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3]
// %with_outline%volume.first->selected;
//QDS set print_volume to render volume
//shader->set_uniform("print_volume.type", static_cast<int>(m_render_volume.type));
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
if (printable_heights) {
std::array<float, 3> extruder_printable_heights;
if ((*printable_heights).size() > 0) {
extruder_printable_heights[0] = 2.0f;
extruder_printable_heights[1] = (*printable_heights)[0];
extruder_printable_heights[2] = (*printable_heights)[1];
shader->set_uniform("extruder_printable_heights", extruder_printable_heights);
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
}
else {
extruder_printable_heights[0] = 0.0f;
shader->set_uniform("extruder_printable_heights", extruder_printable_heights);
}
}
if (volume.first->partly_inside && partly_inside_enable) {
//only partly inside volume need to be painted with boundary check
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
shader->set_uniform("print_volume.z_data", m_print_volume.zs);
if (!printable_heights || (printable_heights && (*printable_heights).size() == 0)) {
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
}
}
else {
//use -1 ad a invalid type
shader->set_uniform("print_volume.type", -1);
}
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
bool enable_support;
int support_threshold_angle = get_selection_support_threshold_angle(enable_support);
shader->set_uniform("is_text_shape", volume.first->is_text_shape);
shader->set_uniform("uniform_color", volume.first->render_color);
shader->set_uniform("z_range", m_z_range, 2);
shader->set_uniform("clipping_plane", m_clipping_plane, 4);
//BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%")
// %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3]
// %with_outline%volume.first->selected;
float normal_z = -::cos(Geometry::deg2rad((float)support_threshold_angle));
//QDS set print_volume to render volume
//shader->set_uniform("print_volume.type", static_cast<int>(m_render_volume.type));
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
if (volume.first->partly_inside && partly_inside_enable) {
//only partly inside volume need to be painted with boundary check
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
shader->set_uniform("print_volume.z_data", m_print_volume.zs);
}
else {
//use -1 ad a invalid type
shader->set_uniform("print_volume.type", -1);
}
bool enable_support;
int support_threshold_angle = get_selection_support_threshold_angle(enable_support);
float normal_z = -::cos(Geometry::deg2rad((float) support_threshold_angle));
shader->set_uniform("volume_world_matrix", volume.first->world_matrix());
shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower);
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
shader->set_uniform("slope.normal_z", normal_z);
shader->set_uniform("volume_world_matrix", volume.first->world_matrix());
shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower);
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
shader->set_uniform("slope.normal_z", normal_z);
#if ENABLE_ENVIRONMENT_MAP
unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id();
bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1";
shader->set_uniform("use_environment_tex", use_environment_texture);
if (use_environment_texture)
glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id));
unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id();
bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1";
shader->set_uniform("use_environment_tex", use_environment_texture);
if (use_environment_texture)
glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id));
#endif // ENABLE_ENVIRONMENT_MAP
glcheck();
glcheck();
//QDS: add outline related logic
volume.first->render(with_outline && volume.first->selected, body_color);
const Transform3d matrix = view_matrix * volume.first->world_matrix();
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
//QDS: add outline related logic
auto red_color = std::array<float, 4>({ 1.0f, 0.0f, 0.0f, 1.0f });//slice_error
volume.first->render(view_matrix, with_outline&& volume.first->selected, volume.first->slice_error ? red_color : body_color);
}
else {
if (volume.first->selected) {
shader->set_uniform("u_model_matrix", volume.first->world_matrix());
volume.first->render(view_matrix, false, body_color);
}
}
#if ENABLE_ENVIRONMENT_MAP
if (use_environment_texture)
@@ -1662,21 +1765,20 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
}
if (m_show_sinking_contours) {
for (GLVolumeWithIdAndZ& volume : to_render) {
// render sinking contours of hovered/displaced volumes
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
(volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) {
shader->stop_using();
glsafe(::glDepthFunc(GL_ALWAYS));
volume.first->render_sinking_contours();
glsafe(::glDepthFunc(GL_LESS));
shader->start_using();
if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) {
if (m_show_sinking_contours) {
for (GLVolumeWithIdAndZ& volume : to_render) {
// render sinking contours of hovered/displaced volumes
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
(volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) {
GUI::wxGetApp().unbind_shader();
glsafe(::glDepthFunc(GL_ALWAYS));
volume.first->render_sinking_contours();
glsafe(::glDepthFunc(GL_LESS));
GUI::wxGetApp().bind_shader(shader);
}
}
}
}
@@ -1688,7 +1790,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
glsafe(::glDisable(GL_BLEND));
}
bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const
bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults* object_results) const
{
if (GUI::wxGetApp().plater() == NULL)
{
@@ -1710,19 +1812,25 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
auto volume_convex_mesh = [volume_sinking, &model](GLVolume& volume) -> const TriangleMesh&
{ return volume_sinking(volume) ? model.objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); };
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Fully_Outside;
bool contained_min_one = false;
//QDS: add instance judge logic, besides to original volume judge logic
std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
//std::map<int64_t, ModelInstanceEPrintVolumeState> model_state;
GUI::PartPlate* curr_plate = GUI::wxGetApp().plater()->get_partplate_list().get_selected_plate();
const Pointfs& pp_bed_shape = curr_plate->get_shape();
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height());
BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height(), build_volume.extruder_areas(), build_volume.extruder_heights());
const std::vector<BoundingBoxf3>& exclude_areas = curr_plate->get_exclude_areas();
std::map<ModelObject*, std::map<int, std::set<int>>> objects_unprintable_filaments;
int extruder_count = build_volume.get_extruder_area_count();
std::vector<std::set<int>> unprintable_filament_ids(extruder_count, std::set<int>());
std::set<ModelObject*> partly_objects_set;
const ModelObjectPtrs &model_objects = model.objects;
for (GLVolume* volume : this->volumes)
{
std::vector<bool> inside_extruders;
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
BuildVolume::ObjectState state;
const BoundingBoxf3& bb = volume_bbox(*volume);
@@ -1733,37 +1841,76 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
case BuildVolume::Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
state = plate_build_volume.volume_state_bbox(bb);
if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1))
{
state = plate_build_volume.check_volume_bbox_state_with_extruder_areas(bb, inside_extruders);
}
break;
case BuildVolume::Type::Circle:
case BuildVolume::Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case BuildVolume::Type::Custom:
state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
{
const indexed_triangle_set& convex_mesh_it = volume_convex_mesh(*volume).its;
const Transform3f trafo = volume->world_matrix().cast<float>();
state = plate_build_volume.object_state(convex_mesh_it, trafo, volume_sinking(*volume));
if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1))
{
state = plate_build_volume.check_object_state_with_extruder_areas(convex_mesh_it, trafo, inside_extruders);
}
break;
}
default:
// Ignore, don't produce any collision.
state = BuildVolume::ObjectState::Inside;
break;
}
assert(state != BuildVolume::ObjectState::Below);
if (state == BuildVolume::ObjectState::Limited) {
//unprintable_filament_ids.resize(inside_extruders.size());
ModelObject *model_object = model_objects[volume->object_idx()];
// Only check for single-color object
std::set<int> object_filaments;
for (ModelVolume *m_volume : model_object->volumes) {
std::vector<int> filaments = m_volume->get_extruders();
object_filaments.insert(filaments.begin(), filaments.end());
}
if (object_filaments.size() == 1) {
ModelVolume *model_volume = model_object->volumes[volume->volume_idx()];
for (size_t i = 0; i < inside_extruders.size(); ++i) {
if (!inside_extruders[i]) {
std::vector<int> filaments = model_volume->get_extruders();
unprintable_filament_ids[i].insert(filaments.begin(), filaments.end());
if (object_results) {
std::map<int, std::set<int>> &obj_extruder_filament_maps = objects_unprintable_filaments[model_object];
std::set<int> &obj_extruder_filaments = obj_extruder_filament_maps[i + 1];
obj_extruder_filaments.insert(filaments.begin(), filaments.end());
}
}
}
}
}
}
int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
volume->is_outside = state != BuildVolume::ObjectState::Inside;
//volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
//int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id);
volume->is_outside = (state != BuildVolume::ObjectState::Inside && state != BuildVolume::ObjectState::Limited);
volume->partly_inside = (state == BuildVolume::ObjectState::Colliding);
if (volume->printable) {
if (overall_state == ModelInstancePVS_Inside && volume->is_outside) {
overall_state = ModelInstancePVS_Fully_Outside;
}
if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
if (state == BuildVolume::ObjectState::Colliding)
{
overall_state = ModelInstancePVS_Partly_Outside;
partly_objects_set.emplace(model_objects[volume->object_idx()]);
}
else if ((state == BuildVolume::ObjectState::Limited) && (overall_state != ModelInstancePVS_Partly_Outside))
overall_state = ModelInstancePVS_Limited;
else if ((state == BuildVolume::ObjectState::Inside) && (overall_state == ModelInstancePVS_Fully_Outside)) {
overall_state = ModelInstancePVS_Fully_Outside;
}
contained_min_one |= !volume->is_outside;
}
ModelInstanceEPrintVolumeState volume_state;
/*ModelInstanceEPrintVolumeState volume_state;
//if (volume->is_outside && (plate_build_volume.bounding_volume().intersects(volume->bounding_box())))
if (volume->is_outside && (state == BuildVolume::ObjectState::Colliding))
volume_state = ModelInstancePVS_Partly_Outside;
@@ -1792,11 +1939,121 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
if (model_state[comp_id] == ModelInstancePVS_Partly_Outside) {
overall_state = ModelInstancePVS_Partly_Outside;
BOOST_LOG_TRIVIAL(debug) << "instance includes " << volume->name << " is partially outside of bed";
}*/
}
}
std::vector<std::vector<int>> unprintable_filament_vec;
for (const std::set<int>& filamnt_ids : unprintable_filament_ids) {
unprintable_filament_vec.emplace_back(std::vector<int>(filamnt_ids.begin(), filamnt_ids.end()));
}
if (object_results && !partly_objects_set.empty()) {
object_results->partly_outside_objects = std::vector<ModelObject*>(partly_objects_set.begin(), partly_objects_set.end());
}
//check per-object error for extruder areas
if (object_results && (extruder_count > 1))
{
const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config;
object_results->mode = curr_plate->get_real_filament_map_mode(project_config);
if (object_results->mode < FilamentMapMode::fmmManual)
{
std::vector<int> conflict_filament_vector;
for (int index = 0; index < extruder_count; index++ )
{
if (!unprintable_filament_vec[index].empty())
{
std::sort (unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end());
if (index == 0)
conflict_filament_vector = unprintable_filament_vec[index];
else
{
std::vector<int> result_filaments;
//result_filaments.reserve(conflict_filaments.size());
std::set_intersection (conflict_filament_vector.begin(), conflict_filament_vector.end(), unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end(), insert_iterator<vector<int>>(result_filaments, result_filaments.begin()));
conflict_filament_vector = result_filaments;
}
}
else
{
conflict_filament_vector.clear();
break;
}
}
if (!conflict_filament_vector.empty())
{
std::set<int> conflict_filaments_set(conflict_filament_vector.begin(), conflict_filament_vector.end());
object_results->filaments = conflict_filament_vector;
for (auto& object_map: objects_unprintable_filaments)
{
ModelObject *model_object = object_map.first;
std::map<int, std::set<int>>& obj_extruder_filament_maps = object_map.second;
std::set<int> obj_filaments_set;
ObjectFilamentInfo object_filament_info;
object_filament_info.object = model_object;
for (std::map<int, std::set<int>>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ )
{
int extruder_id = extruder_map_iter->first;
std::set<int>& filaments_set = extruder_map_iter->second;
for (int filament: filaments_set)
{
if (conflict_filaments_set.find(filament) != conflict_filaments_set.end())
{
obj_filaments_set.emplace(filament);
}
}
}
if (!obj_filaments_set.empty()) {
object_filament_info.auto_filaments = std::vector<int>(obj_filaments_set.begin(), obj_filaments_set.end());
object_results->object_filaments.push_back(std::move(object_filament_info));
}
}
}
}
else
{
std::set<int> conflict_filaments_set;
const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config;
std::vector<int> filament_maps = curr_plate->get_real_filament_maps(project_config);
for (auto& object_map: objects_unprintable_filaments)
{
ModelObject *model_object = object_map.first;
std::map<int, std::set<int>>& obj_extruder_filament_maps = object_map.second;
ObjectFilamentInfo object_filament_info;
object_filament_info.object = model_object;
for (std::map<int, std::set<int>>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ )
{
int extruder_id = extruder_map_iter->first;
std::set<int>& filaments_set = extruder_map_iter->second;
for (int filament: filaments_set)
{
if (filament_maps[filament - 1] == extruder_id)
{
object_filament_info.manual_filaments.emplace(filament, extruder_id);
object_results->filament_maps[filament] = extruder_id;
conflict_filaments_set.emplace(filament);
}
}
}
if (!object_filament_info.manual_filaments.empty())
{
object_results->object_filaments.push_back(std::move(object_filament_info));
}
}
if (!conflict_filaments_set.empty()) {
object_results->filaments = std::vector<int>(conflict_filaments_set.begin(), conflict_filaments_set.end());
}
}
}
for (GLVolume* volume : this->volumes)
/*for (GLVolume* volume : this->volumes)
{
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0)))
{
@@ -1810,7 +2067,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
volume->partly_inside = false;
}
}
}
}*/
if (out_state != nullptr)
*out_state = overall_state;