Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_preview_layout

This commit is contained in:
enricoturri1966 2021-09-20 12:05:52 +02:00
commit f45f92476e
61 changed files with 859 additions and 882 deletions

View file

@ -1,4 +1,5 @@
min_slic3r_version = 2.4.0-alpha0
1.4.0-alpha8 Added material profiles for Prusament Resin. Detect bridging perimeters enabled by default.
1.4.0-alpha7 Updated brim_separation value. Updated Prusa MINI end g-code. Added Filamentworld filament profiles.
1.4.0-alpha6 Added nozzle priming after M600. Added nozzle diameter checks for 0.8 nozzle printer profiles. Updated FW version. Increased number of top solid infill layers (0.2 layer height).
1.4.0-alpha5 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S).
@ -11,9 +12,11 @@ min_slic3r_version = 2.4.0-alpha0
1.3.0-alpha1 Added Prusament PCCF. Increased travel acceleration for Prusa MINI. Updated start g-code for Prusa MINI. Added multiple add:north and Extrudr filament profiles. Updated Z travel speed values.
1.3.0-alpha0 Disabled thick bridges, updated support settings.
min_slic3r_version = 2.3.2-alpha0
1.3.2 Added material profiles for Prusament Resin.
1.3.1 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S).
1.3.0 Added SL1S SPEED profiles.
min_slic3r_version = 2.3.0-rc1
1.2.9 Added material profiles for Prusament Resin.
1.2.8 Added multiple add:north and Extrudr filament profiles.
1.2.7 Updated "Prusament PC Blend Carbon Fiber" profile for Prusa MINI.
1.2.6 Added filament profile for "Prusament PC Blend Carbon Fiber".

View file

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 1.4.0-alpha7
config_version = 1.4.0-alpha8
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -120,7 +120,7 @@ technology = SLA
family = SL1
bed_model = sl1_bed.stl
bed_texture = sl1.svg
default_materials = Prusa Orange Tough @0.05
default_materials = Prusa Orange Tough @0.05; Prusament Resin Tough Prusa Orange @0.05
[printer_model:SL1S]
name = Original Prusa SL1S SPEED
@ -129,7 +129,7 @@ technology = SLA
family = SL1
bed_model = sl1s_bed.stl
bed_texture = sl1s.svg
default_materials = Prusa Orange Tough @0.05 SL1S
default_materials = Prusa Orange Tough @0.05 SL1S; Prusament Resin Tough Prusa Orange @0.05 SL1S
# All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface.
@ -181,7 +181,7 @@ max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0
min_skirt_length = 4
notes =
overhangs = 0
overhangs = 1
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
@ -395,6 +395,7 @@ top_solid_min_thickness = 1.2
bottom_solid_min_thickness = 0.8
single_extruder_multi_material_priming = 0
thick_bridges = 1
overhangs = 0
[print:*soluble_support*]
overhangs = 1
@ -460,10 +461,10 @@ bridge_flow_ratio = 1
bridge_speed = 20
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders==1
layer_height = 0.1
perimeter_acceleration = 800
perimeter_acceleration = 600
top_solid_layers = 9
support_material_contact_distance = 0.17
raft_contact_distance = 0.17
raft_contact_distance = 0.15
[print:*0.15mm*]
inherits = *common*
@ -619,6 +620,7 @@ support_material_contact_distance = 0.1
raft_contact_distance = 0.2
top_solid_infill_speed = 40
thick_bridges = 1
overhangs = 0
## MMU1 specific
[print:0.15mm OPTIMAL SOLUBLE FULL]
@ -704,7 +706,7 @@ small_perimeter_speed = 15
solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_contact_distance = 0.08
raft_contact_distance = 0.08
raft_contact_distance = 0.07
## MK2 - 0.6mm nozzle
@ -772,6 +774,7 @@ single_extruder_multi_material_priming = 0
inherits = 0.35mm FAST
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.5.*/ and nozzle_diameter[0]==0.4
single_extruder_multi_material_priming = 0
overhangs = 0
## MK2.5 - MMU2 specific
@ -1013,7 +1016,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
fill_pattern = grid
fill_density = 20%
support_material_contact_distance = 0.08
raft_contact_distance = 0.08
raft_contact_distance = 0.07
## MK3 - 0.6mm nozzle
@ -1028,7 +1031,7 @@ perimeter_speed = 45
solid_infill_speed = 70
top_solid_infill_speed = 45
support_material_contact_distance = 0.22
raft_contact_distance = 0.22
raft_contact_distance = 0.2
bridge_flow_ratio = 1
[print:0.20mm DETAIL @0.6 nozzle MK3]
@ -1042,7 +1045,7 @@ perimeter_speed = 45
solid_infill_speed = 70
top_solid_infill_speed = 45
support_material_contact_distance = 0.22
raft_contact_distance = 0.22
raft_contact_distance = 0.2
bridge_flow_ratio = 1
[print:0.30mm QUALITY @0.6 nozzle MK3]
@ -1311,7 +1314,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
fill_pattern = grid
fill_density = 20%
support_material_contact_distance = 0.08
raft_contact_distance = 0.08
raft_contact_distance = 0.07
# MINI - 0.6mm nozzle
@ -4496,7 +4499,31 @@ initial_exposure_time = 35
material_type = Tough
material_vendor = Monocure
## Prusa
## Prusa Polymers 0.025
[sla_material:Prusament Resin Tough Prusa Orange @0.025]
inherits = *common 0.025*
exposure_time = 5
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.025]
inherits = *common 0.025*
exposure_time = 5
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.025]
inherits = *common 0.025*
exposure_time = 6
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
## Prusa 0.025
[sla_material:Prusa Orange Tough @0.025]
inherits = *common 0.025*
exposure_time = 6
@ -5185,7 +5212,30 @@ initial_exposure_time = 35
material_type = Tough
material_vendor = Zortrax
## Prusa
## Prusa Polymers 0.05
[sla_material:Prusament Resin Tough Prusa Orange @0.05]
inherits = *common 0.05*
exposure_time = 6
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.05]
inherits = *common 0.05*
exposure_time = 6
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 35
material_type = Tough
material_vendor = Prusa Polymers
## Prusa 0.05
[sla_material:Prusa Beige Tough @0.05]
inherits = *common 0.05*
@ -5447,7 +5497,30 @@ initial_exposure_time = 50
material_type = Tough
material_vendor = BlueCast
## Prusa
## Prusa Polymers 0.1
[sla_material:Prusament Resin Tough Prusa Orange @0.1]
inherits = *common 0.1*
exposure_time = 13
initial_exposure_time = 45
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.1]
inherits = *common 0.1*
exposure_time = 13
initial_exposure_time = 45
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.1]
inherits = *common 0.1*
exposure_time = 14
initial_exposure_time = 45
material_type = Tough
material_vendor = Prusa Polymers
## Prusa 0.1
[sla_material:Prusa Orange Tough @0.1]
inherits = *common 0.1*
@ -5530,6 +5603,31 @@ material_vendor = Made for Prusa
## 0.025 SL1S
## Prusa Polymers 0.025
[sla_material:Prusament Resin Tough Prusa Orange @0.025 SL1S]
inherits = *0.025_sl1s*
exposure_time = 1.8
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.025 SL1S]
inherits = *0.025_sl1s*
exposure_time = 1.8
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.025 SL1S]
inherits = *0.025_sl1s*
exposure_time = 2
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
## Made for Prusa 0.025
[sla_material:Prusa Orange Tough @0.025 SL1S]
inherits = *0.025_sl1s*
exposure_time = 1.8
@ -5644,6 +5742,31 @@ material_vendor = Peopoly
## 0.05 SL1S
## Prusa Polymers 0.05
[sla_material:Prusament Resin Tough Prusa Orange @0.05 SL1S]
inherits = *0.05_sl1s*
exposure_time = 2
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.05 SL1S]
inherits = *0.05_sl1s*
exposure_time = 2
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.05 SL1S]
inherits = *0.05_sl1s*
exposure_time = 2.4
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
## Made for Prusa 0.05
[sla_material:Prusa Orange Tough @0.05 SL1S]
inherits = *0.05_sl1s*
exposure_time = 2
@ -5758,6 +5881,31 @@ material_vendor = Peopoly
## 0.1 SL1S
## Prusa Polymers 0.1
[sla_material:Prusament Resin Tough Prusa Orange @0.1 SL1S]
inherits = *0.1_sl1s*
exposure_time = 2.6
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Rich Black @0.1 SL1S]
inherits = *0.1_sl1s*
exposure_time = 2.6
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
[sla_material:Prusament Resin Tough Anthracite Grey @0.1 SL1S]
inherits = *0.1_sl1s*
exposure_time = 3
initial_exposure_time = 25
material_type = Tough
material_vendor = Prusa Polymers
## Made for Prusa 0.1
[sla_material:Prusa Orange Tough @0.1 SL1S]
inherits = *0.1_sl1s*
exposure_time = 2.6
@ -6573,7 +6721,7 @@ nozzle_diameter = 0.6
max_layer_height = 0.40
min_layer_height = 0.15
default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
retract_length = 3.5
retract_length = 3.2
retract_before_travel = 1.5
[printer:Original Prusa MINI & MINI+ 0.8 nozzle]

View file

@ -34,9 +34,7 @@ void main()
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
float width = 1.5 * i_scales.x;
float height = 1.5 * i_scales.y;
vec4 world_position = vec4(v_position * vec3(vec2(width), height) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);

View file

@ -145,7 +145,7 @@ void IndexedVertexArray::load_mesh(const TriangleMesh &mesh)
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
int vertices_count = 0;
for (size_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
for (size_t i = 0; i < mesh.facets_count(); ++i) {
const stl_facet &facet = mesh.stl.facet_start[i];
for (int j = 0; j < 3; ++j)
this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));

View file

