Another tweak to reduce edge artifacts (image projection)

This commit is contained in:
sentientstardust
2026-05-06 18:52:02 +01:00
parent 76d5e99483
commit 2343e8ff26
4 changed files with 95 additions and 23 deletions

View File

@@ -3079,11 +3079,14 @@ struct ProjectionVisibility
float top = 0.f;
float scale = 1.f;
std::vector<float> depth;
std::vector<float> local_depth_tolerance;
std::vector<uint64_t> triangle_keys;
};
static constexpr float PROJECTION_VISIBILITY_DEPTH_TOLERANCE = 2e-4f;
static constexpr float PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE = 2e-3f;
static constexpr float PROJECTION_VISIBILITY_PROJECTED_TRIANGLE_DEPTH_TOLERANCE = 2e-3f;
static constexpr float PROJECTION_VISIBILITY_MAX_LOCAL_DEPTH_TOLERANCE = 8e-3f;
static constexpr uint64_t PROJECTION_VISIBILITY_INVALID_TRIANGLE_KEY = std::numeric_limits<uint64_t>::max();
static uint64_t projection_visibility_triangle_key(size_t volume_idx, size_t tri_idx)
@@ -3096,9 +3099,52 @@ static bool projection_visibility_valid(const ProjectionVisibility &visibility)
return visibility.width > 0 &&
visibility.height > 0 &&
visibility.depth.size() == size_t(visibility.width) * size_t(visibility.height) &&
visibility.local_depth_tolerance.size() == visibility.depth.size() &&
visibility.triangle_keys.size() == visibility.depth.size();
}
static void projection_visibility_prepare_local_depth_tolerances(ProjectionVisibility &visibility)
{
visibility.local_depth_tolerance.assign(visibility.depth.size(), PROJECTION_VISIBILITY_DEPTH_TOLERANCE);
if (visibility.width <= 0 || visibility.height <= 0 || visibility.depth.size() != size_t(visibility.width) * size_t(visibility.height))
return;
for (int y = 0; y < visibility.height; ++y) {
for (int x = 0; x < visibility.width; ++x) {
const size_t center_idx = size_t(y) * size_t(visibility.width) + size_t(x);
const float center_nearest = visibility.depth[center_idx];
if (!std::isfinite(center_nearest))
continue;
float tolerance = PROJECTION_VISIBILITY_DEPTH_TOLERANCE;
const int min_x = std::max(0, x - 1);
const int max_x = std::min(visibility.width - 1, x + 1);
const int min_y = std::max(0, y - 1);
const int max_y = std::min(visibility.height - 1, y + 1);
for (int sample_y = min_y; sample_y <= max_y; ++sample_y) {
for (int sample_x = min_x; sample_x <= max_x; ++sample_x) {
const size_t idx = size_t(sample_y) * size_t(visibility.width) + size_t(sample_x);
const float nearest = visibility.depth[idx];
if (std::isfinite(nearest))
tolerance = std::max(tolerance, std::abs(center_nearest - nearest) + PROJECTION_VISIBILITY_DEPTH_TOLERANCE);
}
}
visibility.local_depth_tolerance[center_idx] = std::min(tolerance, PROJECTION_VISIBILITY_MAX_LOCAL_DEPTH_TOLERANCE);
}
}
}
static float projection_visibility_local_depth_tolerance(const ProjectionVisibility &visibility, int x, int y)
{
if (x < 0 || y < 0 || x >= visibility.width || y >= visibility.height)
return PROJECTION_VISIBILITY_DEPTH_TOLERANCE;
const size_t idx = size_t(y) * size_t(visibility.width) + size_t(x);
if (idx >= visibility.local_depth_tolerance.size())
return PROJECTION_VISIBILITY_DEPTH_TOLERANCE;
return visibility.local_depth_tolerance[idx];
}
static bool projection_visibility_depth_matches_sample(const ProjectionVisibility &visibility,
int x,
int y,
@@ -3113,16 +3159,21 @@ static bool projection_visibility_depth_matches_sample(const ProjectionVisibilit
if (!std::isfinite(center_nearest))
return false;
const bool has_triangle_key = triangle_key != PROJECTION_VISIBILITY_INVALID_TRIANGLE_KEY;
const bool center_same_triangle =
triangle_key != PROJECTION_VISIBILITY_INVALID_TRIANGLE_KEY &&
visibility.triangle_keys[center_idx] == triangle_key;
const float center_tolerance =
center_same_triangle ? PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE : PROJECTION_VISIBILITY_DEPTH_TOLERANCE;
has_triangle_key && visibility.triangle_keys[center_idx] == triangle_key;
const float local_tolerance = projection_visibility_local_depth_tolerance(visibility, x, y);
float center_tolerance = PROJECTION_VISIBILITY_DEPTH_TOLERANCE;
if (center_same_triangle) {
center_tolerance = std::max(PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE, local_tolerance);
} else if (has_triangle_key) {
center_tolerance = std::max(PROJECTION_VISIBILITY_PROJECTED_TRIANGLE_DEPTH_TOLERANCE, local_tolerance);
}
if (depth <= center_nearest + center_tolerance)
return true;
if (triangle_key == PROJECTION_VISIBILITY_INVALID_TRIANGLE_KEY ||
depth > center_nearest + PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE)
if (!has_triangle_key ||
depth > center_nearest + std::max(PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE, local_tolerance))
return false;
const int min_x = std::max(0, x - 1);
@@ -3139,7 +3190,10 @@ static bool projection_visibility_depth_matches_sample(const ProjectionVisibilit
continue;
const float nearest = visibility.depth[idx];
if (std::isfinite(nearest) && depth <= nearest + PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE)
const float nearby_tolerance =
std::max(PROJECTION_VISIBILITY_SAME_TRIANGLE_DEPTH_TOLERANCE,
projection_visibility_local_depth_tolerance(visibility, sample_x, sample_y));
if (std::isfinite(nearest) && depth <= nearest + nearby_tolerance)
return true;
}
}
@@ -3242,6 +3296,7 @@ static ProjectionVisibility build_projection_visibility(const ProjectionContext
}
}
projection_visibility_prepare_local_depth_tolerances(visibility);
return visibility;
}
@@ -9227,9 +9282,10 @@ bool GLGizmoImageProjection::project_to_rgb_data(ModelObject *object)
projected_triangles[tri_idx] = projected_triangle;
if (projected_triangle) {
projected_triangle_depths[tri_idx] =
texture_mapping_depth_from_span(projection_triangle_image_pixel_span(context, world_matrix, vertices),
projection_target_span,
7);
std::max(1,
texture_mapping_depth_from_span(projection_triangle_image_pixel_span(context, world_matrix, vertices),
projection_target_span,
7));
++projected_triangle_count;
}
}

