Added a cache so that painted areas do not have to be recalculated in every frame,

the painted areas are not rendered as painted when the volume is in hover state
This commit is contained in:
Lukas Matena 2024-06-04 15:12:41 +02:00
parent 93a47c971a
commit 46bb8e5ac6

View File

@ -751,7 +751,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
return;
GLShaderProgram* curr_shader = GUI::wxGetApp().get_current_shader();
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat");
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat");
#if SLIC3R_OPENGL_ES
GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("dashed_lines");
#else
@ -774,9 +774,34 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
if (disable_cullface)
glsafe(::glDisable(GL_CULL_FACE));
// This block is here to render the pained triangles. It is not very nice, but it works.
// There is a cache that holds the OpenGL models of the painted areas to render, one for
// each ModelVolume. The cache is invalidated based on changes in extruder_colors,
// default extruder idx and timestamp of the painted data. The data belonging to objects
// // which no longer exist are removed from the cache periodically.
const ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects;
const std::vector<ColorRGBA> extruders_colors = GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
const bool is_render_as_mmu_painted_enabled = !model_objects.empty() && !extruders_colors.empty();
struct MMPaintCachePerVolume {
size_t extruder_id;
std::unique_ptr<GUI::TriangleSelectorMmGui> triangle_selector_mm;
std::chrono::system_clock::time_point time_used;
uint64_t mm_timestamp;
};
struct MMPaintCache {
std::vector<ColorRGBA> extruders_colors;
std::map<ObjectID, MMPaintCachePerVolume> volume_data;
};
static MMPaintCache mm_paint_cache;
if (mm_paint_cache.extruders_colors != extruders_colors) {
mm_paint_cache.extruders_colors = extruders_colors;
mm_paint_cache.volume_data.clear();
}
auto time_now = std::chrono::system_clock::now();
for (GLVolumeWithIdAndZ& volume : to_render) {
if (!volume.first->is_active)
@ -788,8 +813,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
const int obj_idx = volume.first->object_idx();
const int vol_idx = volume.first->volume_idx();
const bool render_as_mmu_painted = is_render_as_mmu_painted_enabled && !volume.first->selected &&
!volume.first->is_outside && !volume.first->is_wipe_tower && obj_idx >= 0 && vol_idx >= 0 &&
!model_objects[obj_idx]->volumes[vol_idx]->mm_segmentation_facets.empty();
!volume.first->is_outside && volume.first->hover == GLVolume::HS_None && !volume.first->is_wipe_tower && obj_idx >= 0 && vol_idx >= 0 &&
!model_objects[obj_idx]->volumes[vol_idx]->mm_segmentation_facets.empty();
volume.first->set_render_color(true);
// render sinking contours of non-hovered volumes
@ -827,13 +852,30 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
const ModelVolume& model_volume = *model_objects[obj_idx]->volumes[vol_idx];
const size_t extruder_idx = ModelVolume::get_extruder_color_idx(model_volume, GUI::wxGetApp().extruders_edited_cnt());
GUI::TriangleSelectorMmGui ts(model_volume.mesh(), extruders_colors, extruders_colors[extruder_idx]);
ts.deserialize(model_volume.mm_segmentation_facets.get_data(), true);
ts.request_update_render_data();
ts.render(nullptr, world_matrix);
// This block retrieves the painted geometry from the cache or adds it to it.
ObjectID vol_id = model_volume.id();
auto it = mm_paint_cache.volume_data.find(vol_id);
GUI::TriangleSelectorMmGui* ts = nullptr;
uint64_t timestamp = model_volume.mm_segmentation_facets.timestamp();
if (it == mm_paint_cache.volume_data.end() || it->second.extruder_id != extruder_idx || timestamp != it->second.mm_timestamp) {
auto ts_uptr = std::make_unique<GUI::TriangleSelectorMmGui>(model_volume.mesh(), mm_paint_cache.extruders_colors, mm_paint_cache.extruders_colors[extruder_idx]);
ts = ts_uptr.get();
ts->deserialize(model_volume.mm_segmentation_facets.get_data(), true);
ts->request_update_render_data();
mm_paint_cache.volume_data[vol_id] = MMPaintCachePerVolume{ extruder_idx, std::move(ts_uptr), std::chrono::system_clock::now(), timestamp };
}
else {
ts = it->second.triangle_selector_mm.get();
it->second.time_used = time_now;
}
ts->render(nullptr, world_matrix);
if (is_left_handed)
glsafe(::glFrontFace(GL_CCW));
glsafe(::glFrontFace(GL_CCW));
shader->stop_using();
}
@ -879,6 +921,20 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
}
}
// Purge the painted triangles cache from everything that was not used for some time.
// Only do this occasionally (once a second).
using namespace std::chrono_literals;
static auto time_since_last_check = time_now;
if (time_now - time_since_last_check > 1000ms)
for (auto it = mm_paint_cache.volume_data.begin(); it != mm_paint_cache.volume_data.end(); ) {
auto it_delete = it; // The iterator to the deleted element will be invalidated, the others will not.
++it;
if (time_now - it_delete->second.time_used > 5000ms)
mm_paint_cache.volume_data.erase(it_delete);
}
if (m_show_sinking_contours) {
if (sink_shader != nullptr) {
sink_shader->start_using();