Let the User Choose What the Simplified Preview Leaves Out While Dragging

The reduced toolpath set was only ever bound during a camera drag. The slider
check read is_dirty(), which the slider raises inside its own render and
_render_gcode() consumes at the end of the same frame, so it was never true at
the start of the next one; the only time it was true was the frame after a
keyboard or wheel step, which then drew one coarse frame followed by one full
frame. The navigator cube and the mouse wheel never engaged it at all, and the
extra frame requested on every level change was a full-detail frame drawn for
nothing, since the level is chosen before the draw. The reduced buffers were
also built and uploaded on every slider tick with the preference off.

Dragging is now read from ImGui's active id for the sliders and from the
navigator's own flag, a wheel step holds the reduced set for a 150 ms settle
time with the restoring frame scheduled for when it runs out, and nothing is
built while the preference is off.

What the reduced set leaves out is now a choice: skip layers only, skip the
internal infill roles, or keep the shell only. The shell is found geometrically
at load, once per print: every layer is rasterized into a half-millimetre
occupancy grid and closed so that sparse infill reads as solid, a cell is on the
shell when any of its six neighbours is empty, and a segment is kept when at
least half of its cells are. Being geometric it works for the wipe tower, whose
every segment shares one role and which is the bulk of a tall print, where
dropping roles could not. The layer stride is a preference too, one layer in
every N with both ends of the visible range always whole.

On the 636-layer three-filament fixture, frames during a drag against 448467
segments drawn in 334 ms at full detail:

  skip layers only, 1 in 4        110691 segments   83 ms
  skip internal infill, 1 in 4     85661 segments   68 ms
  shell only, 1 in 4               54382 segments   52 ms
  skip internal infill, every layer 347208 segments  255 ms
  shell only, every layer          215797 segments  170 ms

The shell classification takes 63 ms once per load, split across threads. At
rest the preview is pixel identical to before in every configuration, and the
frame after a release or a settled wheel burst is the full one.
This commit is contained in:
Hanif Koh
2026-09-10 16:39:17 +08:00
parent 8fd5d77220
commit 77d00c0ee4
15 changed files with 539 additions and 55 deletions
+43 -7
View File
@@ -1172,8 +1172,13 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
if (current_top_layer_only != required_top_layer_only)
m_viewer.toggle_top_layer_only_view_range();
// ORCA: darken the layers the preview layer slider is not scrubbed to
// ORCA: simplify the preview while the user is dragging
m_reduced_detail_while_dragging = get_app_config()->get_bool("preview_reduced_detail_while_dragging");
m_reduced_detail_mode = reduced_detail_mode_from_string(get_app_config()->get("preview_reduced_detail_mode"));
m_reduced_detail_layer_stride = static_cast<unsigned int>(std::max(1, std::stoi(get_app_config()->get("preview_reduced_detail_layer_stride"))));
apply_reduced_detail_settings();
// ORCA: darken the layers the preview layer slider is not scrubbed to
m_viewer.set_dim_previous_layers(get_app_config()->get_bool("preview_dim_previous_layers"));
m_viewer.set_dim_previous_layers_brightness(0.01f * std::stoi(get_app_config()->get("preview_dim_previous_layers_brightness")));
@@ -1908,13 +1913,44 @@ void GCodeViewer::update_layers_slider_mode()
// TODO m_layers_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder);
}
bool GCodeViewer::set_interacting(bool interacting)
void GCodeViewer::set_interacting(bool interacting)
{
const bool reduced = m_reduced_detail_while_dragging && interacting;
if (reduced == m_viewer.is_reduced_detail())
return false;
m_viewer.set_reduced_detail(reduced);
return true;
m_viewer.set_reduced_detail(m_reduced_detail_while_dragging && interacting);
}
// ORCA: libvgcode only builds a reduced set while its mode is not Off, so the preference switch is
// folded into the mode it is given. Every setter goes through here.
void GCodeViewer::apply_reduced_detail_settings()
{
m_viewer.set_reduced_detail_mode(m_reduced_detail_while_dragging ? m_reduced_detail_mode : libvgcode::EReducedDetailMode::Off);
m_viewer.set_reduced_detail_layer_stride(m_reduced_detail_layer_stride);
}
void GCodeViewer::set_reduced_detail_while_dragging(bool value)
{
m_reduced_detail_while_dragging = value;
apply_reduced_detail_settings();
}
void GCodeViewer::set_reduced_detail_mode(const std::string& mode)
{
m_reduced_detail_mode = reduced_detail_mode_from_string(mode);
apply_reduced_detail_settings();
}
void GCodeViewer::set_reduced_detail_layer_stride(unsigned int value)
{
m_reduced_detail_layer_stride = std::max(1u, value);
apply_reduced_detail_settings();
}
libvgcode::EReducedDetailMode GCodeViewer::reduced_detail_mode_from_string(const std::string& mode)
{
if (mode == "layers")
return libvgcode::EReducedDetailMode::LayersOnly;
if (mode == "shell")
return libvgcode::EReducedDetailMode::ShellOnly;
return libvgcode::EReducedDetailMode::NoInternalInfill;
}
void GCodeViewer::set_layers_z_range(const std::array<unsigned int, 2>& layers_z_range)