View File

@@ -1697,7 +1697,8 @@ void TriangleSelectorPatch::update_render_data()
m_vertex_color_preview_models,
m_vertex_color_preview_colors,
m_vertex_color_preview_filament_ids,
m_texture_mapping_color_preview);
m_texture_mapping_color_preview,
reinterpret_cast<size_t>(this));
} else {
if (model_volume_has_texture_preview_data_for_painting(*m_model_volume)) {
build_mmu_texture_preview_models(*m_model_volume,
@@ -1718,7 +1719,9 @@ void TriangleSelectorPatch::update_render_data()
texture_mgr,
m_vertex_color_preview_models,
m_vertex_color_preview_colors,
m_vertex_color_preview_filament_ids);
m_vertex_color_preview_filament_ids,
nullptr,
reinterpret_cast<size_t>(this));
}
}

View File

@@ -1840,8 +1840,8 @@ bool texture_preview_simulation_is_pending_impl()
}
if (entry->ready_geometry.has_value()) {
pending = true;
if (!entry->ready_generation_reported) {
pending = true;
++texture_preview_vertex_color_simulation_generation();
entry->ready_generation_reported = true;
}
@@ -2461,10 +2461,14 @@ size_t texture_preview_color_facets_source_signature(const ModelVolume
return signature;
}
size_t texture_preview_vertex_color_simulation_cache_key(const ModelVolume &model_volume, unsigned int filament_id, size_t source_kind)
size_t texture_preview_vertex_color_simulation_cache_key(const ModelVolume &model_volume,
unsigned int filament_id,
size_t source_kind,
size_t preview_owner_key)
{
size_t key = texture_preview_simulation_cache_key(model_volume, filament_id);
key ^= std::hash<size_t>{}(source_kind) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
key ^= std::hash<size_t>{}(preview_owner_key) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
return key;
}
@@ -2514,6 +2518,7 @@ bool build_simulated_vertex_color_preview_model_for_state(
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
unsigned int filament_id,
const TexturePreviewSimulationSettings &simulation_settings,
size_t preview_owner_key,
GUI::GLModel &out_model)
{
if (!model_volume_has_vertex_color_preview_data(model_volume) || state_triangles.empty())
@@ -2521,7 +2526,7 @@ bool build_simulated_vertex_color_preview_model_for_state(
const size_t source_signature = texture_preview_vertex_color_source_signature(model_volume, state_triangles);
const size_t simulation_signature = texture_preview_simulation_signature(model_volume, source_signature, simulation_settings);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 1u);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 1u, preview_owner_key);
std::shared_ptr<const TriangleMesh> mesh = model_volume.mesh_ptr();
std::vector<uint32_t> vertex_colors(model_volume.imported_vertex_colors_rgba.begin(), model_volume.imported_vertex_colors_rgba.end());
std::vector<TriangleSelector::FacetStateTriangle> triangles = state_triangles;
@@ -2555,7 +2560,8 @@ bool build_simulated_texture_mapping_color_preview_model_for_state(
unsigned int filament_id,
const TexturePreviewSimulationSettings &simulation_settings,
GUI::GLModel &out_model,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr)
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr,
size_t preview_owner_key = 0)
{
const ColorFacetsAnnotation *color_source = texture_mapping_color_facets_override;
if (color_source == nullptr || color_source->empty())
@@ -2565,7 +2571,7 @@ bool build_simulated_texture_mapping_color_preview_model_for_state(
const size_t source_signature = texture_preview_color_facets_source_signature(model_volume, *color_source, state_triangles);
const size_t simulation_signature = texture_preview_simulation_signature(model_volume, source_signature, simulation_settings);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 2u);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 2u, preview_owner_key);
std::shared_ptr<const TriangleMesh> mesh = model_volume.mesh_ptr();
std::shared_ptr<ColorFacetsAnnotation> color_source_copy = ColorFacetsAnnotation::make_temporary();
color_source_copy->assign(*color_source);
@@ -3195,7 +3201,8 @@ bool build_mmu_vertex_color_preview_models(
std::vector<GUI::GLModel> &out_models,
std::vector<ColorRGBA> &out_colors,
std::vector<unsigned int> &out_filament_ids,
const ColorFacetsAnnotation *texture_mapping_color_facets_override)
const ColorFacetsAnnotation *texture_mapping_color_facets_override,
size_t preview_owner_key)
{
out_models.clear();
out_colors.clear();
@@ -3258,7 +3265,8 @@ bool build_mmu_vertex_color_preview_models(
filament_id,
*simulation_settings,
model,
preview_override))
preview_override,
preview_owner_key))
continue;
} else {
if (!build_texture_mapping_color_preview_model_for_state(model_volume,
@@ -3274,6 +3282,7 @@ bool build_mmu_vertex_color_preview_models(
triangles_per_type[state_id],
filament_id,
*simulation_settings,
preview_owner_key,
model))
continue;
} else {
@@ -3302,7 +3311,8 @@ bool build_mmu_vertex_color_preview_models(
std::vector<GUI::GLModel> &out_models,
std::vector<ColorRGBA> &out_colors,
std::vector<unsigned int> &out_filament_ids,
const ColorFacetsAnnotation *texture_mapping_color_facets_override)
const ColorFacetsAnnotation *texture_mapping_color_facets_override,
size_t preview_owner_key)
{
return build_mmu_vertex_color_preview_models(model_volume,
triangles_per_type,
@@ -3314,7 +3324,8 @@ bool build_mmu_vertex_color_preview_models(
out_models,
out_colors,
out_filament_ids,
texture_mapping_color_facets_override);
texture_mapping_color_facets_override,
preview_owner_key);
}
size_t model_volume_texture_preview_signature(const ModelVolume &model_volume)

View File

@@ -38,7 +38,8 @@ bool build_mmu_vertex_color_preview_models(
std::vector<GUI::GLModel> &out_models,
std::vector<ColorRGBA> &out_colors,
std::vector<unsigned int> &out_filament_ids,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr);
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr,
size_t preview_owner_key = 0);
bool build_mmu_vertex_color_preview_models(
const ModelVolume &model_volume,
@@ -50,7 +51,8 @@ bool build_mmu_vertex_color_preview_models(
std::vector<GUI::GLModel> &out_models,
std::vector<ColorRGBA> &out_colors,
std::vector<unsigned int> &out_filament_ids,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr);
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr,
size_t preview_owner_key = 0);
size_t model_volume_texture_preview_signature(const ModelVolume &model_volume);
size_t model_volume_texture_mapping_color_preview_signature(const ModelVolume &model_volume);