mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-02 13:20:59 +00:00
Warn about the texture bake budget only when it cost detail
Meeting the triangle budget by merging flat faces alone no longer raises the warning, and the warning now quotes the budget instead of the triangle count left after the flat faces were merged.
This commit is contained in:
@@ -478,6 +478,8 @@ DecimateResult decimate(const TriSoup &geometry, size_t target_triangles, bool h
|
|||||||
const Vec3d target = collapse_target(v1, v2).cast<float>().cast<double>();
|
const Vec3d target = collapse_target(v1, v2).cast<float>().cast<double>();
|
||||||
if (check_flipped(v1, v2, target) || check_flipped(v2, v1, target))
|
if (check_flipped(v1, v2, target) || check_flipped(v2, v1, target))
|
||||||
continue;
|
continue;
|
||||||
|
if (!reached_target && top.cost > harvest_ceil)
|
||||||
|
result.target_cost_detail = true;
|
||||||
|
|
||||||
// v1 survives at the new position, v2 goes.
|
// v1 survives at the new position, v2 goes.
|
||||||
pos[size_t(v1)] = target;
|
pos[size_t(v1)] = target;
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ struct DecimateResult
|
|||||||
// The locked faces alone met the target, so it was unreachable without touching preserved
|
// The locked faces alone met the target, so it was unreachable without touching preserved
|
||||||
// geometry.
|
// geometry.
|
||||||
bool locked_over_budget = false;
|
bool locked_over_budget = false;
|
||||||
|
// Reaching the target took a collapse costing more than harvest_tol, so the target removed detail
|
||||||
|
// and not only flat faces a harvest would have taken anyway.
|
||||||
|
bool target_cost_detail = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// `locked_faces`: one entry per input triangle; a vertex touching one may neither move nor be
|
// `locked_faces`: one entry per input triangle; a vertex touching one may neither move nor be
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ PipelineResult run_pipeline(const TriSoup &input, const HeightSampleFn &sample,
|
|||||||
settings.harvest_tol, locked,
|
settings.harvest_tol, locked,
|
||||||
[&](double f) { return report("decimate", f); }, face_color);
|
[&](double f) { return report("decimate", f); }, face_color);
|
||||||
result.locked_over_budget = dec.locked_over_budget;
|
result.locked_over_budget = dec.locked_over_budget;
|
||||||
|
result.budget_limited = result.simplified = dec.target_cost_detail;
|
||||||
displaced = std::move(dec.geometry);
|
displaced = std::move(dec.geometry);
|
||||||
lap("decimate", displaced, over_budget ? "over budget, simplified" : "flat faces harvested");
|
lap("decimate", displaced, over_budget ? "over budget, simplified" : "flat faces harvested");
|
||||||
BOOST_LOG_TRIVIAL(info) << "TextureBake decimate: " << before << " -> " << displaced.triangle_count()
|
BOOST_LOG_TRIVIAL(info) << "TextureBake decimate: " << before << " -> " << displaced.triangle_count()
|
||||||
@@ -349,8 +350,6 @@ PipelineResult run_pipeline(const TriSoup &input, const HeightSampleFn &sample,
|
|||||||
}
|
}
|
||||||
result.triangles_refined = displaced_before_decimate;
|
result.triangles_refined = displaced_before_decimate;
|
||||||
result.triangles_budget = target;
|
result.triangles_budget = target;
|
||||||
result.budget_limited = over_budget;
|
|
||||||
result.simplified = over_budget;
|
|
||||||
if (!report("decimate", 1.0)) {
|
if (!report("decimate", 1.0)) {
|
||||||
result.canceled = true;
|
result.canceled = true;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -110,8 +110,9 @@ struct PipelineResult
|
|||||||
size_t collapse_count = 0;
|
size_t collapse_count = 0;
|
||||||
bool canceled = false;
|
bool canceled = false;
|
||||||
// What the refinement produced, before decimation, and the count it had to fit into (the budget
|
// What the refinement produced, before decimation, and the count it had to fit into (the budget
|
||||||
// plus the preserved geometry). budget_limited says the refined mesh did not fit: the result
|
// plus the preserved geometry). budget_limited says the refined mesh did not fit without collapsing
|
||||||
// carries less of the texture than the resolution asked for, which is what a caller warns about.
|
// more than flat faces: the result carries less of the texture than the resolution asked for,
|
||||||
|
// which is what a caller warns about.
|
||||||
size_t triangles_refined = 0;
|
size_t triangles_refined = 0;
|
||||||
size_t triangles_budget = 0;
|
size_t triangles_budget = 0;
|
||||||
bool budget_limited = false;
|
bool budget_limited = false;
|
||||||
|
|||||||
@@ -2291,7 +2291,6 @@ indexed_triangle_set build_texture_displacement_v2(const indexed_triangle_set
|
|||||||
|
|
||||||
if (stats != nullptr) {
|
if (stats != nullptr) {
|
||||||
stats->triangles_refined = result.triangles_refined;
|
stats->triangles_refined = result.triangles_refined;
|
||||||
stats->triangles_out = result.geometry.triangle_count();
|
|
||||||
stats->triangles_budget = result.triangles_budget;
|
stats->triangles_budget = result.triangles_budget;
|
||||||
stats->budget_limited = result.budget_limited;
|
stats->budget_limited = result.budget_limited;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -824,14 +824,13 @@ void merge_small_color_regions(const indexed_triangle_set &mesh, std::vector<int
|
|||||||
// classic path moves the vertices the mesh already has and has nothing to say here.
|
// classic path moves the vertices the mesh already has and has nothing to say here.
|
||||||
struct TextureBakeStats
|
struct TextureBakeStats
|
||||||
{
|
{
|
||||||
// What the refinement produced, before simplification, and what the bake committed.
|
// What the refinement produced, before simplification.
|
||||||
size_t triangles_refined = 0;
|
size_t triangles_refined = 0;
|
||||||
size_t triangles_out = 0;
|
|
||||||
// What the result had to fit into: the budget for what this bake refines, plus the triangles it
|
// What the result had to fit into: the budget for what this bake refines, plus the triangles it
|
||||||
// only preserves (an earlier bake's relief, which this one does not paint).
|
// only preserves (an earlier bake's relief, which this one does not paint).
|
||||||
size_t triangles_budget = 0;
|
size_t triangles_budget = 0;
|
||||||
// The refined mesh did not fit, so the simplification had to take detail out of it to make it:
|
// The refined mesh did not fit, and removing its flat faces was not enough, so the simplification
|
||||||
// the result carries less of the texture than the chosen resolution asked for.
|
// had to take detail out of it: the result carries less of the texture than the resolution asked for.
|
||||||
bool budget_limited = false;
|
bool budget_limited = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ void TextureDisplacementBakeJob::finalize(bool canceled, std::exception_ptr &ept
|
|||||||
NotificationType::CustomNotification, NotificationManager::NotificationLevel::WarningNotificationLevel,
|
NotificationType::CustomNotification, NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||||
Slic3r::format(_u8L("The triangle budget limited the detail: this resolution needs %1% triangles, "
|
Slic3r::format(_u8L("The triangle budget limited the detail: this resolution needs %1% triangles, "
|
||||||
"the budget kept %2%. Raise Budget or use a coarser Resolution for the full detail."),
|
"the budget kept %2%. Raise Budget or use a coarser Resolution for the full detail."),
|
||||||
count(m_stats.triangles_refined), count(m_stats.triangles_out)));
|
count(m_stats.triangles_refined), count(m_stats.triangles_budget)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include "libslic3r/TextureDisplacement.hpp"
|
#include "libslic3r/TextureDisplacement.hpp"
|
||||||
|
#include "libslic3r/TextureBake/TextureBakeDecimate.hpp"
|
||||||
#include "libslic3r/TextureBake/TextureBakeFlip.hpp"
|
#include "libslic3r/TextureBake/TextureBakeFlip.hpp"
|
||||||
#include "libslic3r/TextureBake/TextureBakeMesh.hpp"
|
#include "libslic3r/TextureBake/TextureBakeMesh.hpp"
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
@@ -2013,3 +2014,21 @@ TEST_CASE("Each layer's texture is sampled only on its own painted area", "[Text
|
|||||||
CHECK_THAT(both(on_side, -Vec3f::UnitX()), WithinAbs(side_only(on_side, -Vec3f::UnitX()), 1e-5f));
|
CHECK_THAT(both(on_side, -Vec3f::UnitX()), WithinAbs(side_only(on_side, -Vec3f::UnitX()), 1e-5f));
|
||||||
CHECK_THAT(both(unpainted, Vec3f::UnitY()), WithinAbs(0.f, 1e-6f));
|
CHECK_THAT(both(unpainted, Vec3f::UnitY()), WithinAbs(0.f, 1e-6f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A budget met by collapsing flat faces alone removes no detail", "[TextureDisplacement]")
|
||||||
|
{
|
||||||
|
// 12 * 4^5 = 12288 triangles on six flat faces, which can go down to 12 without moving the surface.
|
||||||
|
const TextureBake::TriSoup cube = TextureBake::to_soup(subdivide_mesh_uniform(its_make_cube(20., 20., 20.), 0.f, 5));
|
||||||
|
const TextureBake::DecimateResult res = TextureBake::decimate(cube, 1000, true, 0.005);
|
||||||
|
CHECK(res.geometry.triangle_count() <= 1000);
|
||||||
|
CHECK_FALSE(res.target_cost_detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A budget met only by flattening curvature removes detail", "[TextureDisplacement]")
|
||||||
|
{
|
||||||
|
// A 10 degree sphere of radius 10 bulges about 0.04 mm out of each facet, far past a 0.005 mm tolerance.
|
||||||
|
const TextureBake::TriSoup sphere = TextureBake::to_soup(its_make_sphere(10., PI / 18.));
|
||||||
|
const TextureBake::DecimateResult res = TextureBake::decimate(sphere, 100, true, 0.005);
|
||||||
|
CHECK(res.geometry.triangle_count() <= 100);
|
||||||
|
CHECK(res.target_cost_detail);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user