@ -244,9 +244,15 @@ inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::Don
stl_get_size(stl);
}
template<typename V>
inline void its_translate(indexed_triangle_set &its, const V v)
{
for (stl_vertex &v_dst : its.vertices)
v_dst += v;
}
template<typename T>
extern void its_transform(indexed_triangle_set &its, T *trafo3x4)
inline void its_transform(indexed_triangle_set &its, T *trafo3x4)
{
for (stl_vertex &v_dst : its.vertices) {
stl_vertex v_src = v_dst;

View file

@ -78,8 +78,6 @@ add_library(libslic3r STATIC
Format/OBJ.hpp
Format/objparser.cpp
Format/objparser.hpp
Format/PRUS.cpp
Format/PRUS.hpp
Format/STL.cpp
Format/STL.hpp
Format/SL1.hpp

View file

@ -21,6 +21,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/log/trivial.hpp>
#include <boost/property_tree/ptree.hpp>
@ -32,6 +33,8 @@ namespace pt = boost::property_tree;
#include <Eigen/Dense>
#include "miniz_extension.hpp"
#include <fast_float/fast_float.h>
// Slightly faster than sprintf("%.9g"), but there is an issue with the karma floating point formatter,
// https://github.com/boostorg/spirit/pull/586
// where the exported string is one digit shorter than it should be to guarantee lossless round trip.
@ -172,14 +175,18 @@ std::string get_attribute_value_string(const char** attributes, unsigned int att
float get_attribute_value_float(const char** attributes, unsigned int attributes_size, const char* attribute_key)
{
const char* text = get_attribute_value_charptr(attributes, attributes_size, attribute_key);
return (text != nullptr) ? (float)::atof(text) : 0.0f;
float value = 0.0f;
if (const char *text = get_attribute_value_charptr(attributes, attributes_size, attribute_key); text != nullptr)
fast_float::from_chars(text, text + strlen(text), value);
return value;
}
int get_attribute_value_int(const char** attributes, unsigned int attributes_size, const char* attribute_key)
{
const char* text = get_attribute_value_charptr(attributes, attributes_size, attribute_key);
return (text != nullptr) ? ::atoi(text) : 0;
int value = 0;
if (const char *text = get_attribute_value_charptr(attributes, attributes_size, attribute_key); text != nullptr)
boost::spirit::qi::parse(text, text + strlen(text), boost::spirit::qi::int_, value);
return value;
}
bool get_attribute_value_bool(const char** attributes, unsigned int attributes_size, const char* attribute_key)

View file

@ -1842,11 +1842,7 @@ namespace ProcessLayer
assert(m600_extruder_before_layer >= 0);
// Color Change or Tool Change as Color Change.
// add tag for processor
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Color_Change) + ",T" + std::to_string(m600_extruder_before_layer) + "," + custom_gcode->color + "\n";
#else
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Color_Change) + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
// && !MMU1

View file

@ -27,9 +27,7 @@ static const float DEFAULT_TOOLPATH_HEIGHT = 0.2f;
static const float INCHES_TO_MM = 25.4f;
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
#if ENABLE_RETRACT_ACCELERATION
static const float DEFAULT_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
#endif // ENABLE_RETRACT_ACCELERATION
static const float DEFAULT_TRAVEL_ACCELERATION = 1250.0f;
static const size_t MIN_EXTRUDERS_COUNT = 5;
@ -184,10 +182,8 @@ void GCodeProcessor::TimeMachine::reset()
enabled = false;
acceleration = 0.0f;
max_acceleration = 0.0f;
#if ENABLE_RETRACT_ACCELERATION
retract_acceleration = 0.0f;
max_retract_acceleration = 0.0f;
#endif // ENABLE_RETRACT_ACCELERATION
travel_acceleration = 0.0f;
max_travel_acceleration = 0.0f;
extrude_factor_override_percentage = 1.0f;
@ -740,9 +736,7 @@ void GCodeProcessor::Result::reset() {
extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
time = 0;
}
#else
@ -756,9 +750,7 @@ void GCodeProcessor::Result::reset() {
extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
}
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -895,11 +887,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
#if ENABLE_RETRACT_ACCELERATION
float max_retract_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i);
m_time_processor.machines[i].max_retract_acceleration = max_retract_acceleration;
m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
#endif // ENABLE_RETRACT_ACCELERATION
float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
@ -1117,11 +1107,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
#if ENABLE_RETRACT_ACCELERATION
float max_retract_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i);
m_time_processor.machines[i].max_retract_acceleration = max_retract_acceleration;
m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
#endif // ENABLE_RETRACT_ACCELERATION
float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
@ -1200,9 +1188,7 @@ void GCodeProcessor::reset()
m_result.id = ++s_result_id;
m_use_volumetric_e = false;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_last_default_color_id = 0;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
#if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.reset();
@ -1741,7 +1727,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// color change tag
if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) {
unsigned char extruder_id = 0;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
static std::vector<std::string> Default_Colors = {
"#0B2C7A", // { 0.043f, 0.173f, 0.478f }, // bluish
"#1C8891", // { 0.110f, 0.533f, 0.569f },
@ -1790,16 +1775,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
if (m_last_default_color_id == Default_Colors.size())
m_last_default_color_id = 0;
}
#else
if (boost::starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) {
int eid;
if (!parse_number(comment.substr(reserved_tag(ETags::Color_Change).size() + 2), eid) || eid < 0 || eid > 255) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
return;
}
extruder_id = static_cast<unsigned char>(eid);
}
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (extruder_id < m_extruder_colors.size())
m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview
@ -1810,7 +1785,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
if (m_extruder_id == extruder_id) {
m_cp_color.current = m_extruder_colors[extruder_id];
store_move_vertex(EMoveType::Color_change);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::ColorChange, extruder_id + 1, color, "" };
m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z
@ -1818,27 +1792,19 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
process_custom_gcode_time(CustomGCode::ColorChange);
process_filaments(CustomGCode::ColorChange);
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
}
#if !ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
process_custom_gcode_time(CustomGCode::ColorChange);
process_filaments(CustomGCode::ColorChange);
#endif // !ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
return;
}
// pause print tag
if (comment == reserved_tag(ETags::Pause_Print)) {
store_move_vertex(EMoveType::Pause_Print);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::PausePrint, m_extruder_id + 1, "", "" };
m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.set();
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
process_custom_gcode_time(CustomGCode::PausePrint);
return;
}
@ -1846,13 +1812,11 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// custom code tag
if (comment == reserved_tag(ETags::Custom_Code)) {
store_move_vertex(EMoveType::Custom_GCode);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::Custom, m_extruder_id + 1, "", "" };
m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.set();
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
return;
}
@ -2943,22 +2907,14 @@ void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('T', value))
#if ENABLE_RETRACT_ACCELERATION
set_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
#else
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
#endif // ENABLE_RETRACT_ACCELERATION
}
else {
// New acceleration format, compatible with the upstream Marlin.
if (line.has_value('P', value))
set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('R', value))
#if ENABLE_RETRACT_ACCELERATION
set_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
#else
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
#endif // ENABLE_RETRACT_ACCELERATION
if (line.has_value('T', value))
// Interpret the T value as the travel acceleration in the new Marlin format.
set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
@ -3216,20 +3172,12 @@ float GCodeProcessor::get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode
}
}
#if ENABLE_RETRACT_ACCELERATION
float GCodeProcessor::get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{
size_t id = static_cast<size_t>(mode);
return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
}
#else
float GCodeProcessor::get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{
return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, static_cast<size_t>(mode));
}
#endif // ENABLE_RETRACT_ACCELERATION
#if ENABLE_RETRACT_ACCELERATION
void GCodeProcessor::set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
{
size_t id = static_cast<size_t>(mode);
@ -3239,7 +3187,6 @@ void GCodeProcessor::set_retract_acceleration(PrintEstimatedStatistics::ETimeMod
std::min(value, m_time_processor.machines[id].max_retract_acceleration);
}
}
#endif // ENABLE_RETRACT_ACCELERATION
float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{

View file

@ -242,11 +242,9 @@ namespace Slic3r {
float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_acceleration; // mm/s^2
#if ENABLE_RETRACT_ACCELERATION
float retract_acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_retract_acceleration; // mm/s^2
#endif // ENABLE_RETRACT_ACCELERATION
float travel_acceleration; // mm/s^2
// hard limit for the travel acceleration, to which the firmware will clamp.
float max_travel_acceleration; // mm/s^2
@ -359,9 +357,7 @@ namespace Slic3r {
std::vector<float> filament_diameters;
std::vector<float> filament_densities;
PrintEstimatedStatistics print_statistics;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
@ -536,9 +532,7 @@ namespace Slic3r {
#if ENABLE_FIX_PREVIEW_OPTIONS_Z
OptionsZCorrector m_options_z_corrector;
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
size_t m_last_default_color_id;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
#if ENABLE_GCODE_VIEWER_STATISTICS
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -724,9 +718,7 @@ namespace Slic3r {
float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
#if ENABLE_RETRACT_ACCELERATION
void set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
#endif // ENABLE_RETRACT_ACCELERATION
float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;

View file

@ -1,7 +1,13 @@
#include "LocalesUtils.hpp"
#ifdef _WIN32
#include <charconv>
#endif
#include <stdexcept>
#include <fast_float/fast_float.h>
namespace Slic3r {
@ -11,15 +17,15 @@ CNumericLocalesSetter::CNumericLocalesSetter()
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
m_orig_numeric_locale = std::setlocale(LC_NUMERIC, nullptr);
std::setlocale(LC_NUMERIC, "C");
#elif __linux__
#elif __APPLE__
m_original_locale = uselocale((locale_t)0);
m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_original_locale);
uselocale(m_new_locale);
#else // linux / BSD
m_original_locale = uselocale((locale_t)0);
m_new_locale = duplocale(m_original_locale);
m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_new_locale);
uselocale(m_new_locale);
#else // APPLE
m_original_locale = uselocale((locale_t)0);
m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_original_locale);
uselocale(m_new_locale);
#endif
}
@ -48,25 +54,34 @@ bool is_decimal_separator_point()
double string_to_double_decimal_point(const std::string& str, size_t* pos /* = nullptr*/)
{
double out;
std::istringstream stream(str);
if (! (stream >> out))
throw std::invalid_argument("string_to_double_decimal_point conversion failed.");
if (pos) {
if (stream.eof())
*pos = str.size();
else
*pos = stream.tellg();
}
size_t p = fast_float::from_chars(str.data(), str.data() + str.size(), out).ptr - str.data();
if (pos)
*pos = p;
return out;
}
std::string float_to_string_decimal_point(double value, int precision/* = -1*/)
{
// Our Windows build server fully supports C++17 std::to_chars. Let's use it.
// Other platforms are behind, fall back to slow stringstreams for now.
#ifdef _WIN32
constexpr size_t SIZE = 20;
char out[SIZE] = "";
std::to_chars_result res;
if (precision >=0)
res = std::to_chars(out, out+SIZE, value, std::chars_format::fixed, precision);
else
res = std::to_chars(out, out+SIZE, value, std::chars_format::general, 6);
if (res.ec == std::errc::value_too_large)
throw std::invalid_argument("float_to_string_decimal_point conversion failed.");
return std::string(out, res.ptr - out);
#else
std::stringstream buf;
if (precision >= 0)
buf << std::fixed << std::setprecision(precision);
buf << value;
return buf.str();
#endif
}

View file

@ -9,7 +9,6 @@
#include "Format/AMF.hpp"
#include "Format/OBJ.hpp"
#include "Format/PRUS.hpp"
#include "Format/STL.hpp"
#include "Format/3mf.hpp"
@ -118,8 +117,6 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
else if (boost::algorithm::iends_with(input_file, ".3mf"))
//FIXME options & LoadAttribute::CheckVersion ?
result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false);
else if (boost::algorithm::iends_with(input_file, ".prusa"))
result = load_prus(input_file.c_str(), &model);
else
throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension.");
@ -1154,7 +1151,7 @@ size_t ModelObject::facets_count() const
size_t num = 0;
for (const ModelVolume *v : this->volumes)
if (v->is_model_part())
num += v->mesh().stl.stats.number_of_facets;
num += v->mesh().facets_count();
return num;
}
@ -1508,9 +1505,9 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
const Transform3d mv = mi * v->get_matrix();
const TriangleMesh& hull = v->get_convex_hull();
for (const stl_facet &facet : hull.stl.facet_start)
for (const stl_triangle_vertex_indices& facet : hull.its.indices)
for (int i = 0; i < 3; ++ i)
min_z = std::min(min_z, (mv * facet.vertex[i].cast<double>()).z());
min_z = std::min(min_z, (mv * hull.its.vertices[facet[i]].cast<double>()).z());
}
return min_z + inst->get_offset(Z);
@ -1529,9 +1526,9 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
const Transform3d mv = mi * v->get_matrix();
const TriangleMesh& hull = v->get_convex_hull();
for (const stl_facet& facet : hull.stl.facet_start)
for (const stl_triangle_vertex_indices& facet : hull.its.indices)
for (int i = 0; i < 3; ++i)
max_z = std::max(max_z, (mv * facet.vertex[i].cast<double>()).z());
max_z = std::max(max_z, (mv * hull.its.vertices[facet[i]].cast<double>()).z());
}
return max_z + inst->get_offset(Z);
@ -1584,26 +1581,26 @@ void ModelObject::print_info() const
cout << "max_x = " << bb.max(0) << endl;
cout << "max_y = " << bb.max(1) << endl;
cout << "max_z = " << bb.max(2) << endl;
cout << "number_of_facets = " << mesh.stl.stats.number_of_facets << endl;
cout << "number_of_facets = " << mesh.facets_count() << endl;
cout << "manifold = " << (mesh.is_manifold() ? "yes" : "no") << endl;
mesh.repair(); // this calculates number_of_parts
if (mesh.needed_repair()) {
mesh.repair();
if (mesh.stl.stats.degenerate_facets > 0)
cout << "degenerate_facets = " << mesh.stl.stats.degenerate_facets << endl;
if (mesh.stl.stats.edges_fixed > 0)
cout << "edges_fixed = " << mesh.stl.stats.edges_fixed << endl;
if (mesh.stl.stats.facets_removed > 0)
cout << "facets_removed = " << mesh.stl.stats.facets_removed << endl;
if (mesh.stl.stats.facets_added > 0)
cout << "facets_added = " << mesh.stl.stats.facets_added << endl;
if (mesh.stl.stats.facets_reversed > 0)
cout << "facets_reversed = " << mesh.stl.stats.facets_reversed << endl;
if (mesh.stl.stats.backwards_edges > 0)
cout << "backwards_edges = " << mesh.stl.stats.backwards_edges << endl;
if (mesh.stats().degenerate_facets > 0)
cout << "degenerate_facets = " << mesh.stats().degenerate_facets << endl;
if (mesh.stats().edges_fixed > 0)
cout << "edges_fixed = " << mesh.stats().edges_fixed << endl;
if (mesh.stats().facets_removed > 0)
cout << "facets_removed = " << mesh.stats().facets_removed << endl;
if (mesh.stats().facets_added > 0)
cout << "facets_added = " << mesh.stats().facets_added << endl;
if (mesh.stats().facets_reversed > 0)
cout << "facets_reversed = " << mesh.stats().facets_reversed << endl;
if (mesh.stats().backwards_edges > 0)
cout << "backwards_edges = " << mesh.stats().backwards_edges << endl;
}
cout << "number_of_parts = " << mesh.stl.stats.number_of_parts << endl;
cout << "number_of_parts = " << mesh.stats().number_of_parts << endl;
cout << "volume = " << mesh.volume() << endl;
}
@ -1630,7 +1627,7 @@ std::string ModelObject::get_export_filename() const
stl_stats ModelObject::get_object_stl_stats() const
{
if (this->volumes.size() == 1)
return this->volumes[0]->mesh().stl.stats;
return this->volumes[0]->mesh().stats();
stl_stats full_stats;
full_stats.volume = 0.f;
@ -1638,7 +1635,7 @@ stl_stats ModelObject::get_object_stl_stats() const
// fill full_stats from all objet's meshes
for (ModelVolume* volume : this->volumes)
{
const stl_stats& stats = volume->mesh().stl.stats;
const stl_stats& stats = volume->mesh().stats();
// initialize full_stats (for repaired errors)
full_stats.degenerate_facets += stats.degenerate_facets;
@ -1734,7 +1731,7 @@ void ModelVolume::calculate_convex_hull()
int ModelVolume::get_mesh_errors_count() const
{
const stl_stats& stats = this->mesh().stl.stats;
const stl_stats &stats = this->mesh().stats();
return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges;

View file

@ -774,7 +774,7 @@ private:
assert(this->id() != this->supported_facets.id());
assert(this->id() != this->seam_facets.id());
assert(this->id() != this->mmu_segmentation_facets.id());
if (mesh.stl.stats.number_of_facets > 1)
if (mesh.facets_count() > 1)
calculate_convex_hull();
}
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
@ -830,7 +830,7 @@ private:
assert(this->config.id() == other.config.id());
this->set_material_id(other.material_id());
this->config.set_new_unique_id();
if (mesh.stl.stats.number_of_facets > 1)
if (mesh.facets_count() > 1)
calculate_convex_hull();
assert(this->config.id().valid());
assert(this->config.id() != other.config.id());

View file

@ -434,6 +434,8 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print)
return it == print_instances_ordered.end() || (*it)->print_object->height() <= scale_(print.config().extruder_clearance_height.value);
}
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
std::string Print::validate(std::string* warning) const
{
@ -526,42 +528,11 @@ std::string Print::validate(std::string* warning) const
}
if (has_custom_layering) {
const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
if (idx_object == tallest_object_idx)
continue;
const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
// The comparison of the profiles is not just about element-wise equality, some layers may not be
// explicitely included. Always remember z and height of last reference layer that in the vector
// and compare to that. In case some layers are in the vectors multiple times, only the last entry is
// taken into account and compared.
size_t i = 0; // index into tested profile
size_t j = 0; // index into reference profile
coordf_t ref_z = -1.;
coordf_t next_ref_z = layer_height_profile_tallest[0];
coordf_t ref_height = -1.;
while (i < layer_height_profile.size()) {
coordf_t this_z = layer_height_profile[i];
// find the last entry with this z
while (i+2 < layer_height_profile.size() && layer_height_profile[i+2] == this_z)
i += 2;
coordf_t this_height = layer_height_profile[i+1];
if (ref_height < -1. || next_ref_z < this_z + EPSILON) {
ref_z = next_ref_z;
do { // one layer can be in the vector several times
ref_height = layer_height_profile_tallest[j+1];
if (j+2 >= layer_height_profile_tallest.size())
break;
j += 2;
next_ref_z = layer_height_profile_tallest[j];
} while (ref_z == next_ref_z);
}
if (std::abs(this_height - ref_height) > EPSILON)
if (layer_height_profiles[idx_object] != layer_height_profiles[tallest_object_idx])
return L("The Wipe tower is only supported if all objects have the same variable layer height");
i += 2;
}
}
}
}

