Simplify dialog,

remove fast reduction - create mistake
This commit is contained in:
Filip Sykala 2021-08-23 15:57:09 +02:00
parent 89819c1c22
commit b555910185
2 changed files with 58 additions and 68 deletions

View File

@ -111,63 +111,69 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
ImGui::Separator(); ImGui::Separator();
ImGui::Text(_L("Limit by triangles").c_str()); if(ImGui::RadioButton("##use_error", !m_configuration.use_count)) {
m_is_valid_result = false;
m_configuration.use_count = !m_configuration.use_count;
}
ImGui::SameLine();
m_imgui->disabled_begin(m_configuration.use_count);
ImGui::Text(_L("Detail level").c_str());
std::vector<std::string> reduce_captions = {
_u8L("Extra high"),
_u8L("High"),
_u8L("Medium"),
_u8L("Low"),
_u8L("Extra low")
};
ImGui::SameLine(m_gui_cfg->bottom_left_width); ImGui::SameLine(m_gui_cfg->bottom_left_width);
// First initialization + fix triangle count ImGui::SetNextItemWidth(m_gui_cfg->input_width);
if (m_imgui->checkbox("##UseCount", m_configuration.use_count)) { static int reduction = 3;
if (!m_configuration.use_count) m_configuration.use_error = true; if(ImGui::SliderInt("##ReductionLevel", &reduction, 1, 5, reduce_captions[reduction-1].c_str())) {
m_is_valid_result = false; m_is_valid_result = false;
if (reduction < 1) reduction = 1;
if (reduction > 5) reduction = 5;
switch (reduction) {
case 1: m_configuration.max_error = 1e-3f; break;
case 2: m_configuration.max_error = 1e-2f; break;
case 3: m_configuration.max_error = 0.1f; break;
case 4: m_configuration.max_error = 0.5f; break;
case 5: m_configuration.max_error = 1.f; break;
}
}
m_imgui->disabled_end(); // !use_count
if (ImGui::RadioButton("##use_count", m_configuration.use_count)) {
m_is_valid_result = false;
m_configuration.use_count = !m_configuration.use_count;
}
ImGui::SameLine();
// show preview result triangle count (percent)
if (m_need_reload && !m_configuration.use_count) {
m_configuration.wanted_count = static_cast<uint32_t>(m_volume->mesh().its.indices.size());
m_configuration.update_count(triangle_count);
} }
m_imgui->disabled_begin(!m_configuration.use_count); m_imgui->disabled_begin(!m_configuration.use_count);
ImGui::Text(_L("Triangle count").c_str()); ImGui::Text(_L("Ratio").c_str());
ImGui::SameLine(m_gui_cfg->bottom_left_width); ImGui::SameLine(m_gui_cfg->bottom_left_width);
int wanted_count = m_configuration.wanted_count; int wanted_count = m_configuration.wanted_count;
ImGui::SetNextItemWidth(m_gui_cfg->input_width); ImGui::SetNextItemWidth(m_gui_cfg->input_width);
if (ImGui::SliderInt("##triangle_count", &wanted_count, min_triangle_count, triangle_count, "%d")) { const char * format = (m_configuration.wanted_percent > 10)? "%.0f %%":
m_configuration.wanted_count = static_cast<uint32_t>(wanted_count); ((m_configuration.wanted_percent > 1)? "%.1f %%":"%.2f %%");
if (m_configuration.wanted_count < min_triangle_count) if (ImGui::SliderFloat("##triangle_ratio", &m_configuration.wanted_percent, 0.f, 100.f, format)) {
m_configuration.wanted_count = min_triangle_count;
if (m_configuration.wanted_count > triangle_count)
m_configuration.wanted_count = triangle_count;
m_configuration.update_count(triangle_count);
m_is_valid_result = false; m_is_valid_result = false;
} if (m_configuration.wanted_percent < 0.f)
ImGui::Text(_L("Ratio").c_str()); m_configuration.wanted_percent = 0.01;
ImGui::SameLine(m_gui_cfg->bottom_left_width); if (m_configuration.wanted_percent > 100.f)
ImGui::SetNextItemWidth(m_gui_cfg->input_small_width); m_configuration.wanted_percent = 100.f;
const char * precision = (m_configuration.wanted_percent > 10)? "%.0f":
((m_configuration.wanted_percent > 1)? "%.1f":"%.2f");
float step = (m_configuration.wanted_percent > 10)? 1.f:
((m_configuration.wanted_percent > 1)? 0.1f : 0.01f);
if (ImGui::InputFloat("%", &m_configuration.wanted_percent, step, 10*step, precision)) {
if (m_configuration.wanted_percent > 100.f) m_configuration.wanted_percent = 100.f;
m_configuration.update_percent(triangle_count); m_configuration.update_percent(triangle_count);
if (m_configuration.wanted_count < min_triangle_count) {
m_configuration.wanted_count = min_triangle_count;
m_configuration.update_count(triangle_count);
}
m_is_valid_result = false;
} }
m_imgui->disabled_end(); // use_count
ImGui::NewLine(); ImGui::NewLine();
ImGui::Text(_L("Limit by error").c_str());
ImGui::SameLine(m_gui_cfg->bottom_left_width); ImGui::SameLine(m_gui_cfg->bottom_left_width);
if (m_imgui->checkbox("##UseError", m_configuration.use_error)) { ImGui::Text(_L("%d triangles").c_str(), m_configuration.wanted_count);
if (!m_configuration.use_error) m_configuration.use_count = true; m_imgui->disabled_end(); // use_count
m_is_valid_result = false;
}
m_imgui->disabled_begin(!m_configuration.use_error);
ImGui::Text(_L("Max. error").c_str());
ImGui::SameLine(m_gui_cfg->bottom_left_width);
ImGui::SetNextItemWidth(m_gui_cfg->input_small_width);
if (ImGui::InputFloat("##maxError", &m_configuration.max_error, 0.01f, .1f, "%.2f")) {
if (m_configuration.max_error < 0.f) m_configuration.max_error = 0.f;
m_is_valid_result = false;
}
m_imgui->disabled_end(); // use_error
if (m_state == State::settings) { if (m_state == State::settings) {
if (m_imgui->button(_L("Cancel"))) { if (m_imgui->button(_L("Cancel"))) {
@ -256,8 +262,7 @@ void GLGizmoSimplify::process()
m_worker = std::thread([this]() { m_worker = std::thread([this]() {
// store original triangles // store original triangles
uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0; uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0;
float max_error = (m_configuration.use_error) ? float max_error = (!m_configuration.use_count) ? m_configuration.max_error : std::numeric_limits<float>::max();
m_configuration.max_error : std::numeric_limits<float>::max();
std::function<void(void)> throw_on_cancel = [&]() { std::function<void(void)> throw_on_cancel = [&]() {
if (m_state == State::canceling) { if (m_state == State::canceling) {
@ -272,26 +277,17 @@ void GLGizmoSimplify::process()
static int64_t last = 0; static int64_t last = 0;
int64_t now = m_parent.timestamp_now(); int64_t now = m_parent.timestamp_now();
if ((now - last) < 250) return; if ((now - last) < 250) return;
last = now;
request_rerender(); request_rerender();
}; };
indexed_triangle_set collapsed; indexed_triangle_set collapsed = *m_original_its; // copy
if (m_last_error.has_value() && m_last_count.has_value() &&
(!m_configuration.use_count || triangle_count <= *m_last_count) &&
(!m_configuration.use_error || m_configuration.max_error <= *m_last_error)) {
// continue from last reduction - speed up
collapsed = m_volume->mesh().its; // small copy
} else {
collapsed = *m_original_its; // copy
}
try { try {
its_quadric_edge_collapse(collapsed, triangle_count, &max_error, throw_on_cancel, statusfn); its_quadric_edge_collapse(collapsed, triangle_count, &max_error, throw_on_cancel, statusfn);
set_its(collapsed); set_its(collapsed);
m_is_valid_result = true; m_is_valid_result = true;
m_last_count = triangle_count; // need to store last requirement, collapsed count could be count-1
m_last_error = max_error;
} catch (SimplifyCanceledException &) { } catch (SimplifyCanceledException &) {
// set state out of main thread // set state out of main thread
m_state = State::settings; m_state = State::settings;
@ -348,20 +344,18 @@ void GLGizmoSimplify::on_set_state()
void GLGizmoSimplify::create_gui_cfg() { void GLGizmoSimplify::create_gui_cfg() {
if (m_gui_cfg.has_value()) return; if (m_gui_cfg.has_value()) return;
int space_size = m_imgui->calc_text_size(":MM").x; int space_size = m_imgui->calc_text_size(":MM").x;
GuiCfg cfg; GuiCfg cfg;
cfg.top_left_width = std::max(m_imgui->calc_text_size(_L("Mesh name")).x, cfg.top_left_width = std::max(m_imgui->calc_text_size(_L("Mesh name")).x,
m_imgui->calc_text_size(_L("Triangles")).x) m_imgui->calc_text_size(_L("Triangles")).x)
+ space_size; + space_size;
const float radio_size = ImGui::GetFrameHeight();
cfg.bottom_left_width = cfg.bottom_left_width =
std::max( std::max(m_imgui->calc_text_size(_L("Detail level")).x,
std::max(m_imgui->calc_text_size(_L("Limit by triangles")).x, m_imgui->calc_text_size(_L("Ratio")).x) +
std::max(m_imgui->calc_text_size(_L("Triangle count")).x, space_size + radio_size;
m_imgui->calc_text_size(_L("Ratio")).x)),
std::max(m_imgui->calc_text_size(_L("Limit by error")).x,
m_imgui->calc_text_size(_L("Max. error")).x)) + space_size;
cfg.input_width = cfg.bottom_left_width; cfg.input_width = cfg.bottom_left_width;
cfg.input_small_width = cfg.input_width * 0.8; cfg.input_small_width = cfg.input_width * 0.8;
cfg.window_offset = cfg.input_width; cfg.window_offset = cfg.input_width;

View File

@ -44,9 +44,6 @@ private:
std::optional<indexed_triangle_set> m_original_its; std::optional<indexed_triangle_set> m_original_its;
std::optional<float> m_last_error; // for use previous reduction
std::optional<uint32_t> m_last_count;
volatile bool m_need_reload; // after simplify, glReload must be on main thread volatile bool m_need_reload; // after simplify, glReload must be on main thread
std::thread m_worker; std::thread m_worker;
@ -60,12 +57,11 @@ private:
struct Configuration struct Configuration
{ {
bool use_count = true; bool use_count = false;
// minimal triangle count // minimal triangle count
float wanted_percent = 50.f; float wanted_percent = 50.f;
uint32_t wanted_count = 0; // initialize by percents uint32_t wanted_count = 0; // initialize by percents
bool use_error = false;
// maximal quadric error // maximal quadric error
float max_error = 1.; float max_error = 1.;