When projecting images, prefer using texture zones that are already used on the target object
This commit is contained in:
@@ -7331,6 +7331,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
struct TextureSampleData {
|
||||
std::array<float, 4> rgba { { 0.f, 0.f, 0.f, 1.f } };
|
||||
std::vector<float> raw_component_weights;
|
||||
bool raw_component_weights_from_texture { false };
|
||||
};
|
||||
|
||||
struct WeightedTextureSample {
|
||||
@@ -7338,16 +7339,18 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
float y_mm { 0.f };
|
||||
std::array<float, 4> rgba { { 0.f, 0.f, 0.f, 1.f } };
|
||||
std::vector<float> raw_component_weights;
|
||||
bool raw_component_weights_from_texture { false };
|
||||
float weight { 0.f };
|
||||
};
|
||||
std::vector<WeightedTextureSample> samples;
|
||||
samples.reserve(8192);
|
||||
|
||||
auto accumulate_sample = [&samples](float x_mm,
|
||||
float y_mm,
|
||||
const std::array<float, 4> &rgba,
|
||||
float sample_weight,
|
||||
std::vector<float> raw_component_weights = {}) {
|
||||
auto accumulate_sample = [&samples, component_count](float x_mm,
|
||||
float y_mm,
|
||||
const std::array<float, 4> &rgba,
|
||||
float sample_weight,
|
||||
std::vector<float> raw_component_weights = {},
|
||||
bool raw_component_weights_from_texture = false) {
|
||||
if (!std::isfinite(x_mm) || !std::isfinite(y_mm) || sample_weight <= EPSILON)
|
||||
return;
|
||||
if (!std::isfinite(sample_weight) ||
|
||||
@@ -7356,8 +7359,10 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
!std::isfinite(rgba[2]) ||
|
||||
!std::isfinite(rgba[3]))
|
||||
return;
|
||||
if (raw_component_weights.size() != component_count)
|
||||
raw_component_weights_from_texture = false;
|
||||
|
||||
samples.push_back({ x_mm, y_mm, rgba, std::move(raw_component_weights), sample_weight });
|
||||
samples.push_back({ x_mm, y_mm, rgba, std::move(raw_component_weights), raw_component_weights_from_texture, sample_weight });
|
||||
};
|
||||
|
||||
struct LayerPlaneSamplePoint {
|
||||
@@ -7473,7 +7478,8 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
float(world_pos.y()),
|
||||
sample_data.rgba,
|
||||
sample_weight,
|
||||
std::move(sample_data.raw_component_weights));
|
||||
std::move(sample_data.raw_component_weights),
|
||||
sample_data.raw_component_weights_from_texture);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -7483,7 +7489,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
const Vec3d &p1,
|
||||
const Vec3d &p2,
|
||||
const std::array<float, 4> &rgba) {
|
||||
if (accumulate_layer_plane_triangle_samples(p0, p1, p2, [&rgba](const Vec3f &) { return TextureSampleData{ rgba, {} }; }))
|
||||
if (accumulate_layer_plane_triangle_samples(p0, p1, p2, [&rgba](const Vec3f &) { return TextureSampleData{ rgba, {}, false }; }))
|
||||
return;
|
||||
|
||||
const float max_world_edge_mm = std::max({
|
||||
@@ -7640,7 +7646,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
}
|
||||
if (raw_component_weights.size() != component_count)
|
||||
rgba = composite_rgba_over_background_for_gcode(rgba, background_color);
|
||||
return TextureSampleData{ rgba, std::move(raw_component_weights) };
|
||||
return TextureSampleData{ rgba, std::move(raw_component_weights), use_raw_uv_texture };
|
||||
};
|
||||
|
||||
auto sample_data_for_barycentric = [&](const Vec3f &barycentric) {
|
||||
@@ -7711,7 +7717,8 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
float(world_pos.y()),
|
||||
sample_data.rgba,
|
||||
sample_weight,
|
||||
std::move(sample_data.raw_component_weights));
|
||||
std::move(sample_data.raw_component_weights),
|
||||
sample_data.raw_component_weights_from_texture);
|
||||
sampled_from_uv_texture = true;
|
||||
}
|
||||
}
|
||||
@@ -7789,6 +7796,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
weight_field.sample_y_mm.resize(sample_count);
|
||||
weight_field.sample_weight.resize(sample_count);
|
||||
weight_field.sample_component_weights.assign(sample_count * component_count, 0.f);
|
||||
weight_field.raw_component_weights_from_texture = false;
|
||||
|
||||
std::vector<float> fallback_acc(component_count, 0.f);
|
||||
float fallback_weight = 0.f;
|
||||
@@ -7796,6 +7804,8 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode(
|
||||
const WeightedTextureSample &sample = samples[sample_idx];
|
||||
if (sample.weight <= EPSILON)
|
||||
continue;
|
||||
if (sample.raw_component_weights_from_texture)
|
||||
weight_field.raw_component_weights_from_texture = true;
|
||||
|
||||
weight_field.sample_x_mm[sample_idx] = sample.x_mm;
|
||||
weight_field.sample_y_mm[sample_idx] = sample.y_mm;
|
||||
@@ -7911,7 +7921,8 @@ static float sample_vertex_color_weight_field_for_gcode(const VertexColorOverhan
|
||||
bool high_resolution_texture_sampling,
|
||||
bool compact_offset_mode = false)
|
||||
{
|
||||
if (compact_offset_mode && !weight_field.empty() && component_idx < weight_field.component_count) {
|
||||
if (compact_offset_mode && !weight_field.raw_component_weights_from_texture && !weight_field.empty() &&
|
||||
component_idx < weight_field.component_count) {
|
||||
std::vector<float> values(weight_field.component_count, 0.f);
|
||||
float max_value = 0.f;
|
||||
for (size_t idx = 0; idx < weight_field.component_count; ++idx) {
|
||||
|
||||
@@ -66,6 +66,7 @@ struct VertexColorOverhangWeightField {
|
||||
std::vector<float> sample_component_weights;
|
||||
std::vector<std::vector<uint32_t>> buckets;
|
||||
std::vector<float> fallback_weights;
|
||||
bool raw_component_weights_from_texture { false };
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
|
||||
@@ -4343,6 +4343,74 @@ static void assign_texture_mapping_zone_preserving_painted_regions(ModelObject &
|
||||
}
|
||||
}
|
||||
|
||||
static bool image_texture_zone_is_usable_for_projection(const TextureMappingManager &texture_mgr, unsigned int zone_id)
|
||||
{
|
||||
const TextureMappingZone *zone = texture_mgr.zone_from_id(zone_id);
|
||||
return zone != nullptr && zone->enabled && !zone->deleted && zone->is_image_texture();
|
||||
}
|
||||
|
||||
static unsigned int painted_image_texture_zone_id_for_projection(const ModelObject &object)
|
||||
{
|
||||
if (wxGetApp().preset_bundle == nullptr)
|
||||
return 0;
|
||||
|
||||
const TextureMappingManager &texture_mgr = wxGetApp().preset_bundle->texture_mapping_zones;
|
||||
std::vector<unsigned int> painted_ids;
|
||||
for (const ModelVolume *volume : object.volumes) {
|
||||
if (volume == nullptr || !volume->is_model_part() || volume->mmu_segmentation_facets.empty())
|
||||
continue;
|
||||
|
||||
const auto &used_states = volume->mmu_segmentation_facets.get_data().used_states;
|
||||
for (size_t state_idx = static_cast<size_t>(EnforcerBlockerType::Extruder1); state_idx < used_states.size(); ++state_idx) {
|
||||
if (used_states[state_idx] && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(state_idx)))
|
||||
painted_ids.emplace_back(unsigned(state_idx));
|
||||
}
|
||||
}
|
||||
|
||||
for (const TextureMappingZone &zone : texture_mgr.zones())
|
||||
if (image_texture_zone_is_usable_for_projection(texture_mgr, zone.zone_id) &&
|
||||
std::find(painted_ids.begin(), painted_ids.end(), zone.zone_id) != painted_ids.end())
|
||||
return zone.zone_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int base_image_texture_zone_id_for_projection(const ModelObject &object)
|
||||
{
|
||||
if (wxGetApp().preset_bundle == nullptr)
|
||||
return 0;
|
||||
|
||||
const TextureMappingManager &texture_mgr = wxGetApp().preset_bundle->texture_mapping_zones;
|
||||
std::vector<unsigned int> base_ids;
|
||||
if (const ConfigOption *opt = object.config.option("extruder"); opt != nullptr) {
|
||||
const int extruder_id = opt->getInt();
|
||||
if (extruder_id > 0 && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(extruder_id)))
|
||||
base_ids.emplace_back(unsigned(extruder_id));
|
||||
}
|
||||
|
||||
for (const ModelVolume *volume : object.volumes) {
|
||||
if (volume == nullptr || !volume->is_model_part())
|
||||
continue;
|
||||
const int extruder_id = volume->extruder_id();
|
||||
if (extruder_id > 0 && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(extruder_id)))
|
||||
base_ids.emplace_back(unsigned(extruder_id));
|
||||
}
|
||||
|
||||
for (const TextureMappingZone &zone : texture_mgr.zones())
|
||||
if (image_texture_zone_is_usable_for_projection(texture_mgr, zone.zone_id) &&
|
||||
std::find(base_ids.begin(), base_ids.end(), zone.zone_id) != base_ids.end())
|
||||
return zone.zone_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int texture_mapping_zone_id_for_image_projection(ModelObject &object)
|
||||
{
|
||||
if (const unsigned int painted_id = painted_image_texture_zone_id_for_projection(object); painted_id != 0)
|
||||
return painted_id;
|
||||
if (const unsigned int base_id = base_image_texture_zone_id_for_projection(object); base_id != 0)
|
||||
return base_id;
|
||||
return ensure_texture_mapping_zone();
|
||||
}
|
||||
|
||||
struct ManagedRegionColorSource
|
||||
{
|
||||
std::vector<std::vector<TriangleSelector::FacetStateTriangle>> triangles_per_type;
|
||||
@@ -8742,21 +8810,13 @@ bool GLGizmoImageProjection::project_image_to_selected_object()
|
||||
if (!changed)
|
||||
return false;
|
||||
|
||||
unsigned int raw_texture_mapping_filament_id = 0;
|
||||
if (m_raw_atlas.valid()) {
|
||||
raw_texture_mapping_filament_id = ensure_texture_mapping_zone();
|
||||
if (raw_texture_mapping_filament_id != 0) {
|
||||
object->config.set("extruder", int(raw_texture_mapping_filament_id));
|
||||
for (ModelVolume *volume : object->volumes)
|
||||
if (volume != nullptr && volume->is_model_part())
|
||||
volume->config.set("extruder", int(raw_texture_mapping_filament_id));
|
||||
enable_texture_mapping_zone_simulated_preview(raw_texture_mapping_filament_id);
|
||||
}
|
||||
}
|
||||
const bool whole_image_texture_mapped_without_regions = object_is_whole_image_texture_mapped_without_regions(*object);
|
||||
const unsigned int texture_mapping_filament_id =
|
||||
(!whole_image_texture_mapped_without_regions || m_raw_atlas.valid()) ? texture_mapping_zone_id_for_image_projection(*object) : 0;
|
||||
if (m_raw_atlas.valid() && texture_mapping_filament_id != 0)
|
||||
enable_texture_mapping_zone_simulated_preview(texture_mapping_filament_id);
|
||||
|
||||
if (!object_is_whole_image_texture_mapped_without_regions(*object)) {
|
||||
const unsigned int texture_mapping_filament_id =
|
||||
raw_texture_mapping_filament_id != 0 ? raw_texture_mapping_filament_id : ensure_texture_mapping_zone();
|
||||
if (!whole_image_texture_mapped_without_regions) {
|
||||
if (texture_mapping_filament_id != 0) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const int instance_idx = selection.get_instance_idx();
|
||||
|
||||
Reference in New Issue
Block a user