View file

@ -39,23 +39,6 @@ LayerPtrs new_layers(
return out;
}
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
// This function will go away once we get rid of admesh from ModelVolume.
static indexed_triangle_set get_mesh_its_fix_mesh_connectivity(TriangleMesh mesh)
{
assert(mesh.repaired && mesh.has_shared_vertices());
if (mesh.stl.stats.number_of_facets > 0) {
assert(mesh.repaired && mesh.has_shared_vertices());
auto nr_degenerated = mesh.stl.stats.degenerate_facets;
stl_check_facets_exact(&mesh.stl);
if (nr_degenerated != mesh.stl.stats.degenerate_facets)
// stl_check_facets_exact() removed some newly degenerated faces. Some faces could become degenerate after some mesh transformation.
stl_generate_shared_vertices(&mesh.stl, mesh.its);
} else
mesh.its.clear();
return std::move(mesh.its);
}
// Slice single triangle mesh.
static std::vector<ExPolygons> slice_volume(
const ModelVolume &volume,
@ -65,7 +48,7 @@ static std::vector<ExPolygons> slice_volume(
{
std::vector<ExPolygons> layers;
if (! zs.empty()) {
indexed_triangle_set its = get_mesh_its_fix_mesh_connectivity(volume.mesh());
indexed_triangle_set its = volume.mesh().its;
if (its.indices.size() > 0) {
MeshSlicingParamsEx params2 { params };
params2.trafo = params2.trafo * volume.get_matrix();

View file

@ -35,13 +35,6 @@ legend("tan(a) as cura - topographic lines distance limit", "sqrt(tan(a)) as Pru
namespace Slic3r
{
static inline std::pair<float, float> face_z_span(const stl_facet &f)
{
return std::pair<float, float>(
std::min(std::min(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)),
std::max(std::max(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)));
}
// By Florens Waserfall aka @platch:
// This constant essentially describes the volumetric error at the surface which is induced
// by stacking "elliptic" extrusion threads. It is empirically determined by
@ -88,10 +81,15 @@ void SlicingAdaptive::prepare(const ModelObject &object)
mesh.transform(first_instance.get_matrix(), first_instance.is_left_handed());
// 1) Collect faces from mesh.
m_faces.reserve(mesh.stl.stats.number_of_facets);
for (const stl_facet &face : mesh.stl.facet_start) {
Vec3f n = face.normal.normalized();
m_faces.emplace_back(FaceZ({ face_z_span(face), std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
m_faces.reserve(mesh.facets_count());
for (stl_triangle_vertex_indices face : mesh.its.indices) {
stl_vertex vertex[3] = { mesh.its.vertices[face[0]], mesh.its.vertices[face[1]], mesh.its.vertices[face[2]] };
stl_vertex n = face_normal_normalized(vertex);
std::pair<float, float> face_z_span {
std::min(std::min(vertex[0].z(), vertex[1].z()), vertex[2].z()),
std::max(std::max(vertex[0].z(), vertex[1].z()), vertex[2].z())
};
m_faces.emplace_back(FaceZ({ face_z_span, std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
}
// 2) Sort faces lexicographically by their Z span.

View file

@ -41,14 +41,6 @@
//====================
#define ENABLE_2_4_0_ALPHA1 1
// Enable delayed rendering of transparent volumes
#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA1)
// Enable the fix of importing color print view from gcode files into GCodeViewer
#define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA1)
// Enable drawing contours, at cut level, for sinking volumes
#define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA1)
// Enable implementation of retract acceleration in gcode processor
#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA1)
// Enable the fix for exporting and importing to/from 3mf file of mirrored volumes
#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA1)
// Enable rendering seams (and other options) in preview using models
@ -65,7 +57,7 @@
// Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3
#define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2)
// Enable fixing the z position of color change, pause print and custom gcode markers in preview
#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2)
#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2)
// Enable replacing a missing file during reload from disk command
#define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2)
// Enable changes in preview layout

View file

@ -187,6 +187,10 @@ void TriangleMesh::repair(bool update_shared_vertices)
this->repaired = true;
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
if (auto nr_degenerated = this->stl.stats.degenerate_facets; this->facets_count() > 0 && nr_degenerated > 0)
stl_check_facets_exact(&this->stl);
BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() finished";
// This call should be quite cheap, a lot of code requires the indexed_triangle_set data structure,
@ -1129,15 +1133,17 @@ TriangleMesh make_cylinder(double r, double h, double fa)
return mesh;
}
TriangleMesh make_cone(double r, double h, double fa)
indexed_triangle_set its_make_cone(double r, double h, double fa)
{
Pointf3s vertices;
std::vector<Vec3i> facets;
vertices.reserve(3+size_t(2*PI/fa));
vertices.reserve(3+2*size_t(2*PI/fa));
indexed_triangle_set mesh;
auto& vertices = mesh.vertices;
auto& facets = mesh.indices;
vertices.reserve(3 + 2 * size_t(2 * PI / fa));
// base center and top vertex
vertices.emplace_back(Vec3f::Zero());
vertices.emplace_back(Vec3f(0., 0., h));
vertices = { Vec3d::Zero(), Vec3d(0., 0., h) }; // base center and top vertex
size_t i = 0;
for (double angle=0; angle<2*PI; angle+=fa) {
vertices.emplace_back(r*std::cos(angle), r*std::sin(angle), 0.);
@ -1150,11 +1156,15 @@ TriangleMesh make_cone(double r, double h, double fa)
facets.emplace_back(0, 2, i+1); // close the shape
facets.emplace_back(1, i+1, 2);
TriangleMesh mesh(std::move(vertices), std::move(facets));
mesh.repair();
return mesh;
}
TriangleMesh make_cone(double radius, double fa)
{
TriangleMesh mesh(its_make_cone(radius, fa));
mesh.repair();
return mesh;
}
// Generates mesh for a sphere centered about the origin, using the generated angle
// to determine the granularity.
@ -1218,7 +1228,6 @@ TriangleMesh make_sphere(double radius, double fa)
{
TriangleMesh mesh(its_make_sphere(radius, fa));
mesh.repair();
return mesh;
}
@ -1335,4 +1344,13 @@ std::vector<Vec3i> its_face_neighbors_par(const indexed_triangle_set &its)
return create_face_neighbors_index(ex_tbb, its);
}
std::vector<Vec3f> its_face_normals(const indexed_triangle_set &its)
{
std::vector<Vec3f> normals;
normals.reserve(its.indices.size());
for (stl_triangle_vertex_indices face : its.indices)
normals.push_back(its_face_normal(its, face));
return normals;
}
} // namespace Slic3r

View file

@ -52,7 +52,6 @@ public:
TriangleMeshPtrs split() const;
void merge(const TriangleMesh &mesh);
ExPolygons horizontal_projection() const;
const float* first_vertex() const { return this->stl.facet_start.empty() ? nullptr : &this->stl.facet_start.front().vertex[0](0); }
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
Polygon convex_hull();
BoundingBoxf3 bounding_box() const;
@ -80,10 +79,14 @@ public:
// Restore optional data possibly released by release_optional().
void restore_optional();
stl_file stl;
const stl_stats& stats() const { return this->stl.stats; }
indexed_triangle_set its;
bool repaired;
//private:
stl_file stl;
private:
std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const;
};
@ -205,15 +208,21 @@ void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B);
void its_merge(indexed_triangle_set &A, const std::vector<Vec3f> &triangles);
void its_merge(indexed_triangle_set &A, const Pointf3s &triangles);
std::vector<Vec3f> its_face_normals(const indexed_triangle_set &its);
inline Vec3f face_normal(const stl_vertex vertex[3]) { return (vertex[1] - vertex[0]).cross(vertex[2] - vertex[1]).normalized(); }
inline Vec3f face_normal_normalized(const stl_vertex vertex[3]) { return face_normal(vertex).normalized(); }
inline Vec3f its_face_normal(const indexed_triangle_set &its, const stl_triangle_vertex_indices face)
{ const stl_vertex vertices[3] { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] }; return face_normal_normalized(vertices); }
inline Vec3f its_face_normal(const indexed_triangle_set &its, const int face_idx)
{ return its_face_normal(its, its.indices[face_idx]); }
indexed_triangle_set its_make_cube(double x, double y, double z);
TriangleMesh make_cube(double x, double y, double z);
// Generate a TriangleMesh of a cylinder
indexed_triangle_set its_make_cylinder(double r, double h, double fa=(2*PI/360));
TriangleMesh make_cylinder(double r, double h, double fa=(2*PI/360));
indexed_triangle_set its_make_sphere(double rho, double fa=(2*PI/360));
indexed_triangle_set its_make_cone(double r, double h, double fa=(2*PI/360));
TriangleMesh make_cone(double r, double h, double fa=(2*PI/360));
indexed_triangle_set its_make_sphere(double radius, double fa);
TriangleMesh make_sphere(double rho, double fa=(2*PI/360));
inline BoundingBoxf3 bounding_box(const TriangleMesh &m) { return m.bounding_box(); }

View file

@ -9,16 +9,6 @@
namespace Slic3r {
static inline Vec3i root_neighbors(const TriangleMesh &mesh, int triangle_id)
{
Vec3i neighbors;
const stl_neighbors& neighbors_src = mesh.stl.neighbors_start[triangle_id];
for (int i = 0; i < 3; ++i)
// Refuse a neighbor with a flipped normal.
neighbors(i) = neighbors_src.neighbor[i];
return neighbors;
}
#ifndef NDEBUG
bool TriangleSelector::verify_triangle_midpoints(const Triangle &tr) const
{
@ -129,7 +119,7 @@ int TriangleSelector::select_unsplit_triangle(const Vec3f &hit, int facet_idx) c
if (!m_triangles[facet_idx].valid())
return -1;
Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
Vec3i neighbors = m_neighbors[facet_idx];
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
return this->select_unsplit_triangle(hit, facet_idx, neighbors);
}
@ -167,7 +157,7 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
if (! visited[facet]) {
if (select_triangle(facet, new_state, triangle_splitting)) {
// add neighboring facets to list to be proccessed later
for (int neighbor_idx : m_mesh->stl.neighbors_start[facet].neighbor) {
for (int neighbor_idx : m_neighbors[facet]) {
if (neighbor_idx >=0 && (m_cursor.type == SPHERE || faces_camera(neighbor_idx)))
facets_to_check.push_back(neighbor_idx);
}
@ -213,12 +203,12 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
if (current_facet < m_orig_size_indices)
// Propagate over the original triangles.
for (int neighbor_idx : m_mesh->stl.neighbors_start[current_facet].neighbor) {
for (int neighbor_idx : m_neighbors[current_facet]) {
assert(neighbor_idx >= -1);
if (neighbor_idx >= 0 && !visited[neighbor_idx]) {
// Check if neighbour_facet_idx is satisfies angle in seed_fill_angle and append it to facet_queue if it do.
const Vec3f &n1 = m_mesh->stl.facet_start[m_triangles[neighbor_idx].source_triangle].normal;
const Vec3f &n2 = m_mesh->stl.facet_start[m_triangles[current_facet].source_triangle].normal;
const Vec3f &n1 = m_face_normals[m_triangles[neighbor_idx].source_triangle];
const Vec3f &n2 = m_face_normals[m_triangles[current_facet].source_triangle];
if (std::clamp(n1.dot(n2), 0.f, 1.f) >= facet_angle_limit)
facet_queue.push(neighbor_idx);
}
@ -261,7 +251,7 @@ std::pair<std::vector<Vec3i>, std::vector<Vec3i>> TriangleSelector::precompute_a
std::vector<Vec3i> neighbors(m_triangles.size(), Vec3i(-1, -1, -1));
std::vector<Vec3i> neighbors_propagated(m_triangles.size(), Vec3i(-1, -1, -1));
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) {
neighbors[facet_idx] = root_neighbors(*m_mesh, facet_idx);
neighbors[facet_idx] = m_neighbors[facet_idx];
neighbors_propagated[facet_idx] = neighbors[facet_idx];
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx]));
if (m_triangles[facet_idx].is_split())
@ -403,7 +393,7 @@ bool TriangleSelector::select_triangle(int facet_idx, EnforcerBlockerType type,
if (! m_triangles[facet_idx].valid())
return false;
Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
Vec3i neighbors = m_neighbors[facet_idx];
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
if (! select_triangle_recursive(facet_idx, neighbors, type, triangle_splitting))
@ -906,14 +896,10 @@ bool TriangleSelector::is_pointer_in_triangle(int facet_idx) const
bool TriangleSelector::faces_camera(int facet) const
{
assert(facet < m_orig_size_indices);
// The normal is cached in mesh->stl, use it.
Vec3f normal = m_mesh->stl.facet_start[facet].normal;
if (! m_cursor.uniform_scaling) {
// Transform the normal into world coords.
normal = m_cursor.trafo_normal * normal;
}
return (normal.dot(m_cursor.dir) < 0.);
Vec3f n = m_face_normals[facet];
if (! m_cursor.uniform_scaling)
n = m_cursor.trafo_normal * n;
return n.dot(m_cursor.dir) < 0.;
}
@ -1094,7 +1080,7 @@ void TriangleSelector::garbage_collect()
}
TriangleSelector::TriangleSelector(const TriangleMesh& mesh)
: m_mesh{&mesh}
: m_mesh{mesh}, m_neighbors(its_face_neighbors(mesh.its)), m_face_normals(its_face_normals(mesh.its))
{
reset();
}
@ -1107,16 +1093,17 @@ void TriangleSelector::reset()
m_invalid_triangles = 0;
m_free_triangles_head = -1;
m_free_vertices_head = -1;
m_vertices.reserve(m_mesh->its.vertices.size());
for (const stl_vertex& vert : m_mesh->its.vertices)
m_vertices.reserve(m_mesh.its.vertices.size());
for (const stl_vertex& vert : m_mesh.its.vertices)
m_vertices.emplace_back(vert);
m_triangles.reserve(m_mesh->its.indices.size());
for (size_t i = 0; i < m_mesh->its.indices.size(); ++i) {
const stl_triangle_vertex_indices &ind = m_mesh->its.indices[i];
m_triangles.reserve(m_mesh.its.indices.size());
for (size_t i = 0; i < m_mesh.its.indices.size(); ++i) {
const stl_triangle_vertex_indices &ind = m_mesh.its.indices[i];
push_triangle(ind[0], ind[1], ind[2], int(i));
}
m_orig_size_vertices = int(m_vertices.size());
m_orig_size_indices = int(m_triangles.size());
}
@ -1286,7 +1273,7 @@ indexed_triangle_set TriangleSelector::get_facets_strict(EnforcerBlockerType sta
}
for (int itriangle = 0; itriangle < m_orig_size_indices; ++ itriangle)
this->get_facets_strict_recursive(m_triangles[itriangle], root_neighbors(*m_mesh, itriangle), state, out.indices);
this->get_facets_strict_recursive(m_triangles[itriangle], m_neighbors[itriangle], state, out.indices);
for (auto &triangle : out.indices)
for (int i = 0; i < 3; ++ i)
@ -1398,7 +1385,7 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const
std::vector<Vec2i> TriangleSelector::get_seed_fill_contour() const {
std::vector<Vec2i> edges_out;
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) {
const Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
const Vec3i neighbors = m_neighbors[facet_idx];
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
this->get_seed_fill_contour_recursive(facet_idx, neighbors, neighbors, edges_out);
}
@ -1522,10 +1509,10 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
// Reserve number of triangles as if each triangle was saved with 4 bits.
// With MMU painting this estimate may be somehow low, but better than nothing.
m_triangles.reserve(std::max(m_mesh->its.indices.size(), data.second.size() / 4));
m_triangles.reserve(std::max(m_mesh.its.indices.size(), data.second.size() / 4));
// Number of triangles is twice the number of vertices on a large manifold mesh of genus zero.
// Here the triangles count account for both the nodes and leaves, thus the following line may overestimate.
m_vertices.reserve(std::max(m_mesh->its.vertices.size(), m_triangles.size() / 2));
m_vertices.reserve(std::max(m_mesh.its.vertices.size(), m_triangles.size() / 2));
// Vector to store all parents that have offsprings.
struct ProcessingInfo {
@ -1565,7 +1552,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
if (is_split) {
// root is split, add it into list of parents and split it.
// then go to the next.
Vec3i neighbors = root_neighbors(*m_mesh, triangle_id);
Vec3i neighbors = m_neighbors[triangle_id];
parents.push_back({triangle_id, neighbors, 0, num_of_children});
m_triangles[triangle_id].set_division(num_of_split_sides, special_side);
perform_split(triangle_id, neighbors, EnforcerBlockerType::NONE);

View file

@ -161,7 +161,9 @@ protected:
// Lists of vertices and triangles, both original and new
std::vector<Vertex> m_vertices;
std::vector<Triangle> m_triangles;
const TriangleMesh* m_mesh;
const TriangleMesh &m_mesh;
const std::vector<Vec3i> m_neighbors;
const std::vector<Vec3f> m_face_normals;
// Number of invalid triangles (to trigger garbage collection).
int m_invalid_triangles;

View file

@ -9,9 +9,7 @@
#include "3DScene.hpp"
#include "GLShader.hpp"
#include "GUI_App.hpp"
#if ENABLE_ENVIRONMENT_MAP || ENABLE_SINKING_CONTOURS
#include "Plater.hpp"
#endif // ENABLE_ENVIRONMENT_MAP || ENABLE_SINKING_CONTOURS
#include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp"
@ -25,9 +23,7 @@
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/ClipperUtils.hpp"
#if ENABLE_SINKING_CONTOURS
#include "libslic3r/Tesselate.hpp"
#endif // ENABLE_SINKING_CONTOURS
#include <stdio.h>
#include <stdlib.h>
@ -158,22 +154,27 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh& mesh)
}
else {
#endif // ENABLE_SMOOTH_NORMALS
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
unsigned int vertices_count = 0;
for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) {
const stl_facet& facet = mesh.stl.facet_start[i];
for (int j = 0; j < 3; ++j)
this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));
this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2);
vertices_count += 3;
}
this->load_its_flat_shading(mesh.its);
#if ENABLE_SMOOTH_NORMALS
}
#endif // ENABLE_SMOOTH_NORMALS
}
void GLIndexedVertexArray::load_its_flat_shading(const indexed_triangle_set &its)
{
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * its.indices.size());
unsigned int vertices_count = 0;
for (int i = 0; i < int(its.indices.size()); ++ i) {
stl_triangle_vertex_indices face = its.indices[i];
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
stl_vertex n = face_normal_normalized(vertex);
for (int j = 0; j < 3; ++j)
this->push_geometry(vertex[j](0), vertex[j](1), vertex[j](2), n(0), n(1), n(2));
this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2);
vertices_count += 3;
}
}
void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized)
{
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
@ -288,7 +289,6 @@ void GLIndexedVertexArray::render(
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
#if ENABLE_SINKING_CONTOURS
const float GLVolume::SinkingContours::HalfWidth = 0.25f;
void GLVolume::SinkingContours::render()
@ -357,7 +357,6 @@ void GLVolume::SinkingContours::update()
else
m_model.reset();
}
#endif // ENABLE_SINKING_CONTOURS
const std::array<float, 4> GLVolume::SELECTED_COLOR = { 0.0f, 1.0f, 0.0f, 1.0f };
const std::array<float, 4> GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f };
@ -376,12 +375,8 @@ const std::array<std::array<float, 4>, 4> GLVolume::MODEL_COLOR = { {
} };
GLVolume::GLVolume(float r, float g, float b, float a)
: m_transformed_bounding_box_dirty(true)
, m_sla_shift_z(0.0)
, m_transformed_convex_hull_bounding_box_dirty(true)
#if ENABLE_SINKING_CONTOURS
: m_sla_shift_z(0.0)
, m_sinking_contours(*this)
#endif // ENABLE_SINKING_CONTOURS
// geometry_id == 0 -> invalid
, geometry_id(std::pair<size_t, size_t>(0, 0))
, extruder_id(0)
@ -399,9 +394,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, force_transparent(false)
, force_native_color(false)
, force_neutral_color(false)
#if ENABLE_SINKING_CONTOURS
, force_sinking_contours(false)
#endif // ENABLE_SINKING_CONTOURS
, tverts_range(0, size_t(-1))
, qverts_range(0, size_t(-1))
{
@ -506,32 +499,27 @@ bool GLVolume::is_left_handed() const
const BoundingBoxf3& GLVolume::transformed_bounding_box() const
{
if (!m_transformed_bounding_box.has_value()) {
const BoundingBoxf3& box = bounding_box();
assert(box.defined || box.min(0) >= box.max(0) || box.min(1) >= box.max(1) || box.min(2) >= box.max(2));
BoundingBoxf3* transformed_bounding_box = const_cast<BoundingBoxf3*>(&m_transformed_bounding_box);
bool* transformed_bounding_box_dirty = const_cast<bool*>(&m_transformed_bounding_box_dirty);
if (*transformed_bounding_box_dirty) {
*transformed_bounding_box = box.transformed(world_matrix());
*transformed_bounding_box_dirty = false;
assert(box.defined || box.min.x() >= box.max.x() || box.min.y() >= box.max.y() || box.min.z() >= box.max.z());
std::optional<BoundingBoxf3>* trans_box = const_cast<std::optional<BoundingBoxf3>*>(&m_transformed_bounding_box);
*trans_box = box.transformed(world_matrix());
}
return *transformed_bounding_box;
return *m_transformed_bounding_box;
}
const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const
{
BoundingBoxf3* transformed_convex_hull_bounding_box = const_cast<BoundingBoxf3*>(&m_transformed_convex_hull_bounding_box);
bool* transformed_convex_hull_bounding_box_dirty = const_cast<bool*>(&m_transformed_convex_hull_bounding_box_dirty);
if (*transformed_convex_hull_bounding_box_dirty) {
*transformed_convex_hull_bounding_box = this->transformed_convex_hull_bounding_box(world_matrix());
*transformed_convex_hull_bounding_box_dirty = false;
if (!m_transformed_convex_hull_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* trans_box = const_cast<std::optional<BoundingBoxf3>*>(&m_transformed_convex_hull_bounding_box);
*trans_box = transformed_convex_hull_bounding_box(world_matrix());
}
return *transformed_convex_hull_bounding_box;
return *m_transformed_convex_hull_bounding_box;
}
BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &trafo) const
{
return (m_convex_hull && m_convex_hull->stl.stats.number_of_facets > 0) ?
return (m_convex_hull && m_convex_hull->facets_count() > 0) ?
m_convex_hull->transformed_bounding_box(trafo) :
bounding_box().transformed(trafo);
}
@ -605,12 +593,10 @@ bool GLVolume::is_below_printbed() const
return transformed_convex_hull_bounding_box().max.z() < 0.0;
}
#if ENABLE_SINKING_CONTOURS
void GLVolume::render_sinking_contours()
{
m_sinking_contours.render();
}
#endif // ENABLE_SINKING_CONTOURS
std::vector<int> GLVolumeCollection::load_object(
const ModelObject *model_object,
@ -767,6 +753,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
TriangleMesh brim_mesh = make_cube(width + 2.f * brim_width, depth + 2.f * brim_width, 0.2f);
brim_mesh.translate(-brim_width, -brim_width, 0.f);
mesh.merge(brim_mesh);
mesh.repair();
volumes.emplace_back(new GLVolume(color));
GLVolume& v = *volumes.back();
@ -834,11 +821,9 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) const
{
#if ENABLE_SINKING_CONTOURS
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
if (to_render.empty())
return;
#endif // ENABLE_SINKING_CONTOURS
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr)
@ -853,7 +838,6 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
if (disable_cullface)
glsafe(::glDisable(GL_CULL_FACE));
#if ENABLE_SINKING_CONTOURS
for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->set_render_color();
@ -903,7 +887,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
}
if (m_show_sinking_contours)
if (m_show_sinking_contours) {
for (GLVolumeWithIdAndZ& volume : to_render) {
// render sinking contours of hovered/displaced volumes
if (volume.first->is_sinking() && !volume.first->is_below_printbed() &&
@ -915,48 +899,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
shader->start_using();
}
}
#else
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
shader->set_uniform("print_box.min", m_print_box_min, 3);
shader->set_uniform("print_box.max", m_print_box_max, 3);
shader->set_uniform("z_range", m_z_range, 2);
shader->set_uniform("clipping_plane", m_clipping_plane, 4);
shader->set_uniform("slope.normal_z", m_slope.normal_z);
#if ENABLE_ENVIRONMENT_MAP
unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id();
bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1";
shader->set_uniform("use_environment_tex", use_environment_texture);
if (use_environment_texture)
glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id));
#endif // ENABLE_ENVIRONMENT_MAP
glcheck();
GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func);
for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->set_render_color();
shader->set_uniform("uniform_color", volume.first->render_color);
shader->set_uniform("print_box.actived", volume.first->shader_outside_printer_detection_enabled);
shader->set_uniform("print_box.volume_world_matrix", volume.first->world_matrix());
shader->set_uniform("slope.actived", m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower);
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
volume.first->render();
}
#if ENABLE_ENVIRONMENT_MAP
if (use_environment_texture)
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
#endif // ENABLE_ENVIRONMENT_MAP
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
#endif // ENABLE_SINKING_CONTOURS
if (disable_cullface)
glsafe(::glEnable(GL_CULL_FACE));

View file

@ -8,11 +8,10 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/Geometry.hpp"
#if ENABLE_SINKING_CONTOURS
#include "GLModel.hpp"
#endif // ENABLE_SINKING_CONTOURS
#include <functional>
#include <optional>
#define HAS_GLSAFE
#ifdef HAS_GLSAFE
@ -128,6 +127,8 @@ public:
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
#endif // ENABLE_SMOOTH_NORMALS
void load_its_flat_shading(const indexed_triangle_set &its);
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
inline void reserve(size_t sz) {
@ -258,9 +259,7 @@ public:
enum EHoverState : unsigned char
{
HS_None,
#if ENABLE_SINKING_CONTOURS
HS_Hover,
#endif // ENABLE_SINKING_CONTOURS
HS_Select,
HS_Deselect
};
@ -275,17 +274,12 @@ private:
// Shift in z required by sla supports+pad
double m_sla_shift_z;
// Bounding box of this volume, in unscaled coordinates.
BoundingBoxf3 m_transformed_bounding_box;
// Whether or not is needed to recalculate the transformed bounding box.
bool m_transformed_bounding_box_dirty;
std::optional<BoundingBoxf3> m_transformed_bounding_box;
// Convex hull of the volume, if any.
std::shared_ptr<const TriangleMesh> m_convex_hull;
// Bounding box of this volume, in unscaled coordinates.
BoundingBoxf3 m_transformed_convex_hull_bounding_box;
// Whether or not is needed to recalculate the transformed convex hull bounding box.
bool m_transformed_convex_hull_bounding_box_dirty;
std::optional<BoundingBoxf3> m_transformed_convex_hull_bounding_box;
#if ENABLE_SINKING_CONTOURS
class SinkingContours
{
static const float HalfWidth;
@ -303,7 +297,6 @@ private:
};
SinkingContours m_sinking_contours;
#endif // ENABLE_SINKING_CONTOURS
public:
// Color of the triangles / quads held by this volume.
@ -365,10 +358,8 @@ public:
bool force_native_color : 1;
// Whether or not render this volume in neutral
bool force_neutral_color : 1;
#if ENABLE_SINKING_CONTOURS
// Whether or not to force rendering of sinking contours
bool force_sinking_contours : 1;
#endif // ENABLE_SINKING_CONTOURS
};
// Is mouse or rectangle selection over this object to select/deselect it ?
@ -490,16 +481,14 @@ public:
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); }
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box.reset(); m_transformed_convex_hull_bounding_box.reset(); }
bool is_sla_support() const;
bool is_sla_pad() const;
bool is_sinking() const;
bool is_below_printbed() const;
#if ENABLE_SINKING_CONTOURS
void render_sinking_contours();
#endif // ENABLE_SINKING_CONTOURS
// Return an estimate of the memory consumed by this class.
size_t cpu_memory_used() const {

View file

@ -1556,9 +1556,7 @@ void Control::OnMotion(wxMouseEvent& event)
event.Skip();
// Set tooltips with information for each icon
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (GUI::wxGetApp().is_editor())
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
this->SetToolTip(get_tooltip(tick));
if (action) {

View file

@ -977,7 +977,7 @@ void Choice::BUILD() {
propagate_value();
} );
temp->Bind(wxEVT_TEXT_ENTER, [this, temp](wxEvent& e) {
temp->Bind(wxEVT_TEXT_ENTER, [this](wxEvent& e) {
EnterPressed enter(this);
propagate_value();
} );

View file

@ -583,10 +583,8 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print&
// Stealing out lines_ends should be safe because this gcode_result is processed only once (see the 1st if in this function).
std::move(const_cast<std::vector<size_t>&>(gcode_result.lines_ends)));
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (wxGetApp().is_gcode_viewer())
m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
load_toolpaths(gcode_result);
@ -744,9 +742,7 @@ void GCodeViewer::reset()
m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>();
m_print_statistics.reset();
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_sequential_view.gcode_window.reset();
#if ENABLE_GCODE_VIEWER_STATISTICS
m_statistics.reset_all();
@ -3048,7 +3044,11 @@ void GCodeViewer::render_legend(float& legend_height)
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
#if ENABLE_SEAMS_USING_BATCHED_MODELS
auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label,
#else
auto append_item = [this, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label,
#endif // ENABLE_SEAMS_USING_BATCHED_MODELS
bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array<float, 4>& offsets = { 0.0f, 0.0f, 0.0f, 0.0f },
double used_filament_m = 0.0, double used_filament_g = 0.0,
std::function<void()> callback = nullptr) {
@ -3446,11 +3446,7 @@ void GCodeViewer::render_legend(float& legend_height)
}
case EViewType::ColorPrint:
{
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z;
#else
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
size_t total_items = 1;
for (unsigned char i : m_extruder_ids) {
total_items += color_print_ranges(i, custom_gcode_per_print_z).size();
@ -3548,11 +3544,7 @@ void GCodeViewer::render_legend(float& legend_height)
auto generate_partial_times = [this, get_used_filament_from_volume](const TimesList& times, const std::vector<double>& used_filaments) {
PartialTimes items;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z;
#else
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
int extruders_count = wxGetApp().extruders_edited_cnt();
std::vector<Color> last_color(extruders_count);
for (int i = 0; i < extruders_count; ++i) {

View file

@ -783,9 +783,7 @@ private:
GCodeProcessor::Result::SettingsIds m_settings_ids;
std::array<SequentialRangeCap, 2> m_sequential_range_caps;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
public:
GCodeViewer();
@ -834,10 +832,8 @@ public:
void toggle_gcode_window_visibility() { m_sequential_view.gcode_window.toggle_visibility(); }
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<CustomGCode::Item>& get_custom_gcode_per_print_z() { return m_custom_gcode_per_print_z; }
size_t get_extruders_count() { return m_extruders_count; }
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
private:
void load_toolpaths(const GCodeProcessor::Result& gcode_result);

View file

@ -1450,19 +1450,13 @@ void GLCanvas3D::render()
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
_render_background();
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_objects(GLVolumeCollection::ERenderType::Opaque);
#else
_render_objects();
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
if (!m_main_toolbar.is_enabled())
_render_gcode();
_render_sla_slices();
_render_selection();
_render_bed(!camera.is_looking_downward(), true);
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_objects(GLVolumeCollection::ERenderType::Transparent);
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_sequential_clearance();
#if ENABLE_RENDER_SELECTION_CENTER
@ -2932,7 +2926,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return;
}
#if ENABLE_SINKING_CONTOURS
for (GLVolume* volume : m_volumes.volumes) {
volume->force_sinking_contours = false;
}
@ -2944,7 +2937,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
m_dirty = true;
};
#endif // ENABLE_SINKING_CONTOURS
if (m_gizmos.on_mouse(evt)) {
if (wxWindow::FindFocus() != m_canvas)
@ -2970,7 +2962,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
default: { break; }
}
}
#if ENABLE_SINKING_CONTOURS
else if (evt.Dragging()) {
switch (m_gizmos.get_current_type())
{
@ -2984,7 +2975,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
default: { break; }
}
}
#endif // ENABLE_SINKING_CONTOURS
return;
}
@ -3294,10 +3284,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else
evt.Skip();
#if ENABLE_SINKING_CONTOURS
if (m_moving)
show_sinking_contours();
#endif // ENABLE_SINKING_CONTOURS
#ifdef __WXMSW__
if (on_enter_workaround)
@ -5071,12 +5059,7 @@ void GLCanvas3D::_render_bed_for_picking(bool bottom)
wxGetApp().plater()->get_bed().render_for_picking(*this, bottom, scale_factor);
}
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type)
#else
void GLCanvas3D::_render_objects()
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
{
if (m_volumes.empty())
return;
@ -5108,20 +5091,14 @@ void GLCanvas3D::_render_objects()
if (shader != nullptr) {
shader->start_using();
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
switch (type)
{
default:
case GLVolumeCollection::ERenderType::Opaque:
{
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
if (m_picking_enabled && !m_gizmos.is_dragging() && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
int object_id = m_layers_editing.last_object_id;
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) {
#else
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) {
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
// Which volume to paint without the layer height profile shader?
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
});
@ -5130,11 +5107,7 @@ void GLCanvas3D::_render_objects()
}
else {
// do not cull backfaces to show broken geometry, if any
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) {
#else
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) {
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
});
}
@ -5153,7 +5126,6 @@ void GLCanvas3D::_render_objects()
shader->start_using();
}
}
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
break;
}
case GLVolumeCollection::ERenderType::Transparent:
@ -5162,9 +5134,6 @@ void GLCanvas3D::_render_objects()
break;
}
}
#else
m_volumes.render(GLVolumeCollection::ERenderType::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix());
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
shader->stop_using();
}
@ -5673,11 +5642,8 @@ void GLCanvas3D::_update_volumes_hover_state()
}
}
}
#if ENABLE_SINKING_CONTOURS
else if (volume.selected)
volume.hover = GLVolume::HS_Hover;
#endif // ENABLE_SINKING_CONTOURS
}
}

