Add simulated color preview support for top-surface coloring. Make preview settings apply to every texture mapping zone
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
||||
const float UV_EDGE_EPSILON = 0.000001;
|
||||
const float INVALID_TEXTURE_CHECKER_SCALE = 0.2;
|
||||
const float CONTONING_FLAT_SURFACE_NORMAL_Z = 0.999;
|
||||
|
||||
struct PrintVolumeDetection
|
||||
{
|
||||
@@ -13,8 +14,11 @@ struct PrintVolumeDetection
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
uniform sampler2D uniform_texture;
|
||||
uniform sampler2D contoning_flat_surface_texture;
|
||||
uniform float texture_preview_mix;
|
||||
uniform bool invalid_texture_mapping;
|
||||
uniform bool contoning_flat_surface_texture_enabled;
|
||||
uniform bool contoning_flat_surface_include_bottom;
|
||||
uniform bool color_match_preview_active;
|
||||
uniform vec3 color_match_target_oklab;
|
||||
uniform float color_match_tolerance_sq;
|
||||
@@ -78,6 +82,12 @@ void main()
|
||||
|
||||
vec4 color = uniform_color;
|
||||
vec4 texture_color = texture2D(uniform_texture, texture_preview_coord(tex_coord));
|
||||
if (contoning_flat_surface_texture_enabled) {
|
||||
float normal_z = normalize(world_normal).z;
|
||||
if (normal_z >= CONTONING_FLAT_SURFACE_NORMAL_Z ||
|
||||
(contoning_flat_surface_include_bottom && normal_z <= -CONTONING_FLAT_SURFACE_NORMAL_Z))
|
||||
texture_color = texture2D(contoning_flat_surface_texture, texture_preview_coord(tex_coord));
|
||||
}
|
||||
float mix_factor = clamp(texture_preview_mix, 0.0, 1.0);
|
||||
if (color_match_preview_active) {
|
||||
float source_alpha = clamp(texture_color.a, 0.0, 1.0);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
||||
const float UV_EDGE_EPSILON = 0.000001;
|
||||
const float INVALID_TEXTURE_CHECKER_SCALE = 0.2;
|
||||
const float CONTONING_FLAT_SURFACE_NORMAL_Z = 0.999;
|
||||
|
||||
struct PrintVolumeDetection
|
||||
{
|
||||
@@ -13,8 +14,11 @@ struct PrintVolumeDetection
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
uniform sampler2D uniform_texture;
|
||||
uniform sampler2D contoning_flat_surface_texture;
|
||||
uniform float texture_preview_mix;
|
||||
uniform bool invalid_texture_mapping;
|
||||
uniform bool contoning_flat_surface_texture_enabled;
|
||||
uniform bool contoning_flat_surface_include_bottom;
|
||||
uniform bool color_match_preview_active;
|
||||
uniform vec3 color_match_target_oklab;
|
||||
uniform float color_match_tolerance_sq;
|
||||
@@ -80,6 +84,12 @@ void main()
|
||||
|
||||
vec4 color = uniform_color;
|
||||
vec4 texture_color = texture(uniform_texture, texture_preview_coord(tex_coord));
|
||||
if (contoning_flat_surface_texture_enabled) {
|
||||
float normal_z = normalize(world_normal).z;
|
||||
if (normal_z >= CONTONING_FLAT_SURFACE_NORMAL_Z ||
|
||||
(contoning_flat_surface_include_bottom && normal_z <= -CONTONING_FLAT_SURFACE_NORMAL_Z))
|
||||
texture_color = texture(contoning_flat_surface_texture, texture_preview_coord(tex_coord));
|
||||
}
|
||||
float mix_factor = clamp(texture_preview_mix, 0.0, 1.0);
|
||||
if (color_match_preview_active) {
|
||||
float source_alpha = clamp(texture_color.a, 0.0, 1.0);
|
||||
|
||||
@@ -3760,6 +3760,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
||||
this->project_config.apply_only(config, s_project_options);
|
||||
if (const auto *color_opt = this->project_config.option<ConfigOptionStrings>("filament_colour", false); color_opt != nullptr)
|
||||
this->texture_mapping_zones.load_entries(this->project_config.opt_string("texture_mapping_definitions"), color_opt->values);
|
||||
this->texture_mapping_global_settings.load(this->project_config.opt_string("texture_mapping_global_settings"));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -262,6 +262,7 @@ static void remove_texture_mapping_preview_options(nlohmann::json &root)
|
||||
texture_it->erase("preview_opacity_pct");
|
||||
texture_it->erase("simulate_preview_colors");
|
||||
texture_it->erase("limit_preview_resolution");
|
||||
texture_it->erase("simulate_top_surface_lod");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,16 +287,67 @@ static bool texture_mapping_definitions_equal_for_gcode(const ConfigOption *lhs,
|
||||
return lhs_json == rhs_json;
|
||||
}
|
||||
|
||||
static bool texture_mapping_global_settings_json_for_gcode(const ConfigOption *opt, nlohmann::json &out)
|
||||
{
|
||||
out = nlohmann::json::object();
|
||||
if (opt == nullptr)
|
||||
return true;
|
||||
if (opt->type() != coString)
|
||||
return false;
|
||||
const std::string &value = static_cast<const ConfigOptionString *>(opt)->value;
|
||||
if (value.empty())
|
||||
return true;
|
||||
try {
|
||||
out = nlohmann::json::parse(value);
|
||||
} catch (const nlohmann::json::exception &) {
|
||||
return false;
|
||||
}
|
||||
if (!out.is_object())
|
||||
return false;
|
||||
out.erase("schema");
|
||||
auto preview_it = out.find("preview_options");
|
||||
if (preview_it != out.end()) {
|
||||
if (preview_it->is_object()) {
|
||||
preview_it->erase("preview_opacity_pct");
|
||||
preview_it->erase("simulate_preview_colors");
|
||||
preview_it->erase("limit_preview_resolution");
|
||||
preview_it->erase("simulate_top_surface_lod");
|
||||
if (preview_it->empty())
|
||||
out.erase(preview_it);
|
||||
}
|
||||
}
|
||||
out.erase("preview_opacity_pct");
|
||||
out.erase("simulate_preview_colors");
|
||||
out.erase("limit_preview_resolution");
|
||||
out.erase("simulate_top_surface_lod");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool texture_mapping_global_settings_equal_for_gcode(const ConfigOption *lhs, const ConfigOption *rhs)
|
||||
{
|
||||
if (config_options_equal(lhs, rhs))
|
||||
return true;
|
||||
nlohmann::json lhs_json;
|
||||
nlohmann::json rhs_json;
|
||||
return texture_mapping_global_settings_json_for_gcode(lhs, lhs_json) &&
|
||||
texture_mapping_global_settings_json_for_gcode(rhs, rhs_json) &&
|
||||
lhs_json == rhs_json;
|
||||
}
|
||||
|
||||
static void remove_texture_mapping_preview_only_diff(t_config_option_keys &diff,
|
||||
const ConfigBase ¤t_config,
|
||||
const DynamicPrintConfig &new_full_config)
|
||||
{
|
||||
auto it = std::find(diff.begin(), diff.end(), "texture_mapping_definitions");
|
||||
if (it == diff.end())
|
||||
return;
|
||||
if (texture_mapping_definitions_equal_for_gcode(current_config.option("texture_mapping_definitions"),
|
||||
if (it != diff.end() &&
|
||||
texture_mapping_definitions_equal_for_gcode(current_config.option("texture_mapping_definitions"),
|
||||
new_full_config.option("texture_mapping_definitions")))
|
||||
diff.erase(it);
|
||||
it = std::find(diff.begin(), diff.end(), "texture_mapping_global_settings");
|
||||
if (it != diff.end() &&
|
||||
texture_mapping_global_settings_equal_for_gcode(current_config.option("texture_mapping_global_settings"),
|
||||
new_full_config.option("texture_mapping_global_settings")))
|
||||
diff.erase(it);
|
||||
}
|
||||
|
||||
// Collect changes to print config, account for overrides of extruder retract values by filament presets.
|
||||
@@ -325,6 +377,8 @@ static t_config_option_keys print_config_diffs(
|
||||
} else if (*opt_new != *opt_old) {
|
||||
if (opt_key == "texture_mapping_definitions" && texture_mapping_definitions_equal_for_gcode(opt_old, opt_new))
|
||||
continue;
|
||||
if (opt_key == "texture_mapping_global_settings" && texture_mapping_global_settings_equal_for_gcode(opt_old, opt_new))
|
||||
continue;
|
||||
//BBS: add plate_index logic for wipe_tower_x/wipe_tower_y
|
||||
if (!opt_key.compare("wipe_tower_x") || !opt_key.compare("wipe_tower_y")) {
|
||||
const ConfigOptionFloats* option_new = dynamic_cast<const ConfigOptionFloats*>(opt_new);
|
||||
@@ -358,6 +412,8 @@ static t_config_option_keys full_print_config_diffs(const DynamicPrintConfig &cu
|
||||
if (opt_old == nullptr || *opt_new != *opt_old) {
|
||||
if (opt_key == "texture_mapping_definitions" && texture_mapping_definitions_equal_for_gcode(opt_old, opt_new))
|
||||
continue;
|
||||
if (opt_key == "texture_mapping_global_settings" && texture_mapping_global_settings_equal_for_gcode(opt_old, opt_new))
|
||||
continue;
|
||||
//BBS: add plate_index logic for wipe_tower_x/wipe_tower_y
|
||||
if (opt_old && (!opt_key.compare("wipe_tower_x") || !opt_key.compare("wipe_tower_y"))) {
|
||||
const ConfigOptionFloats* option_new = dynamic_cast<const ConfigOptionFloats*>(opt_new);
|
||||
|
||||
@@ -916,7 +916,8 @@ static std::string normalized_prime_tower_color_mode_name(std::string name)
|
||||
std::string TextureMappingGlobalSettings::serialize() const
|
||||
{
|
||||
const std::string normalized_mode = normalize_color_mode_name(prime_tower_color_mode);
|
||||
if (!enabled &&
|
||||
const bool prime_tower_defaults =
|
||||
!enabled &&
|
||||
std::abs((std::isfinite(angle_offset_deg) ? angle_offset_deg : 0.f)) <= 1e-6f &&
|
||||
!preserve_aspect_ratio &&
|
||||
normalized_mode == "auto" &&
|
||||
@@ -928,26 +929,44 @@ std::string TextureMappingGlobalSettings::serialize() const
|
||||
image_file_back.empty() &&
|
||||
image_name_back.empty() &&
|
||||
image_width_back == 0 &&
|
||||
image_height_back == 0)
|
||||
image_height_back == 0;
|
||||
const bool preview_defaults =
|
||||
std::abs((std::isfinite(preview_opacity_pct) ? preview_opacity_pct : TextureMappingZone::DefaultPreviewOpacityPct) -
|
||||
TextureMappingZone::DefaultPreviewOpacityPct) <= 1e-6f &&
|
||||
preview_simulate_colors == TextureMappingZone::DefaultPreviewSimulateColors &&
|
||||
preview_limit_resolution == TextureMappingZone::DefaultPreviewLimitResolution &&
|
||||
preview_simulate_top_surface_lod == TextureMappingZone::DefaultPreviewSimulateTopSurfaceLod;
|
||||
if (prime_tower_defaults && preview_defaults)
|
||||
return {};
|
||||
|
||||
nlohmann::json root;
|
||||
root["schema"] = 1;
|
||||
nlohmann::json prime_tower_texture_mapping;
|
||||
prime_tower_texture_mapping["enabled"] = enabled;
|
||||
prime_tower_texture_mapping["angle_offset_deg"] = std::clamp(std::isfinite(angle_offset_deg) ? angle_offset_deg : 0.f, 0.f, 360.f);
|
||||
prime_tower_texture_mapping["preserve_aspect_ratio"] = preserve_aspect_ratio;
|
||||
prime_tower_texture_mapping["prime_tower_color_mode"] = normalized_mode;
|
||||
prime_tower_texture_mapping["settings_zone_uid"] = prime_tower_settings_zone_uid;
|
||||
prime_tower_texture_mapping["image_file"] = image_file;
|
||||
prime_tower_texture_mapping["image_name"] = image_name;
|
||||
prime_tower_texture_mapping["image_width"] = image_width;
|
||||
prime_tower_texture_mapping["image_height"] = image_height;
|
||||
prime_tower_texture_mapping["image_file_back"] = image_file_back;
|
||||
prime_tower_texture_mapping["image_name_back"] = image_name_back;
|
||||
prime_tower_texture_mapping["image_width_back"] = image_width_back;
|
||||
prime_tower_texture_mapping["image_height_back"] = image_height_back;
|
||||
root["prime_tower_texture_mapping"] = std::move(prime_tower_texture_mapping);
|
||||
if (!preview_defaults || !prime_tower_defaults) {
|
||||
nlohmann::json preview_options;
|
||||
preview_options["preview_opacity_pct"] =
|
||||
std::clamp(std::isfinite(preview_opacity_pct) ? preview_opacity_pct : TextureMappingZone::DefaultPreviewOpacityPct, 0.f, 100.f);
|
||||
preview_options["simulate_preview_colors"] = preview_simulate_colors;
|
||||
preview_options["limit_preview_resolution"] = preview_limit_resolution;
|
||||
preview_options["simulate_top_surface_lod"] = preview_simulate_top_surface_lod;
|
||||
root["preview_options"] = std::move(preview_options);
|
||||
}
|
||||
if (!prime_tower_defaults) {
|
||||
nlohmann::json prime_tower_texture_mapping;
|
||||
prime_tower_texture_mapping["enabled"] = enabled;
|
||||
prime_tower_texture_mapping["angle_offset_deg"] = std::clamp(std::isfinite(angle_offset_deg) ? angle_offset_deg : 0.f, 0.f, 360.f);
|
||||
prime_tower_texture_mapping["preserve_aspect_ratio"] = preserve_aspect_ratio;
|
||||
prime_tower_texture_mapping["prime_tower_color_mode"] = normalized_mode;
|
||||
prime_tower_texture_mapping["settings_zone_uid"] = prime_tower_settings_zone_uid;
|
||||
prime_tower_texture_mapping["image_file"] = image_file;
|
||||
prime_tower_texture_mapping["image_name"] = image_name;
|
||||
prime_tower_texture_mapping["image_width"] = image_width;
|
||||
prime_tower_texture_mapping["image_height"] = image_height;
|
||||
prime_tower_texture_mapping["image_file_back"] = image_file_back;
|
||||
prime_tower_texture_mapping["image_name_back"] = image_name_back;
|
||||
prime_tower_texture_mapping["image_width_back"] = image_width_back;
|
||||
prime_tower_texture_mapping["image_height_back"] = image_height_back;
|
||||
root["prime_tower_texture_mapping"] = std::move(prime_tower_texture_mapping);
|
||||
}
|
||||
return root.dump();
|
||||
}
|
||||
|
||||
@@ -967,6 +986,25 @@ void TextureMappingGlobalSettings::load(const std::string &serialized)
|
||||
if (!root.is_object())
|
||||
return;
|
||||
|
||||
const auto preview_options_it = root.find("preview_options");
|
||||
if (preview_options_it != root.end() && preview_options_it->is_object()) {
|
||||
const auto opacity_it = preview_options_it->find("preview_opacity_pct");
|
||||
if (opacity_it != preview_options_it->end() && opacity_it->is_number())
|
||||
preview_opacity_pct = std::clamp(opacity_it->get<float>(), 0.f, 100.f);
|
||||
const auto simulate_it = preview_options_it->find("simulate_preview_colors");
|
||||
if (simulate_it != preview_options_it->end() && simulate_it->is_boolean())
|
||||
preview_simulate_colors = simulate_it->get<bool>();
|
||||
const auto limit_it = preview_options_it->find("limit_preview_resolution");
|
||||
if (limit_it != preview_options_it->end() && limit_it->is_boolean())
|
||||
preview_limit_resolution = limit_it->get<bool>();
|
||||
const auto top_surface_lod_it = preview_options_it->find("simulate_top_surface_lod");
|
||||
if (top_surface_lod_it != preview_options_it->end() && top_surface_lod_it->is_boolean())
|
||||
preview_simulate_top_surface_lod = top_surface_lod_it->get<bool>();
|
||||
}
|
||||
const auto root_simulate_it = root.find("simulate_preview_colors");
|
||||
if (root_simulate_it != root.end() && root_simulate_it->is_boolean())
|
||||
preview_simulate_colors = root_simulate_it->get<bool>();
|
||||
|
||||
const auto prime_tower_texture_mapping_it = root.find("prime_tower_texture_mapping");
|
||||
if (prime_tower_texture_mapping_it == root.end() || !prime_tower_texture_mapping_it->is_object())
|
||||
return;
|
||||
@@ -1122,9 +1160,6 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const
|
||||
high_resolution_sampling == rhs.high_resolution_sampling &&
|
||||
std::abs(tone_gamma - rhs.tone_gamma) <= eps &&
|
||||
transmission_distance_calibration_mode == rhs.transmission_distance_calibration_mode &&
|
||||
std::abs(preview_opacity_pct - rhs.preview_opacity_pct) <= eps &&
|
||||
preview_simulate_colors == rhs.preview_simulate_colors &&
|
||||
preview_limit_resolution == rhs.preview_limit_resolution &&
|
||||
auto_adjust_filament_selection == rhs.auto_adjust_filament_selection &&
|
||||
floats_equal(filament_strengths_pct, rhs.filament_strengths_pct) &&
|
||||
floats_equal(filament_minimum_offsets_pct, rhs.filament_minimum_offsets_pct) &&
|
||||
@@ -1527,10 +1562,6 @@ std::string TextureMappingManager::serialize_entries()
|
||||
texture["tone_gamma"] = normalize_tone_gamma(zone.tone_gamma);
|
||||
texture["transmission_distance_calibration"] =
|
||||
transmission_distance_calibration_mode_name(zone.transmission_distance_calibration_mode);
|
||||
texture["preview_opacity_pct"] =
|
||||
std::clamp(finite_or(zone.preview_opacity_pct, TextureMappingZone::DefaultPreviewOpacityPct), 0.f, 100.f);
|
||||
texture["simulate_preview_colors"] = zone.preview_simulate_colors;
|
||||
texture["limit_preview_resolution"] = zone.preview_limit_resolution;
|
||||
texture["auto_adjust_filaments"] = zone.auto_adjust_filament_selection;
|
||||
texture["strength_pct"] = floats_to_json(normalized_strengths);
|
||||
texture["minimum_offset_pct"] = floats_to_json(normalized_min_offsets);
|
||||
@@ -1832,10 +1863,6 @@ void TextureMappingManager::load_entries(const std::string &serialized,
|
||||
zone.high_resolution_sampling = true;
|
||||
zone.tone_gamma = normalize_tone_gamma(texture.value("tone_gamma", 1.f));
|
||||
zone.transmission_distance_calibration_mode = transmission_distance_calibration_mode_from_json(texture);
|
||||
zone.preview_opacity_pct =
|
||||
std::clamp(texture.value("preview_opacity_pct", TextureMappingZone::DefaultPreviewOpacityPct), 0.f, 100.f);
|
||||
zone.preview_simulate_colors = texture.value("simulate_preview_colors", TextureMappingZone::DefaultPreviewSimulateColors);
|
||||
zone.preview_limit_resolution = texture.value("limit_preview_resolution", true);
|
||||
zone.auto_adjust_filament_selection = texture.value("auto_adjust_filaments", true);
|
||||
zone.filament_strengths_pct = normalize_strengths(floats_from_json(texture.value("strength_pct", nlohmann::json::array())));
|
||||
zone.filament_minimum_offsets_pct =
|
||||
|
||||
@@ -219,6 +219,7 @@ struct TextureMappingZone
|
||||
static constexpr int DefaultTransmissionDistanceCalibrationMode = int(TDCalibrationAbsolute);
|
||||
static constexpr bool DefaultPreviewSimulateColors = false;
|
||||
static constexpr bool DefaultPreviewLimitResolution = true;
|
||||
static constexpr bool DefaultPreviewSimulateTopSurfaceLod = true;
|
||||
static constexpr bool DefaultAutoAdjustFilamentSelection = true;
|
||||
|
||||
static constexpr int default_modulation_mode_for_surface_pattern(int surface_pattern)
|
||||
@@ -329,9 +330,6 @@ struct TextureMappingZone
|
||||
bool high_resolution_sampling = DefaultHighResolutionSampling;
|
||||
float tone_gamma = DefaultToneGamma;
|
||||
int transmission_distance_calibration_mode = DefaultTransmissionDistanceCalibrationMode;
|
||||
float preview_opacity_pct = DefaultPreviewOpacityPct;
|
||||
bool preview_simulate_colors = DefaultPreviewSimulateColors;
|
||||
bool preview_limit_resolution = DefaultPreviewLimitResolution;
|
||||
bool auto_adjust_filament_selection = DefaultAutoAdjustFilamentSelection;
|
||||
std::vector<float> filament_strengths_pct;
|
||||
std::vector<float> filament_minimum_offsets_pct;
|
||||
@@ -454,9 +452,6 @@ struct TextureMappingZone
|
||||
high_resolution_sampling = DefaultHighResolutionSampling;
|
||||
tone_gamma = DefaultToneGamma;
|
||||
transmission_distance_calibration_mode = DefaultTransmissionDistanceCalibrationMode;
|
||||
preview_opacity_pct = DefaultPreviewOpacityPct;
|
||||
preview_simulate_colors = DefaultPreviewSimulateColors;
|
||||
preview_limit_resolution = DefaultPreviewLimitResolution;
|
||||
auto_adjust_filament_selection = DefaultAutoAdjustFilamentSelection;
|
||||
linear_gradient_mode = DefaultLinearGradientMode;
|
||||
linear_gradient_radius_mm = DefaultLinearGradientRadiusMm;
|
||||
@@ -519,6 +514,10 @@ struct TextureMappingGlobalSettings
|
||||
bool enabled = false;
|
||||
float angle_offset_deg = 0.f;
|
||||
bool preserve_aspect_ratio = false;
|
||||
float preview_opacity_pct = TextureMappingZone::DefaultPreviewOpacityPct;
|
||||
bool preview_simulate_colors = TextureMappingZone::DefaultPreviewSimulateColors;
|
||||
bool preview_limit_resolution = TextureMappingZone::DefaultPreviewLimitResolution;
|
||||
bool preview_simulate_top_surface_lod = TextureMappingZone::DefaultPreviewSimulateTopSurfaceLod;
|
||||
std::string prime_tower_color_mode = "auto";
|
||||
uint64_t prime_tower_settings_zone_uid = 0;
|
||||
std::string image_file;
|
||||
|
||||
@@ -44,6 +44,8 @@ constexpr size_t k_temporary_simulated_texture_preview_max_pixels = 1024ull * 10
|
||||
constexpr size_t k_temporary_simulated_texture_preview_min_source_pixels = k_temporary_simulated_texture_preview_max_pixels * 3 / 2;
|
||||
constexpr size_t k_surface_gradient_preview_max_components = 10;
|
||||
constexpr size_t k_surface_gradient_preview_lut_size = 33;
|
||||
constexpr size_t k_contoning_flat_surface_preview_max_candidates = 250000;
|
||||
constexpr double k_contoning_top_surface_preview_lod_max_samples = 350000.0;
|
||||
constexpr const char *TEXTURE_MAPPING_BACKGROUND_COLOR_CONFIG_KEY = "texture_mapping_background_color";
|
||||
|
||||
struct TexturePreviewMixCandidate
|
||||
@@ -86,6 +88,10 @@ struct TexturePreviewSimulationSettings
|
||||
int generic_solver_lookup_mode = int(TextureMappingZone::GenericSolverClosestMix);
|
||||
int generic_solver_mode = int(TextureMappingZone::GenericSolverV2);
|
||||
int generic_solver_mix_model = TextureMappingZone::DefaultGenericSolverMixModel;
|
||||
bool contoning_flat_surface_quantization = false;
|
||||
int contoning_flat_surface_pattern_filaments = TextureMappingZone::DefaultTopSurfaceContoningPatternFilaments;
|
||||
bool simulate_top_surface_lod = false;
|
||||
float top_surface_lod_pitch_mm = 0.f;
|
||||
float minimum_visibility_offset_factor = 0.f;
|
||||
std::vector<unsigned int> component_ids;
|
||||
std::vector<std::array<float, 3>> component_colors;
|
||||
@@ -257,7 +263,7 @@ std::array<Vec2f, 3> unwrap_triangle_uvs(const Vec2f &uv0, const Vec2f &uv1, con
|
||||
return out;
|
||||
}
|
||||
|
||||
float estimated_texture_preview_mm_per_pixel(const ModelVolume &model_volume)
|
||||
float estimated_texture_preview_mm_per_pixel(const ModelVolume &model_volume, const Transform3d *world_matrix = nullptr)
|
||||
{
|
||||
const unsigned int width = model_volume.imported_texture_width;
|
||||
const unsigned int height = model_volume.imported_texture_height;
|
||||
@@ -286,9 +292,15 @@ float estimated_texture_preview_mm_per_pixel(const ModelVolume &model_volume)
|
||||
size_t(indices[2]) >= its.vertices.size())
|
||||
continue;
|
||||
|
||||
const Vec3d p0 = its.vertices[size_t(indices[0])].cast<double>();
|
||||
const Vec3d p1 = its.vertices[size_t(indices[1])].cast<double>();
|
||||
const Vec3d p2 = its.vertices[size_t(indices[2])].cast<double>();
|
||||
const Vec3d p0 = world_matrix != nullptr ?
|
||||
((*world_matrix) * its.vertices[size_t(indices[0])].cast<double>()) :
|
||||
its.vertices[size_t(indices[0])].cast<double>();
|
||||
const Vec3d p1 = world_matrix != nullptr ?
|
||||
((*world_matrix) * its.vertices[size_t(indices[1])].cast<double>()) :
|
||||
its.vertices[size_t(indices[1])].cast<double>();
|
||||
const Vec3d p2 = world_matrix != nullptr ?
|
||||
((*world_matrix) * its.vertices[size_t(indices[2])].cast<double>()) :
|
||||
its.vertices[size_t(indices[2])].cast<double>();
|
||||
const double tri_area_mm2 = 0.5 * (p1 - p0).cross(p2 - p0).norm();
|
||||
if (!std::isfinite(tri_area_mm2) || tri_area_mm2 <= double(k_epsilon))
|
||||
continue;
|
||||
@@ -457,6 +469,57 @@ float texture_preview_config_float(const char *key, float fallback)
|
||||
return fallback;
|
||||
}
|
||||
|
||||
float texture_preview_config_nozzle_mm(const DynamicPrintConfig &config, const std::vector<unsigned int> &component_ids)
|
||||
{
|
||||
float nozzle = 0.4f;
|
||||
if (const ConfigOptionFloats *opt = config.option<ConfigOptionFloats>("nozzle_diameter")) {
|
||||
for (const unsigned int component_id : component_ids) {
|
||||
const size_t idx = component_id > 0 ? size_t(component_id - 1) : size_t(0);
|
||||
if (idx < opt->values.size() && std::isfinite(opt->values[idx]) && opt->values[idx] > 0.0)
|
||||
nozzle = std::max(nozzle, float(opt->values[idx]));
|
||||
}
|
||||
if (!opt->values.empty() && std::isfinite(opt->values.front()) && opt->values.front() > 0.0)
|
||||
nozzle = std::max(nozzle, float(opt->values.front()));
|
||||
}
|
||||
return nozzle;
|
||||
}
|
||||
|
||||
float texture_preview_config_line_width_mm(const DynamicPrintConfig &config,
|
||||
const char *key,
|
||||
float ratio_over,
|
||||
float fallback)
|
||||
{
|
||||
const ConfigOptionFloatOrPercent *opt = config.option<ConfigOptionFloatOrPercent>(key);
|
||||
if (opt == nullptr || !std::isfinite(opt->value) || std::abs(opt->value) <= k_epsilon)
|
||||
return fallback;
|
||||
|
||||
const float value = opt->percent ? ratio_over * float(opt->value) / 100.f : float(opt->value);
|
||||
return std::isfinite(value) && value > 0.f ? value : fallback;
|
||||
}
|
||||
|
||||
float contoning_flat_surface_lod_pitch_for_texture_preview(const TextureMappingZone &zone,
|
||||
const std::vector<unsigned int> &component_ids)
|
||||
{
|
||||
if (GUI::wxGetApp().preset_bundle == nullptr)
|
||||
return 0.f;
|
||||
|
||||
const DynamicPrintConfig config = GUI::wxGetApp().preset_bundle->full_config();
|
||||
const float nozzle = texture_preview_config_nozzle_mm(config, component_ids);
|
||||
const float line_width = texture_preview_config_line_width_mm(config, "line_width", nozzle, nozzle);
|
||||
const float external_width = texture_preview_config_line_width_mm(config, "outer_wall_line_width", nozzle, line_width);
|
||||
const float configured =
|
||||
std::clamp(zone.top_surface_contoning_min_feature_mm,
|
||||
TextureMappingZone::MinTopSurfaceContoningMinFeatureMm,
|
||||
TextureMappingZone::MaxTopSurfaceContoningMinFeatureMm);
|
||||
const float min_feature = configured > 0.f ?
|
||||
configured :
|
||||
std::max({ 2.0f, 4.f * nozzle, 3.f * external_width });
|
||||
float pitch = std::clamp(external_width,
|
||||
0.25f,
|
||||
std::max(0.25f, min_feature * 0.5f));
|
||||
return std::clamp(pitch, 0.25f, std::max(0.25f, min_feature));
|
||||
}
|
||||
|
||||
std::array<float, 2> raw_offset_visibility_factors_for_texture_preview(const TextureMappingZone &zone)
|
||||
{
|
||||
const float base_outer_width_mm =
|
||||
@@ -693,11 +756,34 @@ std::array<unsigned int, 2> simulated_texture_preview_size(unsigned int width,
|
||||
unsigned int max_edge = 0,
|
||||
size_t max_pixels = 0)
|
||||
{
|
||||
if (max_edge > 0 && max_pixels > 0)
|
||||
return limited_simulated_texture_preview_size(width, height, max_edge, max_pixels);
|
||||
return settings.limit_texture_resolution ?
|
||||
std::array<unsigned int, 2> size = max_edge > 0 && max_pixels > 0 ?
|
||||
limited_simulated_texture_preview_size(width, height, max_edge, max_pixels) :
|
||||
settings.limit_texture_resolution ?
|
||||
limited_simulated_texture_preview_size(width, height) :
|
||||
std::array<unsigned int, 2>{ width, height };
|
||||
|
||||
if (settings.contoning_flat_surface_quantization &&
|
||||
settings.simulate_top_surface_lod &&
|
||||
std::isfinite(settings.texture_preview_mm_per_pixel) &&
|
||||
std::isfinite(settings.top_surface_lod_pitch_mm) &&
|
||||
settings.texture_preview_mm_per_pixel > 0.f &&
|
||||
settings.top_surface_lod_pitch_mm > k_epsilon) {
|
||||
const double scale = double(settings.texture_preview_mm_per_pixel) / double(settings.top_surface_lod_pitch_mm);
|
||||
if (std::isfinite(scale) && scale > 0.0 && scale < 1.0) {
|
||||
unsigned int lod_width = std::max(1u, unsigned(std::ceil(double(width) * scale)));
|
||||
unsigned int lod_height = std::max(1u, unsigned(std::ceil(double(height) * scale)));
|
||||
const double lod_pixels = double(lod_width) * double(lod_height);
|
||||
if (lod_pixels > k_contoning_top_surface_preview_lod_max_samples) {
|
||||
const double sample_cap_scale = std::sqrt(k_contoning_top_surface_preview_lod_max_samples / lod_pixels);
|
||||
lod_width = std::max(1u, unsigned(std::floor(double(lod_width) * sample_cap_scale)));
|
||||
lod_height = std::max(1u, unsigned(std::floor(double(lod_height) * sample_cap_scale)));
|
||||
}
|
||||
size[0] = std::min(size[0], lod_width);
|
||||
size[1] = std::min(size[1], lod_height);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool simulated_texture_preview_needs_temporary_result(unsigned int width,
|
||||
@@ -1030,12 +1116,50 @@ bool is_gradient_zone(const TextureMappingZone &zone)
|
||||
return zone.enabled && !zone.deleted && zone.is_surface_gradient();
|
||||
}
|
||||
|
||||
const TextureMappingGlobalSettings *texture_mapping_global_preview_settings()
|
||||
{
|
||||
return GUI::wxGetApp().preset_bundle != nullptr ?
|
||||
&GUI::wxGetApp().preset_bundle->texture_mapping_global_settings :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
float texture_preview_opacity_factor()
|
||||
{
|
||||
const TextureMappingGlobalSettings *settings = texture_mapping_global_preview_settings();
|
||||
const float opacity_pct = settings != nullptr ?
|
||||
settings->preview_opacity_pct :
|
||||
TextureMappingZone::DefaultPreviewOpacityPct;
|
||||
return std::clamp(opacity_pct, 0.f, 100.f) / 100.f;
|
||||
}
|
||||
|
||||
bool texture_preview_simulate_colors()
|
||||
{
|
||||
const TextureMappingGlobalSettings *settings = texture_mapping_global_preview_settings();
|
||||
return settings != nullptr ?
|
||||
settings->preview_simulate_colors :
|
||||
TextureMappingZone::DefaultPreviewSimulateColors;
|
||||
}
|
||||
|
||||
bool texture_preview_limit_resolution()
|
||||
{
|
||||
const TextureMappingGlobalSettings *settings = texture_mapping_global_preview_settings();
|
||||
return settings != nullptr ?
|
||||
settings->preview_limit_resolution :
|
||||
TextureMappingZone::DefaultPreviewLimitResolution;
|
||||
}
|
||||
|
||||
bool texture_preview_simulate_top_surface_lod()
|
||||
{
|
||||
const TextureMappingGlobalSettings *settings = texture_mapping_global_preview_settings();
|
||||
return settings != nullptr && settings->preview_simulate_top_surface_lod;
|
||||
}
|
||||
|
||||
float texture_preview_mix_for_filament(unsigned int filament_id, size_t num_physical, const TextureMappingManager *texture_mgr)
|
||||
{
|
||||
const TextureMappingZone *zone = zone_for_filament(filament_id, num_physical, texture_mgr);
|
||||
if (zone == nullptr || (!is_image_zone(*zone) && !is_gradient_zone(*zone)))
|
||||
return 0.f;
|
||||
return std::clamp(zone->preview_opacity_pct, 0.f, 100.f) / 100.f;
|
||||
return texture_preview_opacity_factor();
|
||||
}
|
||||
|
||||
bool texture_preview_settings_invalid_for_filament(unsigned int filament_id, size_t num_physical, const TextureMappingManager *texture_mgr)
|
||||
@@ -1524,6 +1648,81 @@ std::vector<float> best_component_mix_weights_for_target(const std::vector<Textu
|
||||
return weights;
|
||||
}
|
||||
|
||||
size_t contoning_flat_surface_preview_candidate_count(size_t component_count, int total_units, size_t limit)
|
||||
{
|
||||
if (component_count == 0 || total_units <= 0)
|
||||
return 0;
|
||||
|
||||
const size_t n = size_t(total_units) + component_count - 1;
|
||||
size_t k = component_count - 1;
|
||||
k = std::min(k, n - k);
|
||||
long double count = 1.0L;
|
||||
for (size_t idx = 1; idx <= k; ++idx) {
|
||||
count = count * static_cast<long double>(n - k + idx) / static_cast<long double>(idx);
|
||||
if (count > static_cast<long double>(limit))
|
||||
return 0;
|
||||
}
|
||||
return size_t(std::max(1.0L, std::round(count)));
|
||||
}
|
||||
|
||||
std::vector<TexturePreviewMixCandidate> build_contoning_flat_surface_mix_candidates(
|
||||
const std::vector<std::array<float, 3>> &component_colors,
|
||||
int total_units)
|
||||
{
|
||||
const size_t candidate_count =
|
||||
contoning_flat_surface_preview_candidate_count(component_colors.size(),
|
||||
total_units,
|
||||
k_contoning_flat_surface_preview_max_candidates);
|
||||
if (component_colors.empty() || total_units <= 0 || candidate_count == 0)
|
||||
return {};
|
||||
|
||||
const size_t component_count = component_colors.size();
|
||||
std::vector<int> units(component_count, 0);
|
||||
std::vector<float> weights(component_count, 0.f);
|
||||
std::vector<TexturePreviewMixCandidate> candidates;
|
||||
candidates.reserve(candidate_count);
|
||||
|
||||
std::function<void(size_t, int)> recurse = [&](size_t idx, int remaining_units) {
|
||||
if (idx + 1 == component_count) {
|
||||
units[idx] = remaining_units;
|
||||
for (size_t weight_idx = 0; weight_idx < component_count; ++weight_idx)
|
||||
weights[weight_idx] = float(units[weight_idx]) / float(std::max(1, total_units));
|
||||
|
||||
TexturePreviewMixCandidate candidate;
|
||||
candidate.rgb = mix_color_solver_components(component_colors, weights, ColorSolverMixModel::PigmentPainter);
|
||||
candidate.perceptual = oklab_from_srgb(candidate.rgb);
|
||||
candidates.emplace_back(std::move(candidate));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int unit = 0; unit <= remaining_units; ++unit) {
|
||||
units[idx] = unit;
|
||||
recurse(idx + 1, remaining_units - unit);
|
||||
}
|
||||
};
|
||||
recurse(0, total_units);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
TexturePreviewMixNearestResult nearest_contoning_flat_surface_mix_candidate(
|
||||
const std::vector<TexturePreviewMixCandidate> &candidates,
|
||||
const std::vector<TexturePreviewMixCandidateKdNode> &nodes,
|
||||
int root,
|
||||
const std::array<float, 3> &target_rgb)
|
||||
{
|
||||
TexturePreviewMixNearestResult result;
|
||||
if (candidates.empty())
|
||||
return result;
|
||||
|
||||
const std::array<float, 3> target_oklab = oklab_from_srgb(target_rgb);
|
||||
const std::array<float, 3> axis_weights = { 1.f, 4.f, 4.f };
|
||||
if (root >= 0 && !nodes.empty())
|
||||
query_texture_preview_mix_candidate_perceptual_kd_tree(candidates, nodes, target_oklab, axis_weights, root, result);
|
||||
if (result.best_idx >= candidates.size())
|
||||
result = nearest_texture_preview_mix_candidates_perceptual_linear(candidates, target_oklab, axis_weights);
|
||||
return result;
|
||||
}
|
||||
|
||||
float apply_texture_tone_gamma(float channel, float tone_gamma)
|
||||
{
|
||||
const float safe_channel = clamp01(channel);
|
||||
@@ -1654,8 +1853,8 @@ std::vector<TexturePreviewBinaryDitherCandidate> binary_dither_candidates_for_te
|
||||
return candidates;
|
||||
}
|
||||
|
||||
std::array<float, 3> texture_preview_target_oklab(const TexturePreviewSimulationSettings &settings,
|
||||
const std::array<float, 4> &sample_rgba)
|
||||
std::array<float, 3> texture_preview_target_rgb(const TexturePreviewSimulationSettings &settings,
|
||||
const std::array<float, 4> &sample_rgba)
|
||||
{
|
||||
std::array<float, 3> target = {
|
||||
clamp01(sample_rgba[0]),
|
||||
@@ -1667,8 +1866,13 @@ std::array<float, 3> texture_preview_target_oklab(const TexturePreviewSimulation
|
||||
target[1] = apply_texture_tone_gamma(target[1], settings.tone_gamma);
|
||||
target[2] = apply_texture_tone_gamma(target[2], settings.tone_gamma);
|
||||
}
|
||||
target = apply_texture_contrast_to_rgb(target, std::clamp(settings.contrast_pct, 25.f, 300.f) / 100.f);
|
||||
return oklab_from_srgb(target);
|
||||
return apply_texture_contrast_to_rgb(target, std::clamp(settings.contrast_pct, 25.f, 300.f) / 100.f);
|
||||
}
|
||||
|
||||
std::array<float, 3> texture_preview_target_oklab(const TexturePreviewSimulationSettings &settings,
|
||||
const std::array<float, 4> &sample_rgba)
|
||||
{
|
||||
return oklab_from_srgb(texture_preview_target_rgb(settings, sample_rgba));
|
||||
}
|
||||
|
||||
struct TexturePreviewBinaryDitherNearestResult {
|
||||
@@ -2118,6 +2322,96 @@ std::vector<float> component_weights_for_texture_preview(const TexturePreviewSim
|
||||
return desired;
|
||||
}
|
||||
|
||||
std::array<float, 3> fallback_contoning_flat_surface_rgb_for_texture_preview(
|
||||
const TexturePreviewSimulationSettings &settings,
|
||||
const std::array<float, 4> &sample_rgba,
|
||||
int total_units)
|
||||
{
|
||||
const size_t component_count = settings.component_colors.size();
|
||||
if (component_count == 0 || total_units <= 0)
|
||||
return { sample_rgba[0], sample_rgba[1], sample_rgba[2] };
|
||||
|
||||
TexturePreviewSimulationSettings local_settings = settings;
|
||||
local_settings.dithering_enabled = false;
|
||||
local_settings.compact_offset_mode = false;
|
||||
local_settings.contoning_flat_surface_quantization = false;
|
||||
std::vector<float> continuous_weights = component_weights_for_texture_preview(local_settings, sample_rgba, false);
|
||||
continuous_weights.resize(component_count, 0.f);
|
||||
|
||||
float total_weight = 0.f;
|
||||
for (float &weight : continuous_weights) {
|
||||
weight = clamp01(weight);
|
||||
total_weight += weight;
|
||||
}
|
||||
|
||||
if (total_weight <= k_epsilon) {
|
||||
const std::array<float, 3> target_rgb = texture_preview_target_rgb(settings, sample_rgba);
|
||||
const std::array<float, 3> target_oklab = oklab_from_srgb(target_rgb);
|
||||
const std::array<float, 3> axis_weights = { 1.f, 4.f, 4.f };
|
||||
size_t best_idx = 0;
|
||||
float best_error = std::numeric_limits<float>::max();
|
||||
for (size_t idx = 0; idx < settings.component_colors.size(); ++idx) {
|
||||
const std::array<float, 3> component_oklab = oklab_from_srgb(settings.component_colors[idx]);
|
||||
const float dl = component_oklab[0] - target_oklab[0];
|
||||
const float da = component_oklab[1] - target_oklab[1];
|
||||
const float db = component_oklab[2] - target_oklab[2];
|
||||
const float error = axis_weights[0] * dl * dl + axis_weights[1] * da * da + axis_weights[2] * db * db;
|
||||
if (error < best_error) {
|
||||
best_error = error;
|
||||
best_idx = idx;
|
||||
}
|
||||
}
|
||||
std::vector<float> one_hot(component_count, 0.f);
|
||||
one_hot[best_idx] = 1.f;
|
||||
return mix_color_solver_components(settings.component_colors, one_hot, ColorSolverMixModel::PigmentPainter);
|
||||
}
|
||||
|
||||
struct QuantizedWeight {
|
||||
size_t idx { 0 };
|
||||
float remainder { 0.f };
|
||||
};
|
||||
|
||||
std::vector<int> counts(component_count, 0);
|
||||
std::vector<QuantizedWeight> remainders;
|
||||
remainders.reserve(component_count);
|
||||
int assigned = 0;
|
||||
for (size_t idx = 0; idx < component_count; ++idx) {
|
||||
const float exact = continuous_weights[idx] * float(total_units) / total_weight;
|
||||
const int count = std::clamp(int(std::floor(exact)), 0, total_units);
|
||||
counts[idx] = count;
|
||||
assigned += count;
|
||||
remainders.push_back({ idx, exact - float(count) });
|
||||
}
|
||||
std::sort(remainders.begin(), remainders.end(), [](const QuantizedWeight &lhs, const QuantizedWeight &rhs) {
|
||||
return lhs.remainder > rhs.remainder;
|
||||
});
|
||||
for (int remaining = total_units - assigned, idx = 0; remaining > 0 && !remainders.empty(); --remaining, ++idx)
|
||||
++counts[remainders[size_t(idx) % remainders.size()].idx];
|
||||
|
||||
std::vector<float> quantized_weights(component_count, 0.f);
|
||||
for (size_t idx = 0; idx < component_count; ++idx)
|
||||
quantized_weights[idx] = float(counts[idx]) / float(total_units);
|
||||
return mix_color_solver_components(settings.component_colors, quantized_weights, ColorSolverMixModel::PigmentPainter);
|
||||
}
|
||||
|
||||
std::array<float, 3> contoning_flat_surface_rgb_for_texture_preview(
|
||||
const TexturePreviewSimulationSettings &settings,
|
||||
const std::array<float, 4> &sample_rgba,
|
||||
const std::vector<TexturePreviewMixCandidate> &candidates,
|
||||
const std::vector<TexturePreviewMixCandidateKdNode> &nodes,
|
||||
int root,
|
||||
int total_units)
|
||||
{
|
||||
const std::array<float, 3> target_rgb = texture_preview_target_rgb(settings, sample_rgba);
|
||||
if (!candidates.empty()) {
|
||||
const TexturePreviewMixNearestResult nearest =
|
||||
nearest_contoning_flat_surface_mix_candidate(candidates, nodes, root, target_rgb);
|
||||
if (nearest.best_idx < candidates.size())
|
||||
return candidates[nearest.best_idx].rgb;
|
||||
}
|
||||
return fallback_contoning_flat_surface_rgb_for_texture_preview(settings, sample_rgba, total_units);
|
||||
}
|
||||
|
||||
std::vector<float> raw_offset_print_width_weights_for_texture_preview(const TexturePreviewSimulationSettings &settings,
|
||||
const std::vector<float> &raw_weights)
|
||||
{
|
||||
@@ -2205,7 +2499,7 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
const std::vector<std::string> &physical_colors)
|
||||
{
|
||||
const TextureMappingZone *zone = zone_for_filament(filament_id, num_physical, texture_mgr);
|
||||
if (zone == nullptr || !is_image_zone(*zone) || !zone->preview_simulate_colors)
|
||||
if (zone == nullptr || !is_image_zone(*zone) || !texture_preview_simulate_colors())
|
||||
return std::nullopt;
|
||||
|
||||
TexturePreviewSimulationSettings settings;
|
||||
@@ -2216,7 +2510,7 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
int(TextureMappingZone::FilamentColorAny),
|
||||
int(TextureMappingZone::FilamentColorRGBKW));
|
||||
settings.force_sequential_filaments = zone->force_sequential_filaments;
|
||||
settings.limit_texture_resolution = zone->preview_limit_resolution;
|
||||
settings.limit_texture_resolution = texture_preview_limit_resolution();
|
||||
settings.dithering_enabled =
|
||||
zone->dithering_enabled &&
|
||||
settings.mapping_mode != int(TextureMappingZone::TextureMappingRawValues);
|
||||
@@ -2246,6 +2540,17 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
int(TextureMappingZone::GenericSolverLegacy),
|
||||
int(TextureMappingZone::GenericSolverV2));
|
||||
settings.generic_solver_mix_model = TextureMappingZone::DefaultGenericSolverMixModel;
|
||||
if (zone->top_surface_contoning_active()) {
|
||||
const int stack_layers =
|
||||
std::clamp(zone->top_surface_contoning_stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers);
|
||||
const int pattern_filaments =
|
||||
std::clamp(zone->top_surface_contoning_pattern_filaments,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments);
|
||||
settings.contoning_flat_surface_pattern_filaments = std::max(1, std::min(stack_layers, pattern_filaments));
|
||||
}
|
||||
settings.minimum_visibility_offset_factor = zone->minimum_visibility_offset_enabled ?
|
||||
std::clamp((std::isfinite(zone->minimum_visibility_offset_pct) ?
|
||||
zone->minimum_visibility_offset_pct :
|
||||
@@ -2256,6 +2561,9 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
settings.component_ids = TextureMappingManager::effective_texture_component_ids(*zone, num_physical, physical_colors);
|
||||
if (settings.component_ids.empty())
|
||||
return std::nullopt;
|
||||
settings.simulate_top_surface_lod =
|
||||
texture_preview_simulate_top_surface_lod() &&
|
||||
zone->top_surface_contoning_active();
|
||||
|
||||
const bool raw_values_mode = settings.mapping_mode == int(TextureMappingZone::TextureMappingRawValues);
|
||||
settings.component_colors.reserve(settings.component_ids.size());
|
||||
@@ -2318,6 +2626,13 @@ size_t texture_preview_simulation_signature(const ModelVolume &model_volume,
|
||||
mix(std::hash<int>{}(settings.generic_solver_lookup_mode));
|
||||
mix(std::hash<int>{}(settings.generic_solver_mode));
|
||||
mix(std::hash<int>{}(settings.generic_solver_mix_model));
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_quantization ? 1 : 0));
|
||||
if (settings.contoning_flat_surface_quantization) {
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_pattern_filaments));
|
||||
mix(std::hash<int>{}(settings.simulate_top_surface_lod ? 1 : 0));
|
||||
if (settings.simulate_top_surface_lod)
|
||||
mix(std::hash<int>{}(int(std::lround(settings.top_surface_lod_pitch_mm * 100000.f))));
|
||||
}
|
||||
mix(std::hash<int>{}(int(std::lround(settings.contrast_pct * 100.f))));
|
||||
mix(std::hash<int>{}(int(std::lround(settings.tone_gamma * 1000.f))));
|
||||
mix(std::hash<int>{}(int(std::lround(settings.minimum_visibility_offset_factor * 100000.f))));
|
||||
@@ -2363,15 +2678,35 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
return result;
|
||||
|
||||
prepare_texture_preview_simulation_settings(settings);
|
||||
const int contoning_flat_surface_pattern_filaments =
|
||||
std::clamp(settings.contoning_flat_surface_pattern_filaments,
|
||||
TextureMappingZone::MinTopSurfaceContoningPatternFilaments,
|
||||
TextureMappingZone::MaxTopSurfaceContoningPatternFilaments);
|
||||
const bool use_contoning_flat_surface_quantization =
|
||||
settings.contoning_flat_surface_quantization &&
|
||||
settings.mapping_mode != int(TextureMappingZone::TextureMappingRawValues) &&
|
||||
!settings.component_colors.empty() &&
|
||||
contoning_flat_surface_pattern_filaments > 0;
|
||||
const std::vector<TexturePreviewMixCandidate> contoning_flat_surface_candidates =
|
||||
use_contoning_flat_surface_quantization ?
|
||||
build_contoning_flat_surface_mix_candidates(settings.component_colors, contoning_flat_surface_pattern_filaments) :
|
||||
std::vector<TexturePreviewMixCandidate>{};
|
||||
std::vector<TexturePreviewMixCandidateKdNode> contoning_flat_surface_nodes;
|
||||
const int contoning_flat_surface_root = contoning_flat_surface_candidates.empty() ?
|
||||
-1 :
|
||||
build_generic_mix_candidate_kd_tree(contoning_flat_surface_candidates, contoning_flat_surface_nodes, true);
|
||||
const bool use_raw_offsets =
|
||||
!use_contoning_flat_surface_quantization &&
|
||||
source_raw_component_channels.size() == settings.component_colors.size() &&
|
||||
source_raw_offsets.size() >= size_t(width) * size_t(height) * size_t(source_raw_channels);
|
||||
const bool use_binary_dithering =
|
||||
!use_contoning_flat_surface_quantization &&
|
||||
settings.dithering_enabled &&
|
||||
settings.mapping_mode != int(TextureMappingZone::TextureMappingRawValues) &&
|
||||
!is_halftone_dithering_method_for_texture_preview(settings.dithering_method) &&
|
||||
!use_raw_offsets;
|
||||
const bool use_halftone_dithering =
|
||||
!use_contoning_flat_surface_quantization &&
|
||||
settings.dithering_enabled &&
|
||||
settings.mapping_mode != int(TextureMappingZone::TextureMappingRawValues) &&
|
||||
is_halftone_dithering_method_for_texture_preview(settings.dithering_method) &&
|
||||
@@ -2404,15 +2739,57 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
return key;
|
||||
};
|
||||
|
||||
auto component_coverage_at_source = [&](double src_x, double src_y, size_t component_idx) {
|
||||
const double source_step_x = double(width) / double(std::max(1u, result.width));
|
||||
const double source_step_y = double(height) / double(std::max(1u, result.height));
|
||||
const bool use_contoning_flat_surface_lod_supersampling =
|
||||
use_contoning_flat_surface_quantization &&
|
||||
settings.simulate_top_surface_lod &&
|
||||
(source_step_x > 1.05 || source_step_y > 1.05);
|
||||
|
||||
auto sample_blended_source_color_at_source = [&](double sample_src_x, double sample_src_y) {
|
||||
const std::array<unsigned char, 4> source_rgba_sample =
|
||||
sample_texture_preview_rgba_bilinear_at_source(source_rgba, width, height, src_x, src_y);
|
||||
const ColorRGBA blended_source_color =
|
||||
composite_texture_mapping_color_over_background_for_preview(ColorRGBA(float(source_rgba_sample[0]) / 255.f,
|
||||
float(source_rgba_sample[1]) / 255.f,
|
||||
float(source_rgba_sample[2]) / 255.f,
|
||||
float(source_rgba_sample[3]) / 255.f),
|
||||
background_color);
|
||||
sample_texture_preview_rgba_bilinear_at_source(source_rgba, width, height, sample_src_x, sample_src_y);
|
||||
return composite_texture_mapping_color_over_background_for_preview(ColorRGBA(float(source_rgba_sample[0]) / 255.f,
|
||||
float(source_rgba_sample[1]) / 255.f,
|
||||
float(source_rgba_sample[2]) / 255.f,
|
||||
float(source_rgba_sample[3]) / 255.f),
|
||||
background_color);
|
||||
};
|
||||
|
||||
auto sample_blended_source_color_for_texel = [&](double src_x, double src_y) {
|
||||
if (!use_contoning_flat_surface_lod_supersampling)
|
||||
return sample_blended_source_color_at_source(src_x, src_y);
|
||||
|
||||
const double radius_x = source_step_x * 0.35;
|
||||
const double radius_y = source_step_y * 0.35;
|
||||
const std::array<std::array<double, 2>, 9> offsets = {
|
||||
std::array<double, 2>{ 0.0, 0.0 },
|
||||
std::array<double, 2>{ -radius_x, -radius_y },
|
||||
std::array<double, 2>{ 0.0, -radius_y },
|
||||
std::array<double, 2>{ radius_x, -radius_y },
|
||||
std::array<double, 2>{ -radius_x, 0.0 },
|
||||
std::array<double, 2>{ radius_x, 0.0 },
|
||||
std::array<double, 2>{ -radius_x, radius_y },
|
||||
std::array<double, 2>{ 0.0, radius_y },
|
||||
std::array<double, 2>{ radius_x, radius_y }
|
||||
};
|
||||
float r = 0.f;
|
||||
float g = 0.f;
|
||||
float b = 0.f;
|
||||
float a = 0.f;
|
||||
for (const std::array<double, 2> &offset : offsets) {
|
||||
const ColorRGBA color = sample_blended_source_color_at_source(src_x + offset[0], src_y + offset[1]);
|
||||
r += color.r();
|
||||
g += color.g();
|
||||
b += color.b();
|
||||
a += color.a();
|
||||
}
|
||||
const float inv_count = 1.f / float(offsets.size());
|
||||
return ColorRGBA(r * inv_count, g * inv_count, b * inv_count, a * inv_count);
|
||||
};
|
||||
|
||||
auto component_coverage_at_source = [&](double src_x, double src_y, size_t component_idx) {
|
||||
const ColorRGBA blended_source_color = sample_blended_source_color_at_source(src_x, src_y);
|
||||
const std::array<float, 4> sampled_rgba = {
|
||||
blended_source_color.r(),
|
||||
blended_source_color.g(),
|
||||
@@ -2481,14 +2858,7 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
for (unsigned int x = 0; x < result.width; ++x) {
|
||||
const double src_x = (double(x) + 0.5) * double(width) / double(std::max(1u, result.width)) - 0.5;
|
||||
const double src_y = (double(y) + 0.5) * double(height) / double(std::max(1u, result.height)) - 0.5;
|
||||
const std::array<unsigned char, 4> source_rgba_sample =
|
||||
sample_texture_preview_rgba_bilinear_at_source(source_rgba, width, height, src_x, src_y);
|
||||
const ColorRGBA blended_source_color =
|
||||
composite_texture_mapping_color_over_background_for_preview(ColorRGBA(float(source_rgba_sample[0]) / 255.f,
|
||||
float(source_rgba_sample[1]) / 255.f,
|
||||
float(source_rgba_sample[2]) / 255.f,
|
||||
float(source_rgba_sample[3]) / 255.f),
|
||||
background_color);
|
||||
const ColorRGBA blended_source_color = sample_blended_source_color_for_texel(src_x, src_y);
|
||||
const std::array<unsigned char, 3> source_rgb = {
|
||||
to_u8(blended_source_color.r()),
|
||||
to_u8(blended_source_color.g()),
|
||||
@@ -2517,6 +2887,7 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
1.f
|
||||
};
|
||||
std::vector<float> component_weights;
|
||||
std::optional<std::array<float, 3>> forced_simulated_rgb;
|
||||
if (use_raw_offsets) {
|
||||
const std::vector<float> raw_sample =
|
||||
sample_texture_preview_raw_offsets_bilinear(source_raw_offsets,
|
||||
@@ -2531,7 +2902,15 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
if (component_weights.size() == settings.component_colors.size())
|
||||
component_weights = raw_offset_print_width_weights_for_texture_preview(settings, component_weights);
|
||||
} else {
|
||||
if (use_halftone_dithering) {
|
||||
if (use_contoning_flat_surface_quantization) {
|
||||
forced_simulated_rgb =
|
||||
contoning_flat_surface_rgb_for_texture_preview(settings,
|
||||
sample_rgba,
|
||||
contoning_flat_surface_candidates,
|
||||
contoning_flat_surface_nodes,
|
||||
contoning_flat_surface_root,
|
||||
contoning_flat_surface_pattern_filaments);
|
||||
} else if (use_halftone_dithering) {
|
||||
const std::vector<float> continuous_coverage =
|
||||
component_weights_for_texture_preview(settings, sample_rgba, false);
|
||||
uint32_t mask = 0;
|
||||
@@ -2613,13 +2992,15 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
activity = 1.f;
|
||||
}
|
||||
|
||||
const std::array<float, 3> simulated_rgb = activity > k_epsilon ?
|
||||
const std::array<float, 3> simulated_rgb = forced_simulated_rgb.has_value() ?
|
||||
*forced_simulated_rgb :
|
||||
(activity > k_epsilon ?
|
||||
mix_color_solver_components(settings.component_colors,
|
||||
component_weights,
|
||||
use_halftone_dithering ?
|
||||
ColorSolverMixModel::PigmentPainter :
|
||||
color_solver_mix_model_from_index(settings.generic_solver_mix_model)) :
|
||||
std::array<float, 3>{ sample_rgba[0], sample_rgba[1], sample_rgba[2] };
|
||||
std::array<float, 3>{ sample_rgba[0], sample_rgba[1], sample_rgba[2] });
|
||||
|
||||
const std::array<unsigned char, 4> out_rgba = {
|
||||
to_u8(simulated_rgb[0]),
|
||||
@@ -2908,10 +3289,16 @@ bool texture_preview_simulation_has_temporary_pending_impl()
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t texture_preview_simulation_cache_key(const ModelVolume &model_volume, unsigned int filament_id)
|
||||
size_t texture_preview_simulation_cache_key(const ModelVolume &model_volume,
|
||||
unsigned int filament_id,
|
||||
unsigned int variant = 0,
|
||||
float texture_preview_mm_per_pixel = 0.f)
|
||||
{
|
||||
size_t key = reinterpret_cast<size_t>(&model_volume);
|
||||
key ^= std::hash<unsigned int>{}(filament_id) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
|
||||
key ^= std::hash<unsigned int>{}(variant) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
|
||||
if (std::isfinite(texture_preview_mm_per_pixel) && texture_preview_mm_per_pixel > 0.f)
|
||||
key ^= std::hash<int>{}(int(std::lround(texture_preview_mm_per_pixel * 100000.f))) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -2957,23 +3344,40 @@ void consume_temporary_simulated_texture_preview_result(TexturePreviewSimulation
|
||||
}
|
||||
|
||||
const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const ModelVolume &model_volume,
|
||||
const Transform3d &world_matrix,
|
||||
unsigned int filament_id,
|
||||
size_t num_physical,
|
||||
const TextureMappingManager *texture_mgr,
|
||||
size_t source_texture_signature,
|
||||
const GUI::GLTexture &fallback_texture)
|
||||
const GUI::GLTexture &fallback_texture,
|
||||
bool contoning_flat_surface_quantization = false,
|
||||
bool *simulated_ready = nullptr)
|
||||
{
|
||||
if (simulated_ready != nullptr)
|
||||
*simulated_ready = false;
|
||||
const TextureMappingZone *zone = zone_for_filament(filament_id, num_physical, texture_mgr);
|
||||
if (contoning_flat_surface_quantization &&
|
||||
(zone == nullptr || !is_image_zone(*zone) || !texture_preview_simulate_colors() || !zone->top_surface_contoning_active()))
|
||||
return nullptr;
|
||||
|
||||
const std::vector<std::string> physical_colors = physical_filament_colors_for_texture_preview(num_physical);
|
||||
std::optional<TexturePreviewSimulationSettings> settings =
|
||||
texture_preview_simulation_settings_for_filament(filament_id, num_physical, texture_mgr, physical_colors);
|
||||
if (!settings.has_value())
|
||||
return &fallback_texture;
|
||||
settings->texture_preview_mm_per_pixel = estimated_texture_preview_mm_per_pixel(model_volume);
|
||||
return contoning_flat_surface_quantization ? nullptr : &fallback_texture;
|
||||
settings->contoning_flat_surface_quantization = contoning_flat_surface_quantization;
|
||||
settings->texture_preview_mm_per_pixel = estimated_texture_preview_mm_per_pixel(model_volume, &world_matrix);
|
||||
if (settings->contoning_flat_surface_quantization && settings->simulate_top_surface_lod)
|
||||
settings->top_surface_lod_pitch_mm =
|
||||
contoning_flat_surface_lod_pitch_for_texture_preview(*zone, settings->component_ids);
|
||||
|
||||
const ColorRGBA background_color = texture_mapping_background_color_for_preview(model_volume);
|
||||
const size_t simulation_signature = texture_preview_simulation_signature(model_volume, source_texture_signature, *settings);
|
||||
auto &cache = texture_preview_simulation_cache();
|
||||
const size_t cache_key = texture_preview_simulation_cache_key(model_volume, filament_id);
|
||||
const size_t cache_key = texture_preview_simulation_cache_key(model_volume,
|
||||
filament_id,
|
||||
contoning_flat_surface_quantization ? 1u : 0u,
|
||||
settings->texture_preview_mm_per_pixel);
|
||||
std::shared_ptr<TexturePreviewSimulationCacheEntry> &entry_ref = cache[cache_key];
|
||||
if (entry_ref == nullptr)
|
||||
entry_ref = std::make_shared<TexturePreviewSimulationCacheEntry>();
|
||||
@@ -2997,8 +3401,11 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model
|
||||
entry.pending_job_state.reset();
|
||||
}
|
||||
|
||||
if (entry.texture != nullptr && entry.uploaded_signature == simulation_signature && entry.texture->get_id() != 0)
|
||||
if (entry.texture != nullptr && entry.uploaded_signature == simulation_signature && entry.texture->get_id() != 0) {
|
||||
if (simulated_ready != nullptr)
|
||||
*simulated_ready = true;
|
||||
return entry.texture.get();
|
||||
}
|
||||
|
||||
if (!entry.pending_future.valid()) {
|
||||
entry.pending_signature = simulation_signature;
|
||||
@@ -3064,10 +3471,13 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model
|
||||
if (temporary_signature != 0 &&
|
||||
entry.texture != nullptr &&
|
||||
entry.uploaded_signature == temporary_signature &&
|
||||
entry.texture->get_id() != 0)
|
||||
entry.texture->get_id() != 0) {
|
||||
if (simulated_ready != nullptr)
|
||||
*simulated_ready = true;
|
||||
return entry.texture.get();
|
||||
}
|
||||
|
||||
return &fallback_texture;
|
||||
return contoning_flat_surface_quantization ? nullptr : &fallback_texture;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -4405,7 +4815,7 @@ std::optional<SurfaceGradientPreviewSettings> surface_gradient_preview_settings_
|
||||
std::clamp(zone.offset_fade_mode,
|
||||
int(TextureMappingZone::OffsetFadeNone),
|
||||
int(TextureMappingZone::OffsetFadeOutInReversed));
|
||||
settings.limit_texture_resolution = zone.preview_limit_resolution;
|
||||
settings.limit_texture_resolution = texture_preview_limit_resolution();
|
||||
const float base_outer_width_mm = std::max(0.05f, surface_gradient_preview_config_float("texture_mapping_outer_wall_gradient_max_line_width", 0.95f));
|
||||
const float min_outer_width_mm = std::clamp(surface_gradient_preview_config_float("texture_mapping_outer_wall_gradient_min_line_width", 0.32f),
|
||||
0.05f,
|
||||
@@ -5033,6 +5443,10 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical,
|
||||
signature_mix_float(texture_preview_config_float("texture_mapping_outer_wall_gradient_global_strength", 100.f), 100.f);
|
||||
signature_mix_float(texture_preview_config_float("texture_mapping_outer_wall_gradient_max_line_width", 0.95f), 1000.f);
|
||||
signature_mix_float(texture_preview_config_float("texture_mapping_outer_wall_gradient_min_line_width", 0.32f), 1000.f);
|
||||
signature_mix_float(texture_preview_opacity_factor(), 10000.f);
|
||||
signature_mix(std::hash<int>{}(texture_preview_simulate_colors() ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(texture_preview_limit_resolution() ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(texture_preview_simulate_top_surface_lod() ? 1 : 0));
|
||||
if (texture_mgr == nullptr)
|
||||
return signature;
|
||||
|
||||
@@ -5066,6 +5480,11 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical,
|
||||
signature_mix(std::hash<int>{}(zone.texture_mapping_mode));
|
||||
signature_mix(std::hash<int>{}(zone.filament_color_mode));
|
||||
signature_mix(std::hash<int>{}(zone.force_sequential_filaments ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_image_printing_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_image_printing_method));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_stack_layers));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_pattern_filaments));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_color_lower_surfaces ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.nonlinear_offset_adjustment ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.compact_offset_mode ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.use_legacy_fixed_color_mode ? 1 : 0));
|
||||
@@ -5080,9 +5499,6 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical,
|
||||
signature_mix(std::hash<int>{}(zone.generic_solver_lookup_mode));
|
||||
signature_mix(std::hash<int>{}(zone.generic_solver_mode));
|
||||
signature_mix(std::hash<int>{}(TextureMappingZone::DefaultGenericSolverMixModel));
|
||||
signature_mix(std::hash<int>{}(zone.preview_simulate_colors ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.preview_limit_resolution ? 1 : 0));
|
||||
signature_mix_float(zone.preview_opacity_pct, 100.f);
|
||||
signature_mix_float(zone.contrast_pct, 100.f);
|
||||
signature_mix_float(zone.tone_gamma);
|
||||
for (const float strength_pct : zone.filament_strengths_pct)
|
||||
@@ -5123,7 +5539,7 @@ static bool active_texture_preview_zone_ids_contains(const std::vector<unsigned
|
||||
|
||||
static bool texture_preview_zone_uses_halftone_model(const TextureMappingZone &zone)
|
||||
{
|
||||
if (!zone.enabled || zone.deleted || !zone.is_image_texture() || !zone.preview_simulate_colors)
|
||||
if (!zone.enabled || zone.deleted || !zone.is_image_texture() || !texture_preview_simulate_colors())
|
||||
return false;
|
||||
const int mapping_mode = std::clamp(zone.texture_mapping_mode,
|
||||
int(TextureMappingZone::TextureMappingFilamentBlending),
|
||||
@@ -5136,6 +5552,29 @@ static bool texture_preview_zone_uses_halftone_model(const TextureMappingZone &z
|
||||
is_halftone_dithering_method_for_texture_preview(method);
|
||||
}
|
||||
|
||||
static bool texture_preview_zone_uses_contoning_flat_surface_texture(const TextureMappingZone &zone)
|
||||
{
|
||||
return zone.enabled &&
|
||||
!zone.deleted &&
|
||||
zone.is_image_texture() &&
|
||||
texture_preview_simulate_colors() &&
|
||||
zone.texture_mapping_mode != int(TextureMappingZone::TextureMappingRawValues) &&
|
||||
zone.top_surface_contoning_active();
|
||||
}
|
||||
|
||||
static bool texture_preview_contoning_flat_surface_texture_for_filament(unsigned int filament_id,
|
||||
size_t num_physical,
|
||||
const TextureMappingManager *texture_mgr,
|
||||
bool &include_bottom)
|
||||
{
|
||||
include_bottom = false;
|
||||
const TextureMappingZone *zone = zone_for_filament(filament_id, num_physical, texture_mgr);
|
||||
if (zone == nullptr || !texture_preview_zone_uses_contoning_flat_surface_texture(*zone))
|
||||
return false;
|
||||
include_bottom = zone->top_surface_contoning_color_lower_surfaces;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool texture_preview_gradient_zone_uses_model(const TextureMappingZone &zone, size_t num_physical)
|
||||
{
|
||||
if (!zone.enabled || zone.deleted || !zone.is_surface_gradient())
|
||||
@@ -5176,6 +5615,11 @@ static void texture_preview_mix_zone_baked_model_settings(size_t &signature,
|
||||
signature_mix(std::hash<int>{}(zone.texture_mapping_mode));
|
||||
signature_mix(std::hash<int>{}(zone.filament_color_mode));
|
||||
signature_mix(std::hash<int>{}(zone.force_sequential_filaments ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_image_printing_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_image_printing_method));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_stack_layers));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_pattern_filaments));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_color_lower_surfaces ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.nonlinear_offset_adjustment ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.compact_offset_mode ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.use_legacy_fixed_color_mode ? 1 : 0));
|
||||
@@ -5190,8 +5634,6 @@ static void texture_preview_mix_zone_baked_model_settings(size_t &signature,
|
||||
signature_mix(std::hash<int>{}(zone.generic_solver_lookup_mode));
|
||||
signature_mix(std::hash<int>{}(zone.generic_solver_mode));
|
||||
signature_mix(std::hash<int>{}(TextureMappingZone::DefaultGenericSolverMixModel));
|
||||
signature_mix(std::hash<int>{}(zone.preview_simulate_colors ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.preview_limit_resolution ? 1 : 0));
|
||||
signature_mix_float(zone.contrast_pct, 100.f);
|
||||
signature_mix_float(zone.tone_gamma);
|
||||
signature_mix(std::hash<int>{}(zone.linear_gradient_mode));
|
||||
@@ -5286,7 +5728,7 @@ size_t texture_preview_model_settings_signature(size_t num_physical,
|
||||
const bool halftone_model = texture_preview_zone_uses_halftone_model(zone);
|
||||
const bool simulated_vertex_color_model =
|
||||
image_zone &&
|
||||
zone.preview_simulate_colors &&
|
||||
texture_preview_simulate_colors() &&
|
||||
(has_texture_mapping_color_preview_data || (!has_texture_preview_data && has_vertex_color_preview_data));
|
||||
signature_mix(std::hash<int>{}(halftone_model ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(simulated_vertex_color_model ? 1 : 0));
|
||||
@@ -5339,9 +5781,13 @@ void render_model_texture_preview_models(
|
||||
set_color_match_preview_uniforms(*shader, color_match);
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
shader->set_uniform("uniform_texture", 0);
|
||||
shader->set_uniform("contoning_flat_surface_texture", 1);
|
||||
shader->set_uniform("contoning_flat_surface_texture_enabled", false);
|
||||
shader->set_uniform("contoning_flat_surface_include_bottom", false);
|
||||
|
||||
const size_t texture_signature = model_volume_texture_preview_signature(model_volume);
|
||||
GLuint bound_texture_id = 0;
|
||||
GLuint bound_contoning_flat_texture_id = 0;
|
||||
const bool color_match_active = color_match != nullptr && color_match->active;
|
||||
for (size_t idx = 0; idx < models.size(); ++idx) {
|
||||
if (color_match_active && !color_match_preview_allows_filament(color_match, filament_ids[idx]))
|
||||
@@ -5361,6 +5807,7 @@ void render_model_texture_preview_models(
|
||||
const GUI::GLTexture *preview_texture = force_original_texture ?
|
||||
&texture :
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
filament_ids[idx],
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
@@ -5370,16 +5817,50 @@ void render_model_texture_preview_models(
|
||||
continue;
|
||||
|
||||
if (preview_texture->get_id() != bound_texture_id) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
bound_texture_id = preview_texture->get_id();
|
||||
}
|
||||
|
||||
bool include_contoning_bottom = false;
|
||||
bool contoning_flat_ready = false;
|
||||
const bool use_contoning_flat_texture =
|
||||
!color_match_active &&
|
||||
!force_original_texture &&
|
||||
texture_preview_contoning_flat_surface_texture_for_filament(filament_ids[idx],
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
include_contoning_bottom);
|
||||
const GUI::GLTexture *contoning_flat_texture = use_contoning_flat_texture ?
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
filament_ids[idx],
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
texture_signature,
|
||||
texture,
|
||||
true,
|
||||
&contoning_flat_ready) :
|
||||
nullptr;
|
||||
const bool contoning_flat_enabled =
|
||||
contoning_flat_ready && contoning_flat_texture != nullptr && contoning_flat_texture->get_id() != 0;
|
||||
if (contoning_flat_enabled && contoning_flat_texture->get_id() != bound_contoning_flat_texture_id) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, contoning_flat_texture->get_id()));
|
||||
bound_contoning_flat_texture_id = contoning_flat_texture->get_id();
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
shader->set_uniform("contoning_flat_surface_texture_enabled", contoning_flat_enabled);
|
||||
shader->set_uniform("contoning_flat_surface_include_bottom", contoning_flat_enabled && include_contoning_bottom);
|
||||
shader->set_uniform("texture_preview_mix", color_match_active ? 1.f : mix);
|
||||
shader->set_uniform("invalid_texture_mapping", invalid);
|
||||
models[idx].set_color(colors[idx]);
|
||||
models[idx].render();
|
||||
}
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
shader->stop_using();
|
||||
restore_render_state(render_state);
|
||||
@@ -5426,6 +5907,7 @@ void render_model_texture_preview_model(
|
||||
const GUI::GLTexture *preview_texture = force_original_texture ?
|
||||
&texture :
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
filament_id,
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
@@ -5450,6 +5932,36 @@ void render_model_texture_preview_model(
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
shader->set_uniform("uniform_texture", 0);
|
||||
shader->set_uniform("contoning_flat_surface_texture", 1);
|
||||
bool include_contoning_bottom = false;
|
||||
bool contoning_flat_ready = false;
|
||||
const bool use_contoning_flat_texture =
|
||||
!color_match_active &&
|
||||
!force_original_texture &&
|
||||
texture_preview_contoning_flat_surface_texture_for_filament(filament_id,
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
include_contoning_bottom);
|
||||
const GUI::GLTexture *contoning_flat_texture = use_contoning_flat_texture ?
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
filament_id,
|
||||
num_physical,
|
||||
texture_mgr,
|
||||
texture_signature,
|
||||
texture,
|
||||
true,
|
||||
&contoning_flat_ready) :
|
||||
nullptr;
|
||||
const bool contoning_flat_enabled =
|
||||
contoning_flat_ready && contoning_flat_texture != nullptr && contoning_flat_texture->get_id() != 0;
|
||||
if (contoning_flat_enabled) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, contoning_flat_texture->get_id()));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
shader->set_uniform("contoning_flat_surface_texture_enabled", contoning_flat_enabled);
|
||||
shader->set_uniform("contoning_flat_surface_include_bottom", contoning_flat_enabled && include_contoning_bottom);
|
||||
shader->set_uniform("texture_preview_mix", color_match_active ? 1.f : mix);
|
||||
shader->set_uniform("invalid_texture_mapping", invalid);
|
||||
model.set_color(color);
|
||||
@@ -5458,6 +5970,9 @@ void render_model_texture_preview_model(
|
||||
else
|
||||
model.render(render_range);
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
shader->stop_using();
|
||||
restore_render_state(render_state);
|
||||
|
||||
@@ -621,7 +621,9 @@ static bool assign_imported_texture_mapping_zone(Model &model)
|
||||
return false;
|
||||
|
||||
project_config.option<ConfigOptionString>("texture_mapping_definitions", true);
|
||||
project_config.option<ConfigOptionString>("texture_mapping_global_settings", true);
|
||||
bundle->texture_mapping_zones.load_entries(project_config.opt_string("texture_mapping_definitions"), color_opt->values);
|
||||
bundle->texture_mapping_global_settings.load(project_config.opt_string("texture_mapping_global_settings"));
|
||||
const unsigned int zone_id = bundle->texture_mapping_zones.ensure_image_texture_zone(color_opt->values.size(), color_opt->values);
|
||||
if (zone_id == 0)
|
||||
return false;
|
||||
@@ -636,6 +638,15 @@ static bool assign_imported_texture_mapping_zone(Model &model)
|
||||
opt->value = serialized;
|
||||
else
|
||||
print_config.set_key_value("texture_mapping_definitions", new ConfigOptionString(serialized));
|
||||
const std::string global_serialized = bundle->texture_mapping_global_settings.serialize();
|
||||
if (ConfigOptionString *opt = project_config.option<ConfigOptionString>("texture_mapping_global_settings"))
|
||||
opt->value = global_serialized;
|
||||
else
|
||||
project_config.set_key_value("texture_mapping_global_settings", new ConfigOptionString(global_serialized));
|
||||
if (ConfigOptionString *opt = print_config.option<ConfigOptionString>("texture_mapping_global_settings"))
|
||||
opt->value = global_serialized;
|
||||
else
|
||||
print_config.set_key_value("texture_mapping_global_settings", new ConfigOptionString(global_serialized));
|
||||
|
||||
for (ModelObject *object : model.objects) {
|
||||
if (!model_object_has_imported_texture_mapping_data(object))
|
||||
@@ -760,6 +771,7 @@ static void load_texture_mapping_definitions(PresetBundle &bundle, const std::st
|
||||
set_texture_mapping_definitions(bundle, serialized);
|
||||
const ConfigOptionStrings *color_opt = bundle.project_config.option<ConfigOptionStrings>("filament_colour", false);
|
||||
bundle.texture_mapping_zones.load_entries(serialized, color_opt != nullptr ? color_opt->values : std::vector<std::string>());
|
||||
set_texture_mapping_definitions(bundle, bundle.texture_mapping_zones.serialize_entries());
|
||||
}
|
||||
|
||||
static void sync_model_texture_mapping_definitions(Model &model, const std::string &serialized)
|
||||
@@ -1867,10 +1879,8 @@ public:
|
||||
const std::vector<float> &component_transmission_distances_mm,
|
||||
int transmission_distance_calibration_mode,
|
||||
float tone_gamma,
|
||||
float preview_opacity_pct,
|
||||
bool force_sequential_filaments,
|
||||
bool auto_adjust_filament_selection,
|
||||
bool preview_limit_resolution,
|
||||
bool reduce_outer_surface_texture,
|
||||
bool seam_hiding,
|
||||
bool nonlinear_offset_adjustment,
|
||||
@@ -2125,13 +2135,28 @@ public:
|
||||
m_force_sequential_filaments_checkbox->SetValue(force_sequential_filaments);
|
||||
filament_root->Add(m_force_sequential_filaments_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap);
|
||||
|
||||
filament_root->AddStretchSpacer(1);
|
||||
auto *filament_calibration_note =
|
||||
new wxStaticText(filament_page,
|
||||
wxID_ANY,
|
||||
_L("NOTE: Filament/TD calibration is not currently used in top-surface coloring"),
|
||||
wxDefaultPosition,
|
||||
wxSize(FromDIP(390), -1));
|
||||
filament_calibration_note->Wrap(FromDIP(390));
|
||||
filament_root->Add(filament_calibration_note, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap);
|
||||
filament_page->Bind(wxEVT_SIZE, [this, filament_page, filament_calibration_note, gap](wxSizeEvent &evt) {
|
||||
const int wrap_width = std::max(FromDIP(120), filament_page->GetClientSize().GetWidth() - gap * 2);
|
||||
filament_calibration_note->Wrap(wrap_width);
|
||||
evt.Skip();
|
||||
});
|
||||
|
||||
auto *preview_box = new wxStaticBoxSizer(wxVERTICAL, preview_page, _L("3D Preview"));
|
||||
auto *preview_opacity_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
preview_opacity_row->Add(new wxStaticText(preview_page, wxID_ANY, _L("Texture opacity")),
|
||||
0,
|
||||
wxALIGN_CENTER_VERTICAL | wxRIGHT,
|
||||
gap);
|
||||
const int opacity = std::clamp(int(std::lround(preview_opacity_pct)), 0, 100);
|
||||
const int opacity = std::clamp(int(std::lround(m_global_settings.preview_opacity_pct)), 0, 100);
|
||||
m_preview_opacity_slider = new wxSlider(preview_page, wxID_ANY, opacity, 0, 100, wxDefaultPosition, wxSize(FromDIP(180), -1), wxSL_HORIZONTAL | wxSL_AUTOTICKS);
|
||||
m_preview_opacity_spin = new wxSpinCtrl(preview_page, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(70), -1),
|
||||
wxSP_ARROW_KEYS | wxALIGN_RIGHT, 0, 100, opacity);
|
||||
@@ -2151,8 +2176,11 @@ public:
|
||||
m_auto_adjust_filament_selection_checkbox->SetValue(auto_adjust_filament_selection);
|
||||
preview_box->Add(m_auto_adjust_filament_selection_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap);
|
||||
m_preview_limit_resolution_checkbox = new wxCheckBox(preview_page, wxID_ANY, _L("Limit color simulation texture resolution"));
|
||||
m_preview_limit_resolution_checkbox->SetValue(preview_limit_resolution);
|
||||
m_preview_limit_resolution_checkbox->SetValue(m_global_settings.preview_limit_resolution);
|
||||
preview_box->Add(m_preview_limit_resolution_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap);
|
||||
m_preview_top_surface_lod_checkbox = new wxCheckBox(preview_page, wxID_ANY, _L("Simulate level of detail for top-surface coloring"));
|
||||
m_preview_top_surface_lod_checkbox->SetValue(m_global_settings.preview_simulate_top_surface_lod);
|
||||
preview_box->Add(m_preview_top_surface_lod_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap);
|
||||
auto *minimum_visibility_offset_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_minimum_visibility_offset_checkbox = new wxCheckBox(preview_page, wxID_ANY, _L("Minimum visibility offset"));
|
||||
m_minimum_visibility_offset_checkbox->SetValue(minimum_visibility_offset_enabled);
|
||||
@@ -2872,6 +2900,7 @@ public:
|
||||
bool force_sequential_filaments() const { return m_force_sequential_filaments_checkbox && m_force_sequential_filaments_checkbox->GetValue(); }
|
||||
bool auto_adjust_filament_selection() const { return m_auto_adjust_filament_selection_checkbox == nullptr || m_auto_adjust_filament_selection_checkbox->GetValue(); }
|
||||
bool preview_limit_resolution() const { return m_preview_limit_resolution_checkbox == nullptr || m_preview_limit_resolution_checkbox->GetValue(); }
|
||||
bool preview_simulate_top_surface_lod() const { return m_preview_top_surface_lod_checkbox != nullptr && m_preview_top_surface_lod_checkbox->GetValue(); }
|
||||
bool reduce_outer_surface_texture() const { return false; }
|
||||
bool seam_hiding() const { return m_seam_hiding_checkbox && m_seam_hiding_checkbox->GetValue(); }
|
||||
bool nonlinear_offset_adjustment() const { return m_nonlinear_offset_adjustment_checkbox && m_nonlinear_offset_adjustment_checkbox->GetValue(); }
|
||||
@@ -3131,6 +3160,9 @@ public:
|
||||
TextureMappingGlobalSettings global_settings() const
|
||||
{
|
||||
TextureMappingGlobalSettings settings = m_global_settings;
|
||||
settings.preview_opacity_pct = preview_opacity_pct();
|
||||
settings.preview_limit_resolution = preview_limit_resolution();
|
||||
settings.preview_simulate_top_surface_lod = preview_simulate_top_surface_lod();
|
||||
settings.enabled = m_prime_tower_mapping_enabled_checkbox != nullptr && m_prime_tower_mapping_enabled_checkbox->GetValue();
|
||||
settings.preserve_aspect_ratio =
|
||||
m_prime_tower_preserve_aspect_ratio_checkbox != nullptr && m_prime_tower_preserve_aspect_ratio_checkbox->GetValue();
|
||||
@@ -3612,6 +3644,7 @@ private:
|
||||
wxCheckBox *m_force_sequential_filaments_checkbox {nullptr};
|
||||
wxCheckBox *m_auto_adjust_filament_selection_checkbox {nullptr};
|
||||
wxCheckBox *m_preview_limit_resolution_checkbox {nullptr};
|
||||
wxCheckBox *m_preview_top_surface_lod_checkbox {nullptr};
|
||||
wxCheckBox *m_reduce_outer_surface_texture_checkbox {nullptr};
|
||||
wxCheckBox *m_seam_hiding_checkbox {nullptr};
|
||||
wxCheckBox *m_nonlinear_offset_adjustment_checkbox {nullptr};
|
||||
@@ -5633,6 +5666,15 @@ Sidebar::Sidebar(Plater *parent)
|
||||
opt->value = serialized;
|
||||
else
|
||||
bundle->project_config.set_key_value("texture_mapping_definitions", new ConfigOptionString(serialized));
|
||||
const std::string global_serialized = bundle->texture_mapping_global_settings.serialize();
|
||||
if (ConfigOptionString *opt = print_cfg->option<ConfigOptionString>("texture_mapping_global_settings"))
|
||||
opt->value = global_serialized;
|
||||
else
|
||||
print_cfg->set_key_value("texture_mapping_global_settings", new ConfigOptionString(global_serialized));
|
||||
if (ConfigOptionString *opt = bundle->project_config.option<ConfigOptionString>("texture_mapping_global_settings"))
|
||||
opt->value = global_serialized;
|
||||
else
|
||||
bundle->project_config.set_key_value("texture_mapping_global_settings", new ConfigOptionString(global_serialized));
|
||||
if (auto *print_tab = wxGetApp().get_tab(Preset::TYPE_PRINT))
|
||||
print_tab->update_dirty();
|
||||
if (wxGetApp().plater() != nullptr)
|
||||
@@ -5654,6 +5696,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
bundle->project_config.opt_string("texture_mapping_definitions") :
|
||||
std::string();
|
||||
bundle->texture_mapping_zones.load_entries(serialized, colors);
|
||||
bundle->texture_mapping_global_settings.load(bundle->project_config.opt_string("texture_mapping_global_settings"));
|
||||
bundle->texture_mapping_zones.add_zone(colors.size(),
|
||||
colors,
|
||||
colors.size() < 2 ? int(TextureMappingZone::LinearGradient) : int(TextureMappingZone::ImageTexture));
|
||||
@@ -7549,13 +7592,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
auto is_preview_only_texture_row_change = [](const TextureMappingZone &before, const TextureMappingZone &after) {
|
||||
TextureMappingZone before_gcode = before;
|
||||
TextureMappingZone after_gcode = after;
|
||||
before_gcode.preview_opacity_pct = TextureMappingZone::DefaultPreviewOpacityPct;
|
||||
before_gcode.preview_simulate_colors = TextureMappingZone::DefaultPreviewSimulateColors;
|
||||
before_gcode.preview_limit_resolution = TextureMappingZone::DefaultPreviewLimitResolution;
|
||||
before_gcode.show_linear_gradient_direction_arrow = false;
|
||||
after_gcode.preview_opacity_pct = TextureMappingZone::DefaultPreviewOpacityPct;
|
||||
after_gcode.preview_simulate_colors = TextureMappingZone::DefaultPreviewSimulateColors;
|
||||
after_gcode.preview_limit_resolution = TextureMappingZone::DefaultPreviewLimitResolution;
|
||||
after_gcode.show_linear_gradient_direction_arrow = false;
|
||||
return before != after && before_gcode == after_gcode;
|
||||
};
|
||||
@@ -7634,6 +7671,19 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
notify_change(affects_scene);
|
||||
};
|
||||
|
||||
auto persist_preview_simulate_colors = [this, bundle, set_config_string, notify_change, refresh_texture_mapping_preview](bool value) {
|
||||
if (bundle == nullptr)
|
||||
return;
|
||||
const bool changed = bundle->texture_mapping_global_settings.preview_simulate_colors != value;
|
||||
bundle->texture_mapping_global_settings.preview_simulate_colors = value;
|
||||
set_config_string("texture_mapping_global_settings", bundle->texture_mapping_global_settings.serialize());
|
||||
if (changed) {
|
||||
notify_change(false);
|
||||
refresh_texture_mapping_preview();
|
||||
CallAfter([this]() { update_texture_mapping_panel(false); });
|
||||
}
|
||||
};
|
||||
|
||||
for (const size_t zone_index : visible_zone_indices) {
|
||||
if (zone_index >= zones.size())
|
||||
continue;
|
||||
@@ -7994,7 +8044,10 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
editor_sizer->Add(contrast_row, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap);
|
||||
|
||||
::CheckBox *preview_colors_chk = nullptr;
|
||||
auto *preview_colors_row = make_sidebar_checkbox_row(editor, preview_colors_chk, _L("Preview Result Colors"), entry.preview_simulate_colors);
|
||||
auto *preview_colors_row = make_sidebar_checkbox_row(editor,
|
||||
preview_colors_chk,
|
||||
_L("Preview Result Colors"),
|
||||
bundle->texture_mapping_global_settings.preview_simulate_colors);
|
||||
editor_sizer->Add(preview_colors_row, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap);
|
||||
|
||||
auto *button_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
@@ -8008,7 +8061,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
auto apply_controls = [zone_index, mgr_ptr, num_physical, filament_checks, surface_choice,
|
||||
linear_gradient_stops_bar, linear_gradient_mode_choice, linear_gradient_radius_spin,
|
||||
linear_gradient_radius_percent_chk,
|
||||
surface_pattern_from_selection, linear_gradient_mode_from_selection, mode_choice, preview_colors_chk,
|
||||
surface_pattern_from_selection, linear_gradient_mode_from_selection, mode_choice,
|
||||
show_direction_arrow_chk, contrast_spin, apply_zone]() {
|
||||
if (mgr_ptr == nullptr)
|
||||
return;
|
||||
@@ -8058,8 +8111,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.filament_color_mode = mode_choice != nullptr ?
|
||||
texture_mapping_color_mode_from_selection(mode_choice->GetSelection(), updated.filament_color_mode) :
|
||||
updated.filament_color_mode;
|
||||
updated.preview_simulate_colors =
|
||||
updated.is_image_texture() && preview_colors_chk != nullptr && preview_colors_chk->GetValue();
|
||||
updated.show_linear_gradient_direction_arrow = show_direction_arrow_chk != nullptr && show_direction_arrow_chk->GetValue();
|
||||
updated.contrast_pct = contrast_spin != nullptr ? std::clamp(float(contrast_spin->GetValue()), 25.f, 300.f) : updated.contrast_pct;
|
||||
updated.high_resolution_sampling = true;
|
||||
@@ -8174,7 +8225,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
linear_gradient_mode_from_selection,
|
||||
mode_choice,
|
||||
surface_choice,
|
||||
preview_colors_chk,
|
||||
contrast_spin,
|
||||
set_sidebar_checkbox_value,
|
||||
surface_pattern_from_selection,
|
||||
@@ -8235,8 +8285,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.filament_color_mode = mode_choice != nullptr ?
|
||||
texture_mapping_color_mode_from_selection(mode_choice->GetSelection(), updated.filament_color_mode) :
|
||||
updated.filament_color_mode;
|
||||
updated.preview_simulate_colors =
|
||||
updated.is_image_texture() && preview_colors_chk != nullptr && preview_colors_chk->GetValue();
|
||||
updated.contrast_pct = contrast_spin != nullptr ? std::clamp(float(contrast_spin->GetValue()), 25.f, 300.f) : updated.contrast_pct;
|
||||
updated.high_resolution_sampling = true;
|
||||
|
||||
@@ -8264,8 +8312,9 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
apply_zone(std::move(updated));
|
||||
};
|
||||
mode_choice->Bind(wxEVT_COMBOBOX, on_mode_choice);
|
||||
preview_colors_chk->Bind(wxEVT_TOGGLEBUTTON, [apply_controls](wxCommandEvent &evt) {
|
||||
apply_controls();
|
||||
preview_colors_chk->Bind(wxEVT_TOGGLEBUTTON, [preview_colors_chk, persist_preview_simulate_colors](wxCommandEvent &evt) {
|
||||
if (preview_colors_chk != nullptr)
|
||||
persist_preview_simulate_colors(preview_colors_chk->GetValue());
|
||||
evt.Skip();
|
||||
});
|
||||
if (show_direction_arrow_chk != nullptr)
|
||||
@@ -8621,10 +8670,8 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
transmission_distances,
|
||||
updated.transmission_distance_calibration_mode,
|
||||
updated.tone_gamma,
|
||||
updated.preview_opacity_pct,
|
||||
updated.force_sequential_filaments,
|
||||
updated.auto_adjust_filament_selection,
|
||||
updated.preview_limit_resolution,
|
||||
updated.reduce_outer_surface_texture,
|
||||
updated.seam_hiding,
|
||||
updated.nonlinear_offset_adjustment,
|
||||
@@ -8682,7 +8729,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.texture_mapping_mode = dlg.texture_mapping_mode();
|
||||
updated.tone_gamma = dlg.tone_gamma();
|
||||
updated.transmission_distance_calibration_mode = dlg.transmission_distance_calibration_mode();
|
||||
updated.preview_opacity_pct = dlg.preview_opacity_pct();
|
||||
updated.force_sequential_filaments = dlg.force_sequential_filaments();
|
||||
if (updated.force_sequential_filaments && ids.size() >= 2) {
|
||||
updated.component_ids = encode_texture_mapping_component_ids(ids);
|
||||
@@ -8690,7 +8736,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.component_b = ids[1];
|
||||
}
|
||||
updated.auto_adjust_filament_selection = dlg.auto_adjust_filament_selection();
|
||||
updated.preview_limit_resolution = dlg.preview_limit_resolution();
|
||||
updated.reduce_outer_surface_texture = dlg.reduce_outer_surface_texture();
|
||||
updated.seam_hiding = dlg.seam_hiding();
|
||||
updated.nonlinear_offset_adjustment = dlg.nonlinear_offset_adjustment();
|
||||
@@ -8752,8 +8797,18 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
updated.generic_solver_mode = dlg.generic_solver_mode();
|
||||
updated.generic_solver_mix_model = dlg.generic_solver_mix_model();
|
||||
const TextureMappingGlobalSettings dlg_global_settings = dlg.global_settings();
|
||||
auto prime_tower_only_settings = [](TextureMappingGlobalSettings settings) {
|
||||
settings.preview_opacity_pct = TextureMappingZone::DefaultPreviewOpacityPct;
|
||||
settings.preview_simulate_colors = TextureMappingZone::DefaultPreviewSimulateColors;
|
||||
settings.preview_limit_resolution = TextureMappingZone::DefaultPreviewLimitResolution;
|
||||
settings.preview_simulate_top_surface_lod = TextureMappingZone::DefaultPreviewSimulateTopSurfaceLod;
|
||||
return settings.serialize();
|
||||
};
|
||||
const bool global_settings_changed =
|
||||
dlg_global_settings.serialize() != bundle->texture_mapping_global_settings.serialize();
|
||||
const bool prime_tower_settings_changed =
|
||||
prime_tower_only_settings(dlg_global_settings) !=
|
||||
prime_tower_only_settings(bundle->texture_mapping_global_settings);
|
||||
if (global_settings_changed)
|
||||
bundle->texture_mapping_global_settings = dlg_global_settings;
|
||||
Model &model = wxGetApp().model();
|
||||
@@ -8792,10 +8847,10 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
|
||||
std::abs(updated.filament_transmission_distances_mm.back()) <= 1e-6f)
|
||||
updated.filament_transmission_distances_mm.pop_back();
|
||||
const bool affects_scene = apply_zone(std::move(updated));
|
||||
const bool prime_tower_preview_changed = global_settings_changed || prime_tower_images_changed;
|
||||
if (prime_tower_preview_changed)
|
||||
notify_change(true);
|
||||
if (affects_scene || prime_tower_preview_changed)
|
||||
const bool prime_tower_preview_changed = prime_tower_settings_changed || prime_tower_images_changed;
|
||||
if (global_settings_changed || prime_tower_images_changed)
|
||||
notify_change(prime_tower_preview_changed);
|
||||
if (affects_scene || global_settings_changed || prime_tower_images_changed)
|
||||
refresh_texture_mapping_preview();
|
||||
CallAfter([this]() { update_texture_mapping_panel(false); });
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user