Convert gradients to RGB for areas that don't support raw offset
This commit is contained in:
@@ -1939,10 +1939,10 @@ static std::optional<TopSurfaceImageContoningCellSample> top_surface_image_conto
|
||||
return;
|
||||
}
|
||||
const std::optional<std::array<float, 3>> rgb =
|
||||
sample_weight_field_rgb(context.weight_field,
|
||||
sample_x_mm,
|
||||
sample_y_mm,
|
||||
context.high_resolution_texture_sampling);
|
||||
texture_mapping_offset_target_rgb_at_point(context,
|
||||
sample_x_mm,
|
||||
sample_y_mm,
|
||||
std::numeric_limits<float>::quiet_NaN());
|
||||
if (!rgb)
|
||||
return;
|
||||
out.rgb[0] += (*rgb)[0];
|
||||
@@ -3064,7 +3064,9 @@ static std::vector<TopSurfaceImageRegionPlan> top_surface_image_region_plans(
|
||||
std::vector<std::string> filament_colours = print_config.filament_colour.values;
|
||||
filament_colours.resize(num_physical, "#FFFFFF");
|
||||
std::vector<unsigned int> components =
|
||||
TextureMappingManager::effective_texture_component_ids(*zone, num_physical, filament_colours);
|
||||
zone->is_image_texture() ?
|
||||
TextureMappingManager::effective_texture_component_ids(*zone, num_physical, filament_colours) :
|
||||
TextureMappingManager::selected_component_ids(*zone, num_physical);
|
||||
components.erase(std::remove_if(components.begin(), components.end(), [num_physical](unsigned int id) {
|
||||
return id == 0 || id > num_physical;
|
||||
}), components.end());
|
||||
@@ -4497,10 +4499,10 @@ static ExtrusionPaths top_surface_image_split_path(const ExtrusionPath &path,
|
||||
continue;
|
||||
const Point qm = lerp(p0, p1, 0.5 * (t0 + t1));
|
||||
const std::vector<float> weights =
|
||||
sample_weight_field_components(context.weight_field,
|
||||
unscale<float>(qm.x()),
|
||||
unscale<float>(qm.y()),
|
||||
context.high_resolution_texture_sampling);
|
||||
texture_mapping_offset_component_weights_at_point(context,
|
||||
unscale<float>(qm.x()),
|
||||
unscale<float>(qm.y()),
|
||||
std::numeric_limits<float>::quiet_NaN());
|
||||
const float coverage = context.active_component_idx < weights.size() ?
|
||||
std::clamp(weights[context.active_component_idx], 0.f, 1.f) :
|
||||
0.f;
|
||||
@@ -4582,10 +4584,10 @@ static std::vector<float> top_surface_image_same_layer_fractions(const std::opti
|
||||
if (!context)
|
||||
return fractions;
|
||||
std::vector<float> weights =
|
||||
sample_weight_field_components(context->weight_field,
|
||||
x_mm,
|
||||
y_mm,
|
||||
context->high_resolution_texture_sampling);
|
||||
texture_mapping_offset_component_weights_at_point(*context,
|
||||
x_mm,
|
||||
y_mm,
|
||||
std::numeric_limits<float>::quiet_NaN());
|
||||
if (weights.size() != size_t(component_count))
|
||||
return fractions;
|
||||
fractions.assign(size_t(component_count), 0.f);
|
||||
@@ -6298,9 +6300,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree,
|
||||
std::vector<std::string> filament_colours = print_config.filament_colour.values;
|
||||
filament_colours.resize(print_config.filament_colour.values.size(), "#FFFFFF");
|
||||
std::vector<unsigned int> components =
|
||||
TextureMappingManager::effective_texture_component_ids(*zone,
|
||||
print_config.filament_colour.values.size(),
|
||||
filament_colours);
|
||||
zone->is_image_texture() ?
|
||||
TextureMappingManager::effective_texture_component_ids(*zone,
|
||||
print_config.filament_colour.values.size(),
|
||||
filament_colours) :
|
||||
TextureMappingManager::selected_component_ids(*zone, print_config.filament_colour.values.size());
|
||||
const std::optional<std::array<float, 4>> background =
|
||||
top_surface_image_equal_blend_background(print_config, components);
|
||||
top_surface_image_context =
|
||||
|
||||
@@ -395,7 +395,7 @@ struct TextureMappingZone
|
||||
bool top_surface_image_printing_active() const
|
||||
{
|
||||
return top_surface_image_printing_enabled &&
|
||||
is_image_texture() &&
|
||||
(is_image_texture() || is_surface_gradient()) &&
|
||||
(top_surface_image_printing_method == int(TopSurfaceImageSameAngle45Width) ||
|
||||
top_surface_image_printing_method == int(TopSurfaceImageSameLayer45Partition) ||
|
||||
(top_surface_image_printing_method == int(TopSurfaceImageContoning) &&
|
||||
@@ -404,7 +404,7 @@ struct TextureMappingZone
|
||||
bool top_surface_contoning_active() const
|
||||
{
|
||||
return top_surface_image_printing_enabled &&
|
||||
is_image_texture() &&
|
||||
(is_image_texture() || is_surface_gradient()) &&
|
||||
top_surface_image_printing_method == int(TopSurfaceImageContoning) &&
|
||||
uses_perimeter_path_modulation_v2();
|
||||
}
|
||||
@@ -416,7 +416,8 @@ struct TextureMappingZone
|
||||
}
|
||||
bool top_surface_contoning_perimeters_active() const
|
||||
{
|
||||
return top_surface_contoning_active() &&
|
||||
return is_image_texture() &&
|
||||
top_surface_contoning_active() &&
|
||||
!effective_top_surface_contoning_only_color_surface_infill() &&
|
||||
!effective_top_surface_contoning_replace_top_perimeters_with_infill() &&
|
||||
!effective_top_surface_contoning_recolor_surrounding_perimeters();
|
||||
|
||||
@@ -2823,6 +2823,133 @@ std::optional<float> sample_weight_field_normal_z(const TextureMappingOffsetWeig
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static float texture_mapping_offset_context_sample_z_mm(const TextureMappingOffsetContext &context, float z_mm)
|
||||
{
|
||||
if (std::isfinite(z_mm))
|
||||
return z_mm;
|
||||
if (std::isfinite(context.sample_z_mm))
|
||||
return context.sample_z_mm;
|
||||
if (context.layer != nullptr && std::isfinite(float(context.layer->print_z)))
|
||||
return float(context.layer->print_z);
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
static float texture_mapping_offset_linear_gradient_t_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm)
|
||||
{
|
||||
const Vec3f sample(x_mm, y_mm, texture_mapping_offset_context_sample_z_mm(context, z_mm));
|
||||
if (context.linear_gradient_radial_mode) {
|
||||
const float radius = std::max(0.01f, context.linear_gradient_radius_mm);
|
||||
return clamp01f((sample - context.linear_gradient_start_mm).norm() / radius);
|
||||
}
|
||||
|
||||
const Vec3f gradient_vec = context.linear_gradient_end_mm - context.linear_gradient_start_mm;
|
||||
const float denom = gradient_vec.squaredNorm();
|
||||
return denom > 1e-8f ? clamp01f((sample - context.linear_gradient_start_mm).dot(gradient_vec) / denom) : 0.f;
|
||||
}
|
||||
|
||||
static std::vector<float> texture_mapping_offset_gradient_component_weights_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm,
|
||||
double direction_x,
|
||||
double direction_y)
|
||||
{
|
||||
std::vector<float> weights(context.component_ids.size(), 0.f);
|
||||
if (weights.empty())
|
||||
return weights;
|
||||
|
||||
if (context.linear_gradient_mode) {
|
||||
const float t = texture_mapping_offset_linear_gradient_t_at_point(context, x_mm, y_mm, z_mm);
|
||||
return TextureMappingManager::linear_gradient_compact_weights(t, context.linear_gradient_stops, context.component_ids);
|
||||
}
|
||||
|
||||
if (context.object_center_mode || !std::isfinite(direction_x) || !std::isfinite(direction_y)) {
|
||||
direction_x = double(x_mm) - unscale<double>(context.object_center.x());
|
||||
direction_y = double(y_mm) - unscale<double>(context.object_center.y());
|
||||
}
|
||||
const double direction_len = std::hypot(direction_x, direction_y);
|
||||
if (!std::isfinite(direction_len) || direction_len <= EPSILON) {
|
||||
direction_x = 1.0;
|
||||
direction_y = 0.0;
|
||||
} else {
|
||||
direction_x /= direction_len;
|
||||
direction_y /= direction_len;
|
||||
}
|
||||
|
||||
const float theta_deg =
|
||||
normalize_texture_mapping_offset_angle_deg(float(Geometry::rad2deg(std::atan2(direction_y, direction_x))));
|
||||
const float sample_theta_deg = context.signed_fade_factor < 0.f ?
|
||||
normalize_texture_mapping_offset_angle_deg(theta_deg + 180.f) :
|
||||
theta_deg;
|
||||
|
||||
for (size_t i = 0; i < weights.size(); ++i) {
|
||||
weights[i] = component_angular_influence(context.component_ids[i],
|
||||
sample_theta_deg,
|
||||
context.component_ids,
|
||||
context.rotated_angles);
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
|
||||
std::vector<float> texture_mapping_offset_component_weights_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm)
|
||||
{
|
||||
if (context.vertex_color_match_mode)
|
||||
return sample_weight_field_components(context.weight_field,
|
||||
x_mm,
|
||||
y_mm,
|
||||
context.high_resolution_texture_sampling);
|
||||
|
||||
std::vector<float> weights =
|
||||
texture_mapping_offset_gradient_component_weights_at_point(context,
|
||||
x_mm,
|
||||
y_mm,
|
||||
z_mm,
|
||||
std::numeric_limits<double>::quiet_NaN(),
|
||||
std::numeric_limits<double>::quiet_NaN());
|
||||
if (!context.linear_gradient_mode && context.fade_factor < 1.f - EPSILON)
|
||||
for (float &weight : weights)
|
||||
weight = clamp01f(1.f + (weight - 1.f) * context.fade_factor);
|
||||
return weights;
|
||||
}
|
||||
|
||||
std::optional<std::array<float, 3>> texture_mapping_offset_target_rgb_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm)
|
||||
{
|
||||
if (context.vertex_color_match_mode)
|
||||
return sample_weight_field_rgb(context.weight_field,
|
||||
x_mm,
|
||||
y_mm,
|
||||
context.high_resolution_texture_sampling);
|
||||
|
||||
if (context.component_colors.empty() || context.component_colors.size() != context.component_ids.size())
|
||||
return std::nullopt;
|
||||
|
||||
std::vector<float> weights = texture_mapping_offset_component_weights_at_point(context, x_mm, y_mm, z_mm);
|
||||
if (weights.empty())
|
||||
return std::nullopt;
|
||||
bool has_weight = false;
|
||||
for (const float weight : weights) {
|
||||
if (std::isfinite(weight) && weight > EPSILON) {
|
||||
has_weight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_weight)
|
||||
weights.assign(context.component_colors.size(), 1.f);
|
||||
|
||||
const std::array<float, 3> rgb =
|
||||
mix_color_solver_components(context.component_colors, weights, ColorSolverMixModel::PigmentPainter);
|
||||
return std::array<float, 3>{ clamp01f(rgb[0]), clamp01f(rgb[1]), clamp01f(rgb[2]) };
|
||||
}
|
||||
|
||||
std::vector<unsigned int> decode_texture_mapping_offset_component_ids(const TextureMappingZone &zone, size_t num_physical)
|
||||
{
|
||||
if (zone.is_linear_gradient())
|
||||
@@ -3203,6 +3330,7 @@ std::optional<TextureMappingOffsetContext> build_texture_mapping_offset_context_
|
||||
context.active_component_id = active_component_id;
|
||||
context.active_component_idx = active_component_idx;
|
||||
context.component_ids = std::move(component_ids);
|
||||
context.component_colors = std::move(component_colors);
|
||||
if (linear_gradient_mode)
|
||||
context.linear_gradient_stops = TextureMappingManager::normalized_linear_gradient_stops(zone, num_physical);
|
||||
context.component_distances_mm = std::move(distances_mm);
|
||||
@@ -3226,6 +3354,7 @@ std::optional<TextureMappingOffsetContext> build_texture_mapping_offset_context_
|
||||
transmission_distance_width_factor(td_calibration_context, active_component_idx, previous_component_idx);
|
||||
context.base_outer_width_mm = base_outer_width_mm;
|
||||
context.layer_height_mm = layer_height_mm;
|
||||
context.sample_z_mm = sample_z_mm;
|
||||
context.layer = &layer;
|
||||
return context;
|
||||
}
|
||||
@@ -3295,61 +3424,31 @@ float texture_mapping_offset_surface_inset_mm(const TextureMappingOffsetContext
|
||||
}
|
||||
inset_strength = std::clamp(1.f - desired_strength, 0.f, 1.f);
|
||||
} else if (context.linear_gradient_mode) {
|
||||
float t = 0.f;
|
||||
float z_mm = context.layer != nullptr ? float(context.layer->print_z) : 0.f;
|
||||
if (std::isfinite(surface_v_mm))
|
||||
z_mm = surface_v_mm;
|
||||
if (!std::isfinite(z_mm))
|
||||
z_mm = 0.f;
|
||||
const Vec3f sample(unscale<float>(point.x()), unscale<float>(point.y()), z_mm);
|
||||
if (context.linear_gradient_radial_mode) {
|
||||
const float radius = std::max(0.01f, context.linear_gradient_radius_mm);
|
||||
t = clamp01f((sample - context.linear_gradient_start_mm).norm() / radius);
|
||||
} else {
|
||||
const Vec3f gradient_vec = context.linear_gradient_end_mm - context.linear_gradient_start_mm;
|
||||
const float denom = gradient_vec.squaredNorm();
|
||||
if (denom > 1e-8f)
|
||||
t = clamp01f((sample - context.linear_gradient_start_mm).dot(gradient_vec) / denom);
|
||||
}
|
||||
if (context.linear_gradient_radial_mode || (context.linear_gradient_end_mm - context.linear_gradient_start_mm).squaredNorm() > 1e-8f) {
|
||||
const std::vector<float> weights =
|
||||
TextureMappingManager::linear_gradient_compact_weights(t, context.linear_gradient_stops, context.component_ids);
|
||||
const float desired_strength = context.active_component_idx < weights.size() ?
|
||||
clamp01f(weights[context.active_component_idx]) :
|
||||
0.f;
|
||||
inset_strength = std::clamp(1.f - desired_strength, 0.f, 1.f);
|
||||
} else {
|
||||
inset_strength = 0.f;
|
||||
}
|
||||
const std::vector<float> weights =
|
||||
texture_mapping_offset_gradient_component_weights_at_point(context,
|
||||
unscale<float>(point.x()),
|
||||
unscale<float>(point.y()),
|
||||
surface_v_mm,
|
||||
outward_x,
|
||||
outward_y);
|
||||
const float desired_strength = context.active_component_idx < weights.size() ?
|
||||
clamp01f(weights[context.active_component_idx]) :
|
||||
0.f;
|
||||
inset_strength = std::clamp(1.f - desired_strength, 0.f, 1.f);
|
||||
} else {
|
||||
double theta_direction_x = outward_x;
|
||||
double theta_direction_y = outward_y;
|
||||
if (context.object_center_mode) {
|
||||
const double radial_x = double(point.x()) - double(context.object_center.x());
|
||||
const double radial_y = double(point.y()) - double(context.object_center.y());
|
||||
const double radial_len = std::hypot(radial_x, radial_y);
|
||||
if (radial_len > EPSILON) {
|
||||
theta_direction_x = radial_x / radial_len;
|
||||
theta_direction_y = radial_y / radial_len;
|
||||
}
|
||||
}
|
||||
|
||||
const float theta_deg =
|
||||
normalize_texture_mapping_offset_angle_deg(float(Geometry::rad2deg(std::atan2(theta_direction_y, theta_direction_x))));
|
||||
const float sample_theta_deg = context.signed_fade_factor < 0.f ?
|
||||
normalize_texture_mapping_offset_angle_deg(theta_deg + 180.f) :
|
||||
theta_deg;
|
||||
const std::vector<float> weights =
|
||||
texture_mapping_offset_gradient_component_weights_at_point(context,
|
||||
unscale<float>(point.x()),
|
||||
unscale<float>(point.y()),
|
||||
surface_v_mm,
|
||||
outward_x,
|
||||
outward_y);
|
||||
float raw_inset_mm = 0.f;
|
||||
const size_t component_count = std::min(context.component_ids.size(), context.component_distances_mm.size());
|
||||
const size_t component_count = std::min(weights.size(), context.component_distances_mm.size());
|
||||
for (size_t i = 0; i < component_count; ++i) {
|
||||
if (i == context.active_component_idx)
|
||||
continue;
|
||||
const float influence =
|
||||
component_angular_influence(context.component_ids[i],
|
||||
sample_theta_deg,
|
||||
context.component_ids,
|
||||
context.rotated_angles);
|
||||
raw_inset_mm += context.component_distances_mm[i] * influence;
|
||||
raw_inset_mm += context.component_distances_mm[i] * weights[i];
|
||||
}
|
||||
inset_strength = std::clamp(raw_inset_mm / std::max(context.inset_strength_reference_mm, float(EPSILON)), 0.f, 1.f);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ struct TextureMappingOffsetContext {
|
||||
unsigned int active_component_id { 0 };
|
||||
size_t active_component_idx { size_t(-1) };
|
||||
std::vector<unsigned int> component_ids;
|
||||
std::vector<std::array<float, 3>> component_colors;
|
||||
std::vector<float> component_distances_mm;
|
||||
std::vector<float> rotated_angles;
|
||||
TextureMappingOffsetWeightField weight_field;
|
||||
@@ -87,6 +88,7 @@ struct TextureMappingOffsetContext {
|
||||
float active_component_td_width_factor { 1.f };
|
||||
float base_outer_width_mm { 0.f };
|
||||
float layer_height_mm { 0.f };
|
||||
float sample_z_mm { std::numeric_limits<float>::quiet_NaN() };
|
||||
const Layer *layer { nullptr };
|
||||
};
|
||||
|
||||
@@ -124,6 +126,16 @@ std::optional<float> sample_weight_field_normal_z(const TextureMappingOffsetWeig
|
||||
float y_mm,
|
||||
bool high_resolution_texture_sampling);
|
||||
|
||||
std::vector<float> texture_mapping_offset_component_weights_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm);
|
||||
|
||||
std::optional<std::array<float, 3>> texture_mapping_offset_target_rgb_at_point(const TextureMappingOffsetContext &context,
|
||||
float x_mm,
|
||||
float y_mm,
|
||||
float z_mm);
|
||||
|
||||
float texture_mapping_offset_surface_inset_mm(const TextureMappingOffsetContext &context,
|
||||
const Point &point,
|
||||
double inward_x,
|
||||
|
||||
Reference in New Issue
Block a user