View file

@ -710,10 +710,8 @@ public:
void set_toolpath_view_type(GCodeViewer::EViewType type);
void set_volumes_z_range(const std::array<double, 2>& range);
void set_toolpaths_z_range(const std::array<unsigned int, 2>& range);
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<CustomGCode::Item>& get_custom_gcode_per_print_z() { return m_gcode_viewer.get_custom_gcode_per_print_z(); }
size_t get_gcode_extruders_count() { return m_gcode_viewer.get_extruders_count(); }
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
std::vector<int> load_object(const Model& model, int obj_idx);
@ -895,11 +893,7 @@ private:
void _render_background() const;
void _render_bed(bool bottom, bool show_axes);
void _render_bed_for_picking(bool bottom);
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void _render_objects(GLVolumeCollection::ERenderType type);
#else
void _render_objects();
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void _render_gcode();
void _render_selection() const;
void _render_sequential_clearance();

View file

@ -7,9 +7,7 @@
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Model.hpp"
#if ENABLE_SINKING_CONTOURS
#include "libslic3r/Polygon.hpp"
#endif // ENABLE_SINKING_CONTOURS
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/predicate.hpp>
@ -78,7 +76,7 @@ void GLModel::init_from(const InitializationData& data)
}
}
void GLModel::init_from(const TriangleMesh& mesh)
void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bbox)
{
if (!m_render_data.empty()) // call reset() if you want to reuse this model
return;
@ -86,31 +84,36 @@ void GLModel::init_from(const TriangleMesh& mesh)
RenderData data;
data.type = PrimitiveType::Triangles;
std::vector<float> vertices = std::vector<float>(18 * mesh.stl.stats.number_of_facets);
std::vector<unsigned int> indices = std::vector<unsigned int>(3 * mesh.stl.stats.number_of_facets);
std::vector<float> vertices = std::vector<float>(18 * its.indices.size());
std::vector<unsigned int> indices = std::vector<unsigned int>(3 * its.indices.size());
unsigned int vertices_count = 0;
for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
const stl_facet& facet = mesh.stl.facet_start[i];
for (size_t j = 0; j < 3; ++j) {
for (uint32_t i = 0; i < its.indices.size(); ++i) {
stl_triangle_vertex_indices face = its.indices[i];
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
stl_vertex n = face_normal_normalized(vertex);
for (size_t j = 0; j < 3; ++ j) {
size_t offset = i * 18 + j * 6;
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(facet.vertex[j].data()), 3 * sizeof(float));
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(facet.normal.data()), 3 * sizeof(float));
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(vertex[j].data()), 3 * sizeof(float));
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(n.data()), 3 * sizeof(float));
}
for (size_t j = 0; j < 3; ++j) {
for (size_t j = 0; j < 3; ++j)
indices[i * 3 + j] = vertices_count + j;
}
vertices_count += 3;
}
data.indices_count = static_cast<unsigned int>(indices.size());
m_bounding_box = mesh.bounding_box();
m_bounding_box = bbox;
send_to_gpu(data, vertices, indices);
m_render_data.emplace_back(data);
}
#if ENABLE_SINKING_CONTOURS
void GLModel::init_from(const indexed_triangle_set& its)
{
this->init_from(its, bounding_box(its));
}
void GLModel::init_from(const Polygons& polygons, float z)
{
auto append_polygon = [](const Polygon& polygon, float z, GUI::GLModel::InitializationData& data) {
@ -137,7 +140,6 @@ void GLModel::init_from(const Polygons& polygons, float z)
}
init_from(init_data);
}
#endif // ENABLE_SINKING_CONTOURS
bool GLModel::init_from_file(const std::string& filename)
{
@ -157,7 +159,9 @@ bool GLModel::init_from_file(const std::string& filename)
return false;
}
init_from(model.mesh());
TriangleMesh mesh = model.mesh();
mesh.require_shared_vertices();
init_from(mesh.its, mesh.bounding_box());
m_filename = filename;

View file

@ -6,13 +6,13 @@
#include <vector>
#include <string>
struct indexed_triangle_set;
namespace Slic3r {
class TriangleMesh;
#if ENABLE_SINKING_CONTOURS
class Polygon;
using Polygons = std::vector<Polygon>;
#endif // ENABLE_SINKING_CONTOURS
namespace GUI {
@ -70,10 +70,9 @@ namespace GUI {
virtual ~GLModel() { reset(); }
void init_from(const InitializationData& data);
void init_from(const TriangleMesh& mesh);
#if ENABLE_SINKING_CONTOURS
void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox);
void init_from(const indexed_triangle_set& its);
void init_from(const Polygons& polygons, float z);
#endif // ENABLE_SINKING_CONTOURS
bool init_from_file(const std::string& filename);
// if entity_id == -1 set the color of all entities

View file

@ -1175,9 +1175,6 @@ void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighte
float right = left + scaled_icons_size;
unsigned int tex_id = m_arrow_texture.texture.get_id();
// width and height of icon arrow is pointing to
float tex_width = (float)m_icons_texture.get_width();
float tex_height = (float)m_icons_texture.get_height();
// arrow width and height
float arr_tex_width = (float)m_arrow_texture.texture.get_width();
float arr_tex_height = (float)m_arrow_texture.texture.get_height();

View file

@ -383,7 +383,9 @@ void create_combochecklist(wxComboCtrl* comboCtrl, const std::string& text, cons
// the following line messes up the popup size the first time it is shown on wxWidgets 3.1.3
// comboCtrl->EnablePopupAnimation(false);
#ifdef _WIN32
popup->SetFont(comboCtrl->GetFont());
#endif // _WIN32
comboCtrl->SetPopupControl(popup);
wxString title = from_u8(text);
max_width = std::max(max_width, 60 + comboCtrl->GetTextExtent(title).x);

View file

@ -429,9 +429,8 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
/* FT_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ",
/* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML",
/* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;",
/* FT_PRUSA */ "Prusa Control files (*.prusa)|*.prusa;*.PRUSA",
/* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC",
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA",
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF",
/* FT_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF",
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",

View file

@ -55,7 +55,6 @@ enum FileType
FT_OBJ,
FT_AMF,
FT_3MF,
FT_PRUSA,
FT_GCODE,
FT_MODEL,
FT_PROJECT,

View file

@ -689,7 +689,7 @@ wxMenuItem* MenuFactory::append_menu_item_fix_through_netfabb(wxMenu* menu)
return nullptr;
wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Fix through the Netfabb"), "",
[](wxCommandEvent&) { obj_list()->fix_through_netfabb(); }, "", menu,
[]() {return plater()->can_fix_through_netfabb(); }, plater());
[]() {return plater()->can_fix_through_netfabb(); }, m_parent);
return menu_item;
}
@ -698,7 +698,7 @@ wxMenuItem* MenuFactory::append_menu_item_simplify(wxMenu* menu)
{
wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Simplify model"), "",
[](wxCommandEvent&) { obj_list()->simplify(); }, "", menu,
[]() {return plater()->can_simplify(); }, plater());
[]() {return plater()->can_simplify(); }, m_parent);
menu->AppendSeparator();
return menu_item;
@ -779,7 +779,7 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
}
append_submenu(menu, extruder_selection_menu, wxID_ANY, name, _L("Use another extruder"),
"edit_uni"/* : "change_extruder"*/, []() {return true; }, GUI::wxGetApp().plater());
"edit_uni"/* : "change_extruder"*/, []() {return true; }, m_parent);
// menu->AppendSubMenu(extruder_selection_menu, name);
}
@ -1061,6 +1061,7 @@ wxMenu* MenuFactory::multi_selection_menu()
wxMenu* menu = new MenuWithSeparators();
append_menu_item_fix_through_netfabb(menu);
append_menu_item_reload_from_disk(menu);
append_menu_items_convert_unit(menu);
if (obj_list()->can_merge_to_multipart_object())

