mirror of
https://github.com/QIDITECH/QIDIStudio.git
synced 2026-02-07 20:31:49 +03:00
update slic3r
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "GLShader.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Colors.hpp"
|
||||
|
||||
#include "Plater.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/QuadricEdgeCollapse.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -415,6 +417,44 @@ std::array<std::array<float, 4>, 5> GLVolume::MODEL_COLOR = { {
|
||||
{ 1.0f, 1.0f, 0.0f, 1.f }
|
||||
} };
|
||||
|
||||
float GLVolume::LOD_HIGH_ZOOM = 3.5f;
|
||||
float GLVolume::LOD_MIDDLE_ZOOM = 2.8f;
|
||||
float GLVolume::LOD_SMALL_ZOOM = 1.4f;
|
||||
float GLVolume::LAST_CAMERA_ZOOM_VALUE = 0.0f;
|
||||
const float ZOOM_THRESHOLD = 0.3f;
|
||||
const unsigned char LOD_UPDATE_FREQUENCY = 20;
|
||||
const Vec2i LOD_SCREEN_MIN = Vec2i(45, 35);
|
||||
const Vec2i LOD_SCREEN_MAX = Vec2i(65, 55);
|
||||
|
||||
Vec2f calc_pt_in_screen(const Vec3d &pt, const Matrix4d &view_proj_mat, int window_width, int window_height)
|
||||
{
|
||||
auto tran = view_proj_mat;
|
||||
Vec4d temp_center(pt.x(), pt.y(), pt.z(), 1.0);
|
||||
Vec4d temp_ndc = tran * temp_center;
|
||||
Vec3d screen_box_center = Vec3d(temp_ndc.x(), temp_ndc.y(), temp_ndc.z()) / temp_ndc.w();
|
||||
|
||||
float x = 0.5f * (1 + screen_box_center(0)) * window_width;
|
||||
float y = 0.5f * (1 - screen_box_center(1)) * window_height;
|
||||
return Vec2f(x, y);
|
||||
}
|
||||
|
||||
LOD_LEVEL calc_volume_box_in_screen_bigger_than_threshold(const BoundingBoxf3 &v_box_in_world, const Matrix4d &view_proj_mat,
|
||||
int window_width, int window_height)
|
||||
{
|
||||
auto s_min = calc_pt_in_screen(v_box_in_world.min, view_proj_mat, window_width, window_height);
|
||||
auto s_max = calc_pt_in_screen(v_box_in_world.max, view_proj_mat, window_width, window_height);
|
||||
auto size_x = abs(s_max.x() - s_min.x());
|
||||
auto size_y = abs(s_max.y() - s_min.y());
|
||||
if (size_x >= LOD_SCREEN_MAX.x() || size_y >= LOD_SCREEN_MAX.y()) {
|
||||
return LOD_LEVEL::HIGH;
|
||||
}
|
||||
if (size_x <= LOD_SCREEN_MIN.x() && size_y <= LOD_SCREEN_MIN.y()) {
|
||||
return LOD_LEVEL::SMALL;
|
||||
} else {
|
||||
return LOD_LEVEL::MIDDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void GLVolume::update_render_colors()
|
||||
{
|
||||
GLVolume::DISABLED_COLOR = GLColor(RenderColor::colors[RenderCol_Model_Disable]);
|
||||
@@ -463,6 +503,8 @@ GLVolume::GLVolume(float r, float g, float b, float a, bool create_index_data)
|
||||
, force_sinking_contours(false)
|
||||
, tverts_range(0, size_t(-1))
|
||||
, qverts_range(0, size_t(-1))
|
||||
, tverts_range_lod(0, size_t(-1))
|
||||
, qverts_range_lod(0, size_t(-1))
|
||||
{
|
||||
color = { r, g, b, a };
|
||||
set_render_color(color);
|
||||
@@ -580,6 +622,93 @@ std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume)
|
||||
return color;
|
||||
}
|
||||
|
||||
bool GLVolume::simplify_mesh(const TriangleMesh &mesh, std::shared_ptr<GLIndexedVertexArray> va, LOD_LEVEL lod) const {
|
||||
return simplify_mesh(mesh.its,va,lod);
|
||||
}
|
||||
#define SUPER_LARGE_FACES 500000
|
||||
#define LARGE_FACES 100000
|
||||
bool GLVolume::simplify_mesh(const indexed_triangle_set &_its, std::shared_ptr<GLIndexedVertexArray> va, LOD_LEVEL lod) const
|
||||
{
|
||||
if (_its.indices.size() == 0 || _its.vertices.size() == 0) { return false; }
|
||||
auto its = std::make_unique<indexed_triangle_set>(_its);
|
||||
auto m_state = std::make_unique<State>();
|
||||
if (lod == LOD_LEVEL::MIDDLE) {
|
||||
m_state->config.max_error = 0.5f;
|
||||
if (_its.indices.size() > SUPER_LARGE_FACES) {
|
||||
m_state->config.max_error = 0.4f;
|
||||
} else if (_its.indices.size() > LARGE_FACES) {
|
||||
m_state->config.max_error = 0.3f;
|
||||
}
|
||||
}
|
||||
if (lod == LOD_LEVEL::SMALL) {
|
||||
m_state->config.max_error = 0.1f;
|
||||
if (_its.indices.size() > SUPER_LARGE_FACES) {
|
||||
m_state->config.max_error = 0.08f;
|
||||
} else if (_its.indices.size() > LARGE_FACES) {
|
||||
m_state->config.max_error = 0.05f;
|
||||
}
|
||||
}
|
||||
|
||||
//std::mutex m_state_mutex;
|
||||
std::thread m_worker = std::thread(
|
||||
[va,this](std::unique_ptr<indexed_triangle_set> its, std::unique_ptr<State> state) {
|
||||
// Checks that the UI thread did not request cancellation, throws if so.
|
||||
std::function<void(void)> throw_on_cancel = []() {
|
||||
};
|
||||
std::function<void(int)> statusfn = [&state](int percent) {
|
||||
state->progress = percent;
|
||||
};
|
||||
// Initialize.
|
||||
uint32_t triangle_count = 0;
|
||||
float max_error = std::numeric_limits<float>::max();
|
||||
{
|
||||
if (state->config.use_count)
|
||||
triangle_count = state->config.wanted_count;
|
||||
if (!state->config.use_count)
|
||||
max_error = state->config.max_error;
|
||||
state->progress = 0;
|
||||
state->result.reset();
|
||||
state->status = State::Status::running;
|
||||
}
|
||||
int init_face_count = its->indices.size();
|
||||
TriangleMesh origin_mesh(*its);
|
||||
try { // Start the actual calculation.
|
||||
its_quadric_edge_collapse(*its, triangle_count, &max_error, throw_on_cancel, statusfn);
|
||||
} catch (std::exception&) {
|
||||
state->status = State::idle;
|
||||
}
|
||||
if (state->status == State::Status::running) {
|
||||
// We were not cancelled, the result is valid.
|
||||
state->status = State::Status::idle;
|
||||
state->result = std::move(its);
|
||||
}
|
||||
if (state->result) {
|
||||
int end_face_count = (*state->result).indices.size();
|
||||
if (init_face_count < 200 || (init_face_count < 1000 && end_face_count < init_face_count * 0.5)) {
|
||||
return;
|
||||
}
|
||||
TriangleMesh mesh(*state->result);
|
||||
float eps = 1.0f;
|
||||
Vec3f origin_min = origin_mesh.stats().min - Vec3f(eps, eps, eps);
|
||||
Vec3f origin_max = origin_mesh.stats().max + Vec3f(eps, eps, eps);
|
||||
if (origin_min.x() < mesh.stats().min.x() && origin_min.y() < mesh.stats().min.y() && origin_min.z() < mesh.stats().min.z()&&
|
||||
origin_max.x() > mesh.stats().max.x() && origin_max.y() > mesh.stats().max.y() && origin_max.z() > mesh.stats().max.z()) {
|
||||
if (va && va.use_count() >= 2) {
|
||||
va->load_mesh(mesh);
|
||||
}
|
||||
}
|
||||
else {
|
||||
state->status = State::cancelling;
|
||||
}
|
||||
}
|
||||
},
|
||||
std::move(its),std::move(m_state));
|
||||
if (m_worker.joinable()) {
|
||||
m_worker.detach();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Transform3d GLVolume::world_matrix() const
|
||||
{
|
||||
Transform3d m = m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix();
|
||||
@@ -688,6 +817,12 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
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;
|
||||
@@ -704,6 +839,11 @@ 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();
|
||||
if (colors.size() == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
color_volume = true;
|
||||
if (mv->mmu_segmentation_facets.timestamp() != mmuseg_ts) {
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, current mmuseg_ts %3%, current color size %4%")
|
||||
@@ -713,10 +853,11 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_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++) {
|
||||
mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]);
|
||||
mmuseg_ivas[idx].finalize_geometry(true);
|
||||
if (its_per_color[idx].indices.size() > 0) {
|
||||
mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]);
|
||||
mmuseg_ivas[idx].finalize_geometry(true);
|
||||
}
|
||||
}
|
||||
|
||||
mmuseg_ts = mv->mmu_segmentation_facets.timestamp();
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, new mmuseg_ts %3%, new color size %4%")
|
||||
%this %this->name %mmuseg_ts %mmuseg_ivas.size();
|
||||
@@ -734,8 +875,8 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
}
|
||||
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)
|
||||
GLIndexedVertexArray* iva = &mmuseg_ivas[idx];
|
||||
if (iva->triangle_indices_size == 0 && iva->quad_indices_size == 0)
|
||||
continue;
|
||||
|
||||
if (shader) {
|
||||
@@ -745,6 +886,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
int extruder_id = mv->extruder_id();
|
||||
//shader->set_uniform("uniform_color", colors[extruder_id - 1]);
|
||||
//to make black not too hard too see
|
||||
if (extruder_id <= 0) { extruder_id = 1; }
|
||||
std::array<float, 4> new_color = adjust_color_for_rendering(colors[extruder_id - 1]);
|
||||
shader->set_uniform("uniform_color", new_color);
|
||||
}
|
||||
@@ -763,7 +905,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
}
|
||||
}
|
||||
}
|
||||
iva.render(this->tverts_range, this->qverts_range);
|
||||
iva->render(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
|
||||
@@ -773,7 +915,32 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
}
|
||||
else {
|
||||
glsafe(::glMultMatrixd(world_matrix().data()));
|
||||
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||
auto render_which = [this](std::shared_ptr<GLIndexedVertexArray> cur) {
|
||||
if (cur->vertices_and_normals_interleaved_VBO_id > 0) {
|
||||
cur->render(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);
|
||||
} else {
|
||||
indexed_vertex_array->render(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;
|
||||
LAST_CAMERA_ZOOM_VALUE = zoom;
|
||||
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);
|
||||
} else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle) {
|
||||
render_which(indexed_vertex_array_middle);
|
||||
} else {
|
||||
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -887,9 +1054,22 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||
glsafe(::glPushMatrix());
|
||||
|
||||
Transform3d matrix = world_matrix();
|
||||
Transform3d world_tran = matrix;
|
||||
matrix.scale(scale);
|
||||
glsafe(::glMultMatrixd(matrix.data()));
|
||||
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||
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;
|
||||
LAST_CAMERA_ZOOM_VALUE = zoom;
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
this->indexed_vertex_array->render(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);
|
||||
|
||||
@@ -957,6 +1137,7 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj
|
||||
if (shader) {
|
||||
if (idx == 0) {
|
||||
int extruder_id = model_volume->extruder_id();
|
||||
if (extruder_id <= 0) { extruder_id = 1; }
|
||||
//to make black not too hard too see
|
||||
std::array<float, 4> new_color = adjust_color_for_rendering(extruder_colors[extruder_id - 1]);
|
||||
if (ban_light) {
|
||||
@@ -998,6 +1179,14 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
void GLVolume::set_bounding_boxes_as_dirty()
|
||||
{
|
||||
m_lod_update_index = LOD_UPDATE_FREQUENCY;
|
||||
m_transformed_bounding_box.reset();
|
||||
m_transformed_convex_hull_bounding_box.reset();
|
||||
m_transformed_non_sinking_bounding_box.reset();
|
||||
}
|
||||
|
||||
bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); }
|
||||
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposPad); }
|
||||
|
||||
@@ -1067,12 +1256,13 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
bool opengl_initialized,
|
||||
bool lod_enabled)
|
||||
{
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
||||
for (int instance_idx : instance_idxs)
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized));
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized, false, lod_enabled));
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
@@ -1084,7 +1274,8 @@ int GLVolumeCollection::load_object_volume(
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized,
|
||||
bool in_assemble_view,
|
||||
bool use_loaded_id)
|
||||
bool use_loaded_id,
|
||||
bool lod_enabled)
|
||||
{
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
@@ -1112,6 +1303,8 @@ int GLVolumeCollection::load_object_volume(
|
||||
else {
|
||||
GLVolume* first_volume = *(volume_set.begin());
|
||||
new_volume->indexed_vertex_array = first_volume->indexed_vertex_array;
|
||||
new_volume->indexed_vertex_array_middle = first_volume->indexed_vertex_array_middle;
|
||||
new_volume->indexed_vertex_array_small = first_volume->indexed_vertex_array_small;
|
||||
need_create_mesh = false;
|
||||
}
|
||||
volume_set.emplace(new_volume);
|
||||
@@ -1127,6 +1320,21 @@ int GLVolumeCollection::load_object_volume(
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
v.indexed_vertex_array->load_mesh(mesh, true);
|
||||
#else
|
||||
if (lod_enabled) {
|
||||
if (v.indexed_vertex_array_middle == nullptr)
|
||||
{
|
||||
v.indexed_vertex_array_middle = std::make_shared<GLIndexedVertexArray>();
|
||||
}
|
||||
|
||||
v.simplify_mesh(mesh, v.indexed_vertex_array_middle, LOD_LEVEL::MIDDLE); // include finalize_geometry
|
||||
|
||||
if (v.indexed_vertex_array_small == nullptr)
|
||||
{
|
||||
v.indexed_vertex_array_small = std::make_shared<GLIndexedVertexArray>();
|
||||
}
|
||||
v.simplify_mesh(mesh, v.indexed_vertex_array_small, LOD_LEVEL::SMALL);
|
||||
}
|
||||
|
||||
v.indexed_vertex_array->load_mesh(mesh);
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
v.indexed_vertex_array->finalize_geometry(opengl_initialized);
|
||||
@@ -1369,7 +1577,12 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||
if (disable_cullface)
|
||||
glsafe(::glDisable(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")) {
|
||||
continue;
|
||||
}
|
||||
#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
|
||||
if (type == ERenderType::Transparent) {
|
||||
volume.first->force_transparent = true;
|
||||
|
||||
Reference in New Issue
Block a user