Introduce a new seam alignment option: Aligned back (#10255)

* Introduce a new seam alignment option: spAlignedBack.
This commit is contained in:
SoftFever
2025-07-29 21:11:35 +08:00
committed by GitHub
parent 4cdbe5fa30
commit 8f3ed9bc7b
3 changed files with 22 additions and 12 deletions

View File

@@ -128,7 +128,8 @@ Vec3f sample_power_cosine_hemisphere(const Vec2f &samples, float power) {
std::vector<float> raycast_visibility(const AABBTreeIndirect::Tree<3, float> &raycasting_tree,
const indexed_triangle_set &triangles,
const TriangleSetSamples &samples,
size_t negative_volumes_start_index) {
size_t negative_volumes_start_index,
SeamPosition seam_position = spAligned) {
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: raycast visibility of " << samples.positions.size() << " samples over " << triangles.indices.size()
<< " triangles: end";
@@ -151,7 +152,7 @@ std::vector<float> raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra
std::vector<float> result(samples.positions.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, result.size()),
[&triangles, &precomputed_sample_directions, model_contains_negative_parts, negative_volumes_start_index,
&raycasting_tree, &result, &samples](tbb::blocked_range<size_t> r) {
&raycasting_tree, &result, &samples, seam_position](tbb::blocked_range<size_t> r) {
// Maintaining hits memory outside of the loop, so it does not have to be reallocated for each query.
std::vector<igl::Hit> hits;
for (size_t s_idx = r.begin(); s_idx < r.end(); ++s_idx) {
@@ -161,6 +162,11 @@ std::vector<float> raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra
const Vec3f &center = samples.positions[s_idx];
const Vec3f &normal = samples.normals[s_idx];
if (seam_position == spAlignedBack) {
const float front_adjustment = std::clamp((normal.dot(Vec3f(0.0f, -1.0f, 0.0f)) + 1.2f) * 0.5f, 0.0f, 1.0f);
result[s_idx] += front_adjustment;
}
// apply the local direction via Frame struct - the local_dir is with respect to +Z being forward
Frame f;
f.set_from_z(normal);
@@ -617,7 +623,8 @@ std::pair<size_t, size_t> find_previous_and_next_perimeter_point(const std::vect
// Computes all global model info - transforms object, performs raycasting
void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po,
std::function<void(void)> throw_if_canceled) {
std::function<void(void)> throw_if_canceled,
SeamPosition seam_position = spAligned) {
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: gather occlusion meshes: start";
auto obj_transform = po->trafo_centered();
@@ -692,7 +699,7 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po,
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: build AABB tree: end";
result.mesh_samples_visibility = raycast_visibility(raycasting_tree, triangle_set, result.mesh_samples,
negative_volumes_start_index);
negative_volumes_start_index, seam_position);
throw_if_canceled();
#ifdef DEBUG_FILES
result.debug_export(triangle_set);
@@ -741,7 +748,7 @@ struct SeamComparator {
// should return if a is better seamCandidate than b
bool is_first_better(const SeamCandidate &a, const SeamCandidate &b, const Vec2f &preffered_location = Vec2f { 0.0f,
0.0f }) const {
if (setup == SeamPosition::spAligned && a.central_enforcer != b.central_enforcer) {
if ((setup == SeamPosition::spAligned || setup == SeamPosition::spAlignedBack) && a.central_enforcer != b.central_enforcer) {
return a.central_enforcer;
}
@@ -790,7 +797,7 @@ struct SeamComparator {
// Also used by the random seam generator.
bool is_first_not_much_worse(const SeamCandidate &a, const SeamCandidate &b) const {
// Blockers/Enforcers discrimination, top priority
if (setup == SeamPosition::spAligned && a.central_enforcer != b.central_enforcer) {
if ((setup == SeamPosition::spAligned || setup == SeamPosition::spAlignedBack) && a.central_enforcer != b.central_enforcer) {
// Prefer centers of enforcers.
return a.central_enforcer;
}
@@ -1426,8 +1433,8 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
GlobalModelInfo global_model_info { };
gather_enforcers_blockers(global_model_info, po);
throw_if_canceled_func();
if (configured_seam_preference == spAligned || configured_seam_preference == spNearest) {
compute_global_occlusion(global_model_info, po, throw_if_canceled_func);
if (configured_seam_preference == spAligned || configured_seam_preference == spNearest || configured_seam_preference == spAlignedBack) {
compute_global_occlusion(global_model_info, po, throw_if_canceled_func, configured_seam_preference);
}
throw_if_canceled_func();
BOOST_LOG_TRIVIAL(debug)
@@ -1436,7 +1443,7 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: gather_seam_candidates: end";
throw_if_canceled_func();
if (configured_seam_preference == spAligned || configured_seam_preference == spNearest) {
if (configured_seam_preference == spAligned || configured_seam_preference == spNearest || configured_seam_preference == spAlignedBack) {
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: calculate_candidates_visibility : start";
calculate_candidates_visibility(po, global_model_info);
@@ -1472,7 +1479,7 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
<< "SeamPlacer: pick_seam_point : end";
}
throw_if_canceled_func();
if (configured_seam_preference == spAligned || configured_seam_preference == spRear) {
if (configured_seam_preference == spAligned || configured_seam_preference == spRear || configured_seam_preference == spAlignedBack) {
BOOST_LOG_TRIVIAL(debug)
<< "SeamPlacer: align_seam_points : start";
align_seam_points(po, comparator);

View File

@@ -270,8 +270,9 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportType)
static t_config_enum_values s_keys_map_SeamPosition {
{ "nearest", spNearest },
{ "aligned", spAligned },
{ "aligned_back", spAlignedBack },
{ "back", spRear },
{ "random", spRandom },
{ "random", spRandom }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamPosition)
@@ -4365,10 +4366,12 @@ void PrintConfigDef::init_fff_params()
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values();
def->enum_values.push_back("nearest");
def->enum_values.push_back("aligned");
def->enum_values.push_back("aligned_back");
def->enum_values.push_back("back");
def->enum_values.push_back("random");
def->enum_labels.push_back(L("Nearest"));
def->enum_labels.push_back(L("Aligned"));
def->enum_labels.push_back(L("Aligned back"));
def->enum_labels.push_back(L("Back"));
def->enum_labels.push_back(L("Random"));
def->mode = comSimple;

View File

@@ -176,7 +176,7 @@ inline bool is_auto(SupportType stype)
};
enum SeamPosition {
spNearest, spAligned, spRear, spRandom
spNearest, spAligned, spAlignedBack, spRear, spRandom
};
// Orca