View file

@ -19,6 +19,7 @@
#include "Selection.hpp"
#include "format.hpp"
#include "NotificationManager.hpp"
#include "MsgDialog.hpp"
#include <boost/algorithm/string.hpp>
#include <wx/progdlg.h>
@ -369,7 +370,7 @@ void ObjectList::get_selection_indexes(std::vector<int>& obj_idxs, std::vector<i
}
}
std::sort(obj_idxs.begin(), obj_idxs.end(), std::greater<int>());
std::sort(obj_idxs.begin(), obj_idxs.end(), std::less<int>());
obj_idxs.erase(std::unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
}
@ -393,7 +394,7 @@ wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx /
const stl_stats& stats = vol_idx == -1 ?
(*m_objects)[obj_idx]->get_object_stl_stats() :
(*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stl.stats;
(*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats();
if (stats.degenerate_facets > 0)
tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d degenerate facet", "%1$d degenerate facets", stats.degenerate_facets), stats.degenerate_facets) + "\n";
@ -4013,13 +4014,124 @@ void ObjectList::rename_item()
void ObjectList::fix_through_netfabb()
{
int obj_idx, vol_idx;
get_selected_item_indexes(obj_idx, vol_idx);
// Do not fix anything when a gizmo is open. There might be issues with updates
// and what is worse, the snapshot time would refer to the internal stack.
if (!wxGetApp().plater()->canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::Undefined))
return;
wxGetApp().plater()->fix_through_netfabb(obj_idx, vol_idx);
// model_name
std::vector<std::string> succes_models;
// model_name failing reason
std::vector<std::pair<std::string, std::string>> failed_models;
std::vector<int> obj_idxs, vol_idxs;
get_selection_indexes(obj_idxs, vol_idxs);
std::vector<std::string> model_names;
// clear selections from the non-broken models if any exists
// and than fill names of models to repairing
if (vol_idxs.empty()) {
for (int i = int(obj_idxs.size())-1; i >= 0; --i)
if (object(obj_idxs[i])->get_mesh_errors_count() == 0)
obj_idxs.erase(obj_idxs.begin()+i);
for (int obj_idx : obj_idxs)
model_names.push_back(object(obj_idx)->name);
}
else {
ModelObject* obj = object(obj_idxs.front());
for (int i = int(vol_idxs.size()) - 1; i >= 0; --i)
if (obj->get_mesh_errors_count(vol_idxs[i]) == 0)
vol_idxs.erase(vol_idxs.begin() + i);
for (int vol_idx : vol_idxs)
model_names.push_back(obj->volumes[vol_idx]->name);
}
auto plater = wxGetApp().plater();
auto fix_and_update_progress = [this, plater, model_names](const int obj_idx, const int vol_idx,
int model_idx,
wxProgressDialog& progress_dlg,
std::vector<std::string>& succes_models,
std::vector<std::pair<std::string, std::string>>& failed_models)
{
const std::string& model_name = model_names[model_idx];
wxString msg = _L("Repairing model");
if (model_names.size() == 1)
msg += ": " + from_u8(model_name) + "\n";
else {
msg += ":\n";
for (size_t i = 0; i < model_names.size(); ++i)
msg += (i == model_idx ? " > " : " ") + from_u8(model_names[i]) + "\n";
msg += "\n";
}
plater->clear_before_change_mesh(obj_idx);
std::string res;
if (!fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res))
return false;
wxGetApp().plater()->changed_mesh(obj_idx);
plater->changed_mesh(obj_idx);
if (res.empty())
succes_models.push_back(model_name);
else
failed_models.push_back({ model_name, res });
update_item_error_icon(obj_idx, vol_idx);
update_info_items(obj_idx);
return true;
};
Plater::TakeSnapshot snapshot(plater, _L("Fix through NetFabb"));
// Open a progress dialog.
wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100,
nullptr, // ! parent of the wxProgressDialog should be nullptr to avoid flickering during the model fixing
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
int model_idx{ 0 };
if (vol_idxs.empty()) {
int vol_idx{ -1 };
for (int obj_idx : obj_idxs) {
if (object(obj_idx)->get_mesh_errors_count(vol_idx) == 0)
continue;
if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg, succes_models, failed_models))
break;
model_idx++;
}
}
else {
int obj_idx{ obj_idxs.front() };
for (int vol_idx : vol_idxs) {
if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg, succes_models, failed_models))
break;
model_idx++;
}
}
// Close the progress dialog
progress_dlg.Update(100, "");
// Show info message
wxString msg;
wxString bullet_suf = "\n - ";
if (!succes_models.empty()) {
msg = _L_PLURAL("Folowing model is repaired successfully", "Folowing models are repaired successfully", succes_models.size()) + ":";
for (auto& model : succes_models)
msg += bullet_suf + from_u8(model);
msg += "\n\n";
}
if (!failed_models.empty()) {
msg += _L_PLURAL("Folowing model repair failed", "Folowing models repair failed", failed_models.size()) + ":\n";
for (auto& model : failed_models)
msg += bullet_suf + from_u8(model.first) + ": " + _(model.second);
}
if (msg.IsEmpty())
msg = _L("Repairing was canceled");
// !!! Use wxMessageDialog instead of MessageDialog here
// It will not be "dark moded" but the Application will not lose a focus after model repairing
wxMessageDialog(nullptr, msg, _L("Model Repair by the Netfabb service"), wxICON_INFORMATION | wxOK).ShowModal();
}
void ObjectList::simplify()

View file

@ -654,7 +654,6 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
update_layers_slider_mode();
Plater* plater = wxGetApp().plater();
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
CustomGCode::Info ticks_info_from_model;
if (wxGetApp().is_editor())
ticks_info_from_model = plater->model().custom_gcode_per_print_z;
@ -662,18 +661,10 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
ticks_info_from_model.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_model.gcodes = m_canvas->get_custom_gcode_per_print_z();
}
#else
CustomGCode::Info& ticks_info_from_model = plater->model().custom_gcode_per_print_z;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
check_layers_slider_values(ticks_info_from_model.gcodes, layers_z);
//first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
#else
m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config());
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_layers_slider->SetSliderValues(layers_z);
assert(m_layers_slider->GetMinValue() == 0);
m_layers_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1);
@ -943,14 +934,10 @@ void Preview::load_print_as_fff(bool keep_z_range)
colors = wxGetApp().plater()->get_colors_for_color_print(m_gcode_result);
if (!gcode_preview_data_valid) {
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (wxGetApp().is_editor())
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
else
color_print_values = m_canvas->get_custom_gcode_per_print_z();
#else
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
colors.push_back("#808080"); // gray color for pause print or custom G-code
}
}
@ -972,11 +959,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
zs = m_canvas->get_gcode_layers_zs();
m_loaded = true;
}
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
else if (wxGetApp().is_editor()) {
#else
else {
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
// Load the initial preview based on slices, not the final G-code.
m_canvas->load_preview(colors, color_print_values);
m_left_sizer->Hide(m_bottom_toolbar_panel);
@ -985,7 +968,6 @@ void Preview::load_print_as_fff(bool keep_z_range)
zs = m_canvas->get_volumes_print_zs(true);
}
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (!zs.empty() && !m_keep_current_preview_type) {
unsigned int number_extruders = wxGetApp().is_editor() ?
(unsigned int)print->extruders().size() :
@ -1021,7 +1003,6 @@ void Preview::load_print_as_fff(bool keep_z_range)
}
#endif // ENABLE_PREVIEW_LAYOUT
}
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (zs.empty()) {
// all layers filtered out
@ -1030,23 +1011,6 @@ void Preview::load_print_as_fff(bool keep_z_range)
} else
update_layers_slider(zs, keep_z_range);
}
#if !ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (!m_keep_current_preview_type) {
unsigned int number_extruders = (unsigned int)print->extruders().size();
const wxString choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes.empty() ?
_L("Color Print") :
(number_extruders > 1) ? _L("Tool") : _L("Feature type");
int type = m_choice_view_type->FindString(choice);
if (m_choice_view_type->GetSelection() != type) {
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count)) {
m_choice_view_type->SetSelection(type);
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
}
}
}
#endif // !ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
}
void Preview::load_print_as_sla()

View file

@ -53,9 +53,9 @@ void GLGizmoBase::Grabber::render(float size, const std::array<float, 4>& render
if (! cube_initialized) {
// This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least).
TriangleMesh mesh = make_cube(1., 1., 1.);
mesh.translate(Vec3f(-0.5, -0.5, -0.5));
const_cast<GLModel&>(cube).init_from(mesh);
indexed_triangle_set mesh = its_make_cube(1., 1., 1.);
its_translate(mesh, Vec3f(-0.5, -0.5, -0.5));
const_cast<GLModel&>(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
const_cast<bool&>(cube_initialized) = true;
}
@ -90,9 +90,9 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u
m_base_color = DEFAULT_BASE_COLOR;
m_drag_color = DEFAULT_DRAG_COLOR;
m_highlight_color = DEFAULT_HIGHLIGHT_COLOR;
m_cone.init_from(make_cone(1., 1., 2 * PI / 24));
m_sphere.init_from(make_sphere(1., (2 * M_PI) / 24.));
m_cylinder.init_from(make_cylinder(1., 1., 2 * PI / 24.));
m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24));
m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.));
m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.));
}
void GLGizmoBase::set_hover_id(int id)

View file

@ -16,9 +16,7 @@
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Model.hpp"
#if ENABLE_SINKING_CONTOURS
#include "libslic3r/TriangleMeshSlicer.hpp"
#endif // ENABLE_SINKING_CONTOURS
namespace Slic3r {
namespace GUI {
@ -92,9 +90,7 @@ void GLGizmoCut::on_render()
m_max_z = box.max.z();
set_cut_z(m_cut_z);
#if ENABLE_SINKING_CONTOURS
update_contours();
#endif // ENABLE_SINKING_CONTOURS
const float min_x = box.min.x() - Margin;
const float max_x = box.max.x() + Margin;
@ -143,13 +139,11 @@ void GLGizmoCut::on_render()
shader->stop_using();
#if ENABLE_SINKING_CONTOURS
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z()));
glsafe(::glLineWidth(2.0f));
m_cut_contours.contours.render();
glsafe(::glPopMatrix());
#endif // ENABLE_SINKING_CONTOURS
}
void GLGizmoCut::on_render_for_picking()
@ -275,7 +269,6 @@ BoundingBoxf3 GLGizmoCut::bounding_box() const
return ret;
}
#if ENABLE_SINKING_CONTOURS
void GLGizmoCut::update_contours()
{
const Selection& selection = m_parent.get_selection();
@ -315,7 +308,6 @@ void GLGizmoCut::update_contours()
else
m_cut_contours.contours.reset();
}
#endif // ENABLE_SINKING_CONTOURS
} // namespace GUI
} // namespace Slic3r

View file

@ -2,11 +2,9 @@
#define slic3r_GLGizmoCut_hpp_
#include "GLGizmoBase.hpp"
#if ENABLE_SINKING_CONTOURS
#include "slic3r/GUI/GLModel.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/ObjectID.hpp"
#endif // ENABLE_SINKING_CONTOURS
namespace Slic3r {
namespace GUI {
@ -26,7 +24,6 @@ class GLGizmoCut : public GLGizmoBase
bool m_keep_lower{ true };
bool m_rotate_lower{ false };
#if ENABLE_SINKING_CONTOURS
struct CutContours
{
TriangleMesh mesh;
@ -39,7 +36,6 @@ class GLGizmoCut : public GLGizmoBase
};
CutContours m_cut_contours;
#endif // ENABLE_SINKING_CONTOURS
public:
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
@ -66,9 +62,7 @@ private:
void perform_cut(const Selection& selection);
double calc_projection(const Linef3& mouse_ray) const;
BoundingBoxf3 bounding_box() const;
#if ENABLE_SINKING_CONTOURS
void update_contours();
#endif // ENABLE_SINKING_CONTOURS
};
} // namespace GUI

View file

@ -287,13 +287,14 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
float dot_limit = limit.dot(down);
// Now calculate dot product of vert_direction and facets' normals.
int idx = -1;
for (const stl_facet &facet : mv->mesh().stl.facet_start) {
++idx;
if (facet.normal.dot(down) > dot_limit) {
int idx = 0;
const indexed_triangle_set &its = mv->mesh().its;
for (stl_triangle_vertex_indices face : its.indices) {
if (its_face_normal(its, face).dot(down) > dot_limit) {
m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER);
m_triangle_selectors.back()->request_update_render_data();
}
++ idx;
}
}

View file

@ -142,7 +142,9 @@ void GLGizmoFlatten::update_planes()
// Now we'll go through all the facets and append Points of facets sharing the same normal.
// This part is still performed in mesh coordinate system.
const int num_of_facets = ch.stl.stats.number_of_facets;
const int num_of_facets = ch.facets_count();
const std::vector<Vec3f> face_normals = its_face_normals(ch.its);
const std::vector<Vec3i> face_neighbors = its_face_neighbors(ch.its);
std::vector<int> facet_queue(num_of_facets, 0);
std::vector<bool> facet_visited(num_of_facets, false);
int facet_queue_cnt = 0;
@ -154,7 +156,7 @@ void GLGizmoFlatten::update_planes()
if (!facet_visited[facet_idx]) {
facet_queue[facet_queue_cnt ++] = facet_idx;
facet_visited[facet_idx] = true;
normal_ptr = &ch.stl.facet_start[facet_idx].normal;
normal_ptr = &face_normals[facet_idx];
m_planes.emplace_back();
break;
}
@ -163,20 +165,18 @@ void GLGizmoFlatten::update_planes()
while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt];
const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal;
const stl_normal& this_normal = face_normals[facet_idx];
if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) {
stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex;
const Vec3i face = ch.its.indices[facet_idx];
for (int j=0; j<3; ++j)
m_planes.back().vertices.emplace_back(first_vertex[j].cast<double>());
m_planes.back().vertices.emplace_back(ch.its.vertices[face[j]].cast<double>());
facet_visited[facet_idx] = true;
for (int j = 0; j < 3; ++ j) {
int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j];
if (! facet_visited[neighbor_idx])
for (int j = 0; j < 3; ++ j)
if (int neighbor_idx = face_neighbors[facet_idx][j]; neighbor_idx >= 0 && ! facet_visited[neighbor_idx])
facet_queue[facet_queue_cnt ++] = neighbor_idx;
}
}
}
m_planes.back().normal = normal_ptr->cast<double>();
Pointf3s& verts = m_planes.back().vertices;

View file

@ -20,7 +20,7 @@ namespace GUI {
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
{
m_vbo_cylinder.init_from(make_cylinder(1., 1.));
m_vbo_cylinder.init_from(its_make_cylinder(1., 1.));
}

View file

@ -291,6 +291,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
m_imgui->text("");
ImGui::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("first_color"));
ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_width);
@ -302,6 +303,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
if(ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
m_modified_extruders_colors[m_first_selected_extruder_idx] = {first_color.x, first_color.y, first_color.z, first_color.w};
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("second_color"));
ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_width);
@ -317,14 +319,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("tool_type"));
float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(2.f)) / 2.f;
ImGui::NewLine();
ImGui::AlignTextToFramePadding();
ImGui::SameLine(tool_type_offset + m_imgui->scaled(0.f));
ImGui::PushItemWidth(tool_type_radio_brush);
if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BRUSH)) {
@ -382,12 +382,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::Separator();
if(m_tool_type == ToolType::BRUSH) {
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type"));
ImGui::NewLine();
float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(2.f)) / 2.f;
ImGui::AlignTextToFramePadding();
ImGui::SameLine(cursor_type_offset + m_imgui->scaled(0.f));
ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
@ -458,8 +456,8 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::Separator();
} else if(m_tool_type == ToolType::SMART_FILL) {
m_imgui->text(m_desc["smart_fill_angle"] + ":");
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc["smart_fill_angle"] + ":");
std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo,"
"placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_width);

View file

@ -20,7 +20,7 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
, m_starting_box_center(Vec3d::Zero())
, m_starting_box_bottom_center(Vec3d::Zero())
{
m_vbo_cone.init_from(make_cone(1., 1., 2*PI/36));
m_vbo_cone.init_from(its_make_cone(1., 1., 2*PI/36));
}
std::string GLGizmoMove3D::get_tooltip() const

View file

@ -8,8 +8,9 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/TriangleMesh.hpp"
@ -20,17 +21,10 @@ GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& ic
: GLGizmoBase(parent, icon_filename, sprite_id)
{
// Make sphere and save it into a vertex buffer.
const TriangleMesh sphere_mesh = make_sphere(1., (2*M_PI)/24.);
for (size_t i=0; i<sphere_mesh.its.vertices.size(); ++i)
m_vbo_sphere.push_geometry(sphere_mesh.its.vertices[i].cast<double>(),
sphere_mesh.stl.facet_start[i].normal.cast<double>());
for (const stl_triangle_vertex_indices& indices : sphere_mesh.its.indices)
m_vbo_sphere.push_triangle(indices(0), indices(1), indices(2));
m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.));
m_vbo_sphere.finalize_geometry(true);
}
// port of 948bc382655993721d93d3b9fce9b0186fcfb211
void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate)
{
@ -632,9 +626,15 @@ void TriangleSelectorGUI::update_render_data()
GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers;
int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt;
for (int i = 0; i < 3; ++i)
iva.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v;
const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v;
const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v;
//FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort
// or the current implementation may be more cache friendly.
const Vec3f n = (v1 - v0).cross(v2 - v1).normalized();
iva.push_geometry(v0, n);
iva.push_geometry(v1, n);
iva.push_geometry(v2, n);
iva.push_triangle(cnt, cnt + 1, cnt + 2);
cnt += 3;
}

View file

@ -881,7 +881,7 @@ CommonGizmosDataID GLGizmoSlaSupports::on_get_requirements() const
void GLGizmoSlaSupports::ask_about_changes_call_after(std::function<void()> on_yes, std::function<void()> on_no)
{
wxGetApp().CallAfter([this, on_yes, on_no]() {
wxGetApp().CallAfter([on_yes, on_no]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
MessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually "

View file

@ -30,11 +30,8 @@ public:
ClippingPlane(const Vec3d& direction, double offset)
{
Vec3d norm_dir = direction.normalized();
m_data[0] = norm_dir(0);
m_data[1] = norm_dir(1);
m_data[2] = norm_dir(2);
m_data[3] = offset;
set_normal(direction);
set_offset(offset);
}
bool operator==(const ClippingPlane& cp) const {
@ -48,7 +45,13 @@ public:
}
bool is_point_clipped(const Vec3d& point) const { return distance(point) < 0.; }
void set_normal(const Vec3d& normal) { for (size_t i=0; i<3; ++i) m_data[i] = normal(i); }
void set_normal(const Vec3d& normal)
{
const Vec3d norm_dir = normal.normalized();
m_data[0] = norm_dir.x();
m_data[1] = norm_dir.y();
m_data[2] = norm_dir.z();
}
void set_offset(double offset) { m_data[3] = offset; }
Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); }
bool is_active() const { return m_data[3] != DBL_MAX; }
@ -113,10 +116,8 @@ public:
// during MeshRaycaster existence.
MeshRaycaster(const TriangleMesh& mesh)
: m_emesh(mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length
, m_normals(its_face_normals(mesh.its))
{
m_normals.reserve(mesh.stl.facet_start.size());
for (const stl_facet& facet : mesh.stl.facet_start)
m_normals.push_back(facet.normal);
}
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,

View file

@ -1176,7 +1176,9 @@ void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(boo
void NotificationManager::SlicingProgressNotification::on_cancel_button()
{
if (m_cancel_callback){
m_cancel_callback();
if (!m_cancel_callback()) {
set_progress_state(SlicingProgressState::SP_NO_SLICING);
}
}
}
int NotificationManager::SlicingProgressNotification::get_duration()
@ -1681,7 +1683,7 @@ void NotificationManager::upload_job_notification_show_error(int id, const std::
}
}
void NotificationManager::init_slicing_progress_notification(std::function<void()> cancel_callback)
void NotificationManager::init_slicing_progress_notification(std::function<bool()> cancel_callback)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {

View file

@ -188,7 +188,7 @@ public:
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
// slicing progress
void init_slicing_progress_notification(std::function<void()> cancel_callback);
void init_slicing_progress_notification(std::function<bool()> cancel_callback);
// percentage negative = canceled, <0-1) = progress, 1 = completed
void set_slicing_progress_percentage(const std::string& text, float percentage);
// hides slicing progress notification imidietly
@ -496,7 +496,7 @@ private:
SP_CANCELLED, // fades after 10 seconds, simple message
SP_COMPLETED // Has export hyperlink and print info, fades after 20 sec if sidebar is shown, otherwise no fade out
};
SlicingProgressNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function<void()> callback)
SlicingProgressNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function<bool()> callback)
: ProgressBarNotification(n, id_provider, evt_handler)
, m_cancel_callback(callback)
{
@ -507,7 +507,7 @@ private:
// sets text of notification - call after setting progress state
void set_status_text(const std::string& text);
// sets cancel button callback
void set_cancel_callback(std::function<void()> callback) { m_cancel_callback = callback; }
void set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; }
bool has_cancel_callback() const { return m_cancel_callback != nullptr; }
// sets SlicingProgressState, negative percent means canceled
void set_progress_state(float percent);
@ -545,7 +545,8 @@ private:
const float win_pos_x, const float win_pos_y) override;
void on_cancel_button();
int get_duration() override;
std::function<void()> m_cancel_callback;
// if returns false, process was already canceled
std::function<bool()> m_cancel_callback;
SlicingProgressState m_sp_state { SlicingProgressState::SP_PROGRESS };
bool m_has_print_info { false };
std::string m_print_info;

View file

@ -37,7 +37,6 @@ void ObjectDataViewModelNode::init_container()
static constexpr char LayerRootIcon[] = "edit_layers_all";
static constexpr char LayerIcon[] = "edit_layers_some";
static constexpr char WarningIcon[] = "exclamation";
static constexpr char InfoIcon[] = "objlist_info";
struct InfoItemAtributes {
std::string name;

View file

@ -1722,7 +1722,6 @@ struct Plater::priv
#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE
void replace_with_stl();
void reload_all_from_disk();
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
void create_simplify_notification(const std::vector<size_t>& obj_ids);
void set_current_panel(wxPanel* panel);
@ -3664,27 +3663,6 @@ void Plater::priv::reload_all_from_disk()
}
}
void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
{
if (obj_idx < 0)
return;
// Do not fix anything when a gizmo is open. There might be issues with updates
// and what is worse, the snapshot time would refer to the internal stack.
if (! q->canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::Undefined))
return;
// size_t snapshot_time = undo_redo_stack().active_snapshot_time();
Plater::TakeSnapshot snapshot(q, _L("Fix through NetFabb"));
q->clear_before_change_mesh(obj_idx);
ModelObject* mo = model.objects[obj_idx];
fix_model_by_win10_sdk_gui(*mo, vol_idx);
q->changed_mesh(obj_idx);
// workaround to fix the issue, when PrusaSlicer lose a focus after model fixing
q->SetFocus();
}
void Plater::priv::create_simplify_notification(const std::vector<size_t>& obj_ids) {
const uint32_t triangles_to_suggest_simplify = 1000000;
@ -4041,12 +4019,14 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
if (evt.error()) {
std::pair<std::string, bool> message = evt.format_error_message();
if (evt.critical_error()) {
if (q->m_tracking_popup_menu)
if (q->m_tracking_popup_menu) {
// We don't want to pop-up a message box when tracking a pop-up menu.
// We postpone the error message instead.
q->m_tracking_popup_menu_error_message = message.first;
else
} else {
show_error(q, message.first, message.second);
notification_manager->set_slicing_progress_hidden();
}
} else
notification_manager->push_slicing_error_notification(message.first);
// this->statusbar()->set_status_text(from_u8(message.first));
@ -4168,7 +4148,8 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
const bool is_some_full_instances = get_selection().is_single_full_instance() ||
get_selection().is_single_full_object() ||
get_selection().is_multiple_full_instance();
menu = is_some_full_instances ? menus.object_menu() : menus.part_menu();
menu = is_some_full_instances ? menus.object_menu() :
get_selection().is_single_volume() ? menus.part_menu() : menus.multi_selection_menu();
}
}
@ -4273,7 +4254,10 @@ void Plater::priv::init_notification_manager()
notification_manager->init();
auto cancel_callback = [this]() {
if (this->background_process.idle())
return false;
this->background_process.stop();
return true;
};
notification_manager->init_slicing_progress_notification(cancel_callback);
notification_manager->set_fff(printer_technology == ptFFF);
@ -4521,11 +4505,22 @@ bool Plater::priv::can_delete_all() const
bool Plater::priv::can_fix_through_netfabb() const
{
int obj_idx = get_selected_object_idx();
if (obj_idx < 0)
return false;
std::vector<int> obj_idxs, vol_idxs;
sidebar->obj_list()->get_selection_indexes(obj_idxs, vol_idxs);
return model.objects[obj_idx]->get_mesh_errors_count() > 0;
if (vol_idxs.empty()) {
for (auto obj_idx : obj_idxs)
if (model.objects[obj_idx]->get_mesh_errors_count() > 0)
return true;
return false;
}
int obj_idx = obj_idxs.front();
for (auto vol_idx : vol_idxs)
if (model.objects[obj_idx]->get_mesh_errors_count(vol_idx) > 0)
return true;
return false;
}
@ -6233,7 +6228,6 @@ std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessor
std::vector<std::string> colors = get_extruder_colors_from_plater_config(result);
colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size());
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (wxGetApp().is_gcode_viewer() && result != nullptr) {
for (const CustomGCode::Item& code : result->custom_gcode_per_print_z) {
if (code.type == CustomGCode::ColorChange)
@ -6241,14 +6235,11 @@ std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessor
}
}
else {
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z.gcodes) {
if (code.type == CustomGCode::ColorChange)
colors.emplace_back(code.color);
}
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
}
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
return colors;
}
@ -6472,7 +6463,6 @@ void Plater::suppress_background_process(const bool stop_background_process)
this->p->suppressed_backround_processing_update = true;
}
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
void Plater::mirror(Axis axis) { p->mirror(axis); }
void Plater::split_object() { p->split_object(); }
void Plater::split_volume() { p->split_volume(); }

View file

@ -235,7 +235,6 @@ public:
void schedule_background_process(bool schedule = true);
bool is_background_process_update_scheduled() const;
void suppress_background_process(const bool stop_background_process) ;
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
void send_gcode();
void eject_drive();

View file

@ -619,8 +619,8 @@ void PreferencesDialog::create_settings_mode_widget()
m_values["old_settings_layout_mode"] = (id == 0) ? "1" : "0";
#ifdef _MSW_DARK_MODE
if (!disable_new_layout)
m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0";
#endif
m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0";
m_values["dlg_settings_layout_mode"] = (id == dlg_id) ? "1" : "0";
});
id++;

View file

@ -620,24 +620,54 @@ const GLVolume* Selection::get_volume(unsigned int volume_idx) const
const BoundingBoxf3& Selection::get_bounding_box() const
{
if (m_bounding_box_dirty)
calc_bounding_box();
return m_bounding_box;
if (!m_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
(*bbox)->merge((*m_volumes)[i]->transformed_convex_hull_bounding_box());
}
}
}
return *m_bounding_box;
}
const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const
{
if (m_unscaled_instance_bounding_box_dirty)
calc_unscaled_instance_bounding_box();
return m_unscaled_instance_bounding_box;
if (!m_unscaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
if (volume.is_modifier)
continue;
Transform3d trafo = volume.get_instance_transformation().get_matrix(false, false, true, false) * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_unscaled_instance_bounding_box;
}
const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
{
if (m_scaled_instance_bounding_box_dirty)
calc_scaled_instance_bounding_box();
return m_scaled_instance_bounding_box;
if (!m_scaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
if (volume.is_modifier)
continue;
Transform3d trafo = volume.get_instance_transformation().get_matrix(false, false, false, false) * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_scaled_instance_bounding_box;
}
void Selection::start_dragging()
@ -823,10 +853,10 @@ void Selection::flattening_rotate(const Vec3d& normal)
}
#if !DISABLE_INSTANCES_SYNCH
// we want to synchronize z-rotation as well, otherwise the flattening behaves funny
// when applied on one of several identical instances
// Apply the same transformation also to other instances,
// but respect their possibly diffrent z-rotation.
if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_FULL);
synchronize_unselected_instances(SYNC_ROTATION_GENERAL);
#endif // !DISABLE_INSTANCES_SYNCH
this->set_bounding_boxes_dirty();
@ -1692,52 +1722,6 @@ void Selection::do_remove_object(unsigned int object_idx)
}
}
void Selection::calc_bounding_box() const
{
BoundingBoxf3* bounding_box = const_cast<BoundingBoxf3*>(&m_bounding_box);
*bounding_box = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
bounding_box->merge((*m_volumes)[i]->transformed_convex_hull_bounding_box());
}
}
*const_cast<bool*>(&m_bounding_box_dirty) = false;
}
void Selection::calc_unscaled_instance_bounding_box() const
{
BoundingBoxf3* unscaled_instance_bounding_box = const_cast<BoundingBoxf3*>(&m_unscaled_instance_bounding_box);
*unscaled_instance_bounding_box = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
if (volume.is_modifier)
continue;
Transform3d trafo = volume.get_instance_transformation().get_matrix(false, false, true, false) * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
unscaled_instance_bounding_box->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
*const_cast<bool*>(&m_unscaled_instance_bounding_box_dirty) = false;
}
void Selection::calc_scaled_instance_bounding_box() const
{
BoundingBoxf3* scaled_instance_bounding_box = const_cast<BoundingBoxf3*>(&m_scaled_instance_bounding_box);
*scaled_instance_bounding_box = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
if (volume.is_modifier)
continue;
Transform3d trafo = volume.get_instance_transformation().get_matrix(false, false, false, false) * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
scaled_instance_bounding_box->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
*const_cast<bool*>(&m_scaled_instance_bounding_box_dirty) = false;
}
void Selection::render_selected_volumes() const
{
float color[3] = { 1.0f, 1.0f, 1.0f };
@ -2055,10 +2039,6 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
v->set_instance_offset(Z, volume->get_instance_offset().z());
break;
}
case SYNC_ROTATION_FULL:
// rotation comes from place on face -> force given z
v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() });
break;
case SYNC_ROTATION_GENERAL:
// generic rotation -> update instance z with the delta of the rotation.
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());

View file

@ -1,10 +1,12 @@
#ifndef slic3r_GUI_Selection_hpp_
#define slic3r_GUI_Selection_hpp_
#include <set>
#include "libslic3r/Geometry.hpp"
#include "GLModel.hpp"
#include <set>
#include <optional>
namespace Slic3r {
class Shader;
@ -203,14 +205,11 @@ private:
IndicesList m_list;
Cache m_cache;
Clipboard m_clipboard;
BoundingBoxf3 m_bounding_box;
bool m_bounding_box_dirty;
std::optional<BoundingBoxf3> m_bounding_box;
// Bounding box of a selection, with no instance scaling applied. This bounding box
// is useful for absolute scaling of tilted objects in world coordinate space.
BoundingBoxf3 m_unscaled_instance_bounding_box;
bool m_unscaled_instance_bounding_box_dirty;
BoundingBoxf3 m_scaled_instance_bounding_box;
bool m_scaled_instance_bounding_box_dirty;
std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
#if ENABLE_RENDER_SELECTION_CENTER
GLModel m_vbo_sphere;
@ -359,10 +358,7 @@ private:
void do_remove_volume(unsigned int volume_idx);
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
void do_remove_object(unsigned int object_idx);
void calc_bounding_box() const;
void calc_unscaled_instance_bounding_box() const;
void calc_scaled_instance_bounding_box() const;
void set_bounding_boxes_dirty() { m_bounding_box_dirty = true; m_unscaled_instance_bounding_box_dirty = true; m_scaled_instance_bounding_box_dirty = true; }
void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
void render_selected_volumes() const;
void render_synchronized_volumes() const;
void render_bounding_box(const BoundingBoxf3& box, float* color) const;
@ -375,10 +371,8 @@ public:
enum SyncRotationType {
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
SYNC_ROTATION_NONE = 0,
// Synchronize fully. Used from "place on bed" feature.
SYNC_ROTATION_FULL = 1,
// Synchronize after rotation by an axis not parallel with Z.
SYNC_ROTATION_GENERAL = 2,
SYNC_ROTATION_GENERAL = 1,
};
void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
void synchronize_unselected_volumes();

View file

@ -318,7 +318,10 @@ public:
const char* what() const throw() { return "Model repair has been canceled"; }
};
void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
// returt FALSE, if fixing was canceled
// fix_result is empty, if fixing finished successfully
// fix_result containes a message if fixing failed
bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxProgressDialog& progress_dialog, const wxString& msg_header, std::string& fix_result)
{
std::mutex mutex;
std::condition_variable condition;
@ -337,11 +340,6 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
else
volumes.emplace_back(model_object.volumes[volume_idx]);
// Open a progress dialog.
wxProgressDialog progress_dialog(
_L("Model fixing"),
_L("Exporting model") + "...",
100, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); // ! parent of the wxProgressDialog should be nullptr to avoid flickering during the model fixing
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
bool success = false;
@ -423,21 +421,23 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
});
while (! finished) {
condition.wait_for(lock, std::chrono::milliseconds(500), [&progress]{ return progress.updated; });
if (! progress_dialog.Update(progress.percent, _(progress.message)))
// decrease progress.percent value to avoid closing of the progress dialog
if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message)))
canceled = true;
else
progress_dialog.Fit();
progress.updated = false;
}
if (canceled) {
// Nothing to show.
} else if (success) {
Slic3r::GUI::MessageDialog dlg(nullptr, _L("Model repaired successfully"), _L("Model Repair by the Netfabb service"), wxICON_INFORMATION | wxOK);
dlg.ShowModal();
fix_result = "";
} else {
Slic3r::GUI::MessageDialog dlg(nullptr, _L("Model repair failed:") + " \n" + _(progress.message), _L("Model Repair by the Netfabb service"), wxICON_ERROR | wxOK);
dlg.ShowModal();
fix_result = progress.message;
}
worker_thread.join();
return !canceled;
}
} // namespace Slic3r

View file

@ -3,6 +3,8 @@
#include <string>
class wxProgressDialog;
namespace Slic3r {
class Model;
@ -12,12 +14,14 @@ class Print;
#ifdef HAS_WIN10SDK
extern bool is_windows10();
extern void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx);
// returt false, if fixing was canceled
extern bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxProgressDialog& progress_dlg, const wxString& msg_header, std::string& fix_result);
#else /* HAS_WIN10SDK */
inline bool is_windows10() { return false; }
inline void fix_model_by_win10_sdk_gui(ModelObject &, int) {}
// returt false, if fixing was canceled
inline bool fix_model_by_win10_sdk_gui(ModelObject&, int, wxProgressDialog&, const wxString&, std::string&) { return false; }
#endif /* HAS_WIN10SDK */

View file

@ -342,7 +342,7 @@ SCENARIO( "TriangleMesh: Mesh merge functions") {
cube.merge(cube2);
cube.repair();
THEN( "There are twice as many facets in the merged mesh as the original.") {
REQUIRE(cube.stl.stats.number_of_facets == 2 * cube2.stl.stats.number_of_facets);
REQUIRE(cube.facets_count() == 2 * cube2.facets_count());
}
}
}

View file

@ -10,7 +10,6 @@
#include "libslic3r/Format/AMF.hpp"
#include "libslic3r/Format/3mf.hpp"
#include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/PRUS.hpp"
#include "libslic3r/Format/STL.hpp"
#include "libslic3r/PresetBundle.hpp"
%}