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 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-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-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). 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-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. 1.3.0-alpha0 Disabled thick bridges, updated support settings.
min_slic3r_version = 2.3.2-alpha0 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.1 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S).
1.3.0 Added SL1S SPEED profiles. 1.3.0 Added SL1S SPEED profiles.
min_slic3r_version = 2.3.0-rc1 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.8 Added multiple add:north and Extrudr filament profiles.
1.2.7 Updated "Prusament PC Blend Carbon Fiber" profile for Prusa MINI. 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". 1.2.6 Added filament profile for "Prusament PC Blend Carbon Fiber".

View File

@ -5,7 +5,7 @@
name = Prusa Research name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs. # 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. # 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? # Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/ 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% changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -120,7 +120,7 @@ technology = SLA
family = SL1 family = SL1
bed_model = sl1_bed.stl bed_model = sl1_bed.stl
bed_texture = sl1.svg 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] [printer_model:SL1S]
name = Original Prusa SL1S SPEED name = Original Prusa SL1S SPEED
@ -129,7 +129,7 @@ technology = SLA
family = SL1 family = SL1
bed_model = sl1s_bed.stl bed_model = sl1s_bed.stl
bed_texture = sl1s.svg 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 # All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface. # not make it into the user interface.
@ -181,7 +181,7 @@ max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0 max_volumetric_speed = 0
min_skirt_length = 4 min_skirt_length = 4
notes = notes =
overhangs = 0 overhangs = 1
only_retract_when_crossing_perimeters = 0 only_retract_when_crossing_perimeters = 0
ooze_prevention = 0 ooze_prevention = 0
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode 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 bottom_solid_min_thickness = 0.8
single_extruder_multi_material_priming = 0 single_extruder_multi_material_priming = 0
thick_bridges = 1 thick_bridges = 1
overhangs = 0
[print:*soluble_support*] [print:*soluble_support*]
overhangs = 1 overhangs = 1
@ -460,10 +461,10 @@ bridge_flow_ratio = 1
bridge_speed = 20 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 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 layer_height = 0.1
perimeter_acceleration = 800 perimeter_acceleration = 600
top_solid_layers = 9 top_solid_layers = 9
support_material_contact_distance = 0.17 support_material_contact_distance = 0.17
raft_contact_distance = 0.17 raft_contact_distance = 0.15
[print:*0.15mm*] [print:*0.15mm*]
inherits = *common* inherits = *common*
@ -619,6 +620,7 @@ support_material_contact_distance = 0.1
raft_contact_distance = 0.2 raft_contact_distance = 0.2
top_solid_infill_speed = 40 top_solid_infill_speed = 40
thick_bridges = 1 thick_bridges = 1
overhangs = 0
## MMU1 specific ## MMU1 specific
[print:0.15mm OPTIMAL SOLUBLE FULL] [print:0.15mm OPTIMAL SOLUBLE FULL]
@ -704,7 +706,7 @@ small_perimeter_speed = 15
solid_infill_speed = 40 solid_infill_speed = 40
top_solid_infill_speed = 30 top_solid_infill_speed = 30
support_material_contact_distance = 0.08 support_material_contact_distance = 0.08
raft_contact_distance = 0.08 raft_contact_distance = 0.07
## MK2 - 0.6mm nozzle ## MK2 - 0.6mm nozzle
@ -772,6 +774,7 @@ single_extruder_multi_material_priming = 0
inherits = 0.35mm FAST 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 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 single_extruder_multi_material_priming = 0
overhangs = 0
## MK2.5 - MMU2 specific ## MK2.5 - MMU2 specific
@ -1013,7 +1016,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
fill_pattern = grid fill_pattern = grid
fill_density = 20% fill_density = 20%
support_material_contact_distance = 0.08 support_material_contact_distance = 0.08
raft_contact_distance = 0.08 raft_contact_distance = 0.07
## MK3 - 0.6mm nozzle ## MK3 - 0.6mm nozzle
@ -1028,7 +1031,7 @@ perimeter_speed = 45
solid_infill_speed = 70 solid_infill_speed = 70
top_solid_infill_speed = 45 top_solid_infill_speed = 45
support_material_contact_distance = 0.22 support_material_contact_distance = 0.22
raft_contact_distance = 0.22 raft_contact_distance = 0.2
bridge_flow_ratio = 1 bridge_flow_ratio = 1
[print:0.20mm DETAIL @0.6 nozzle MK3] [print:0.20mm DETAIL @0.6 nozzle MK3]
@ -1042,7 +1045,7 @@ perimeter_speed = 45
solid_infill_speed = 70 solid_infill_speed = 70
top_solid_infill_speed = 45 top_solid_infill_speed = 45
support_material_contact_distance = 0.22 support_material_contact_distance = 0.22
raft_contact_distance = 0.22 raft_contact_distance = 0.2
bridge_flow_ratio = 1 bridge_flow_ratio = 1
[print:0.30mm QUALITY @0.6 nozzle MK3] [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_pattern = grid
fill_density = 20% fill_density = 20%
support_material_contact_distance = 0.08 support_material_contact_distance = 0.08
raft_contact_distance = 0.08 raft_contact_distance = 0.07
# MINI - 0.6mm nozzle # MINI - 0.6mm nozzle
@ -4496,7 +4499,31 @@ initial_exposure_time = 35
material_type = Tough material_type = Tough
material_vendor = Monocure 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] [sla_material:Prusa Orange Tough @0.025]
inherits = *common 0.025* inherits = *common 0.025*
exposure_time = 6 exposure_time = 6
@ -5185,7 +5212,30 @@ initial_exposure_time = 35
material_type = Tough material_type = Tough
material_vendor = Zortrax 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] [sla_material:Prusa Beige Tough @0.05]
inherits = *common 0.05* inherits = *common 0.05*
@ -5447,7 +5497,30 @@ initial_exposure_time = 50
material_type = Tough material_type = Tough
material_vendor = BlueCast 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] [sla_material:Prusa Orange Tough @0.1]
inherits = *common 0.1* inherits = *common 0.1*
@ -5530,6 +5603,31 @@ material_vendor = Made for Prusa
## 0.025 SL1S ## 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] [sla_material:Prusa Orange Tough @0.025 SL1S]
inherits = *0.025_sl1s* inherits = *0.025_sl1s*
exposure_time = 1.8 exposure_time = 1.8
@ -5644,6 +5742,31 @@ material_vendor = Peopoly
## 0.05 SL1S ## 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] [sla_material:Prusa Orange Tough @0.05 SL1S]
inherits = *0.05_sl1s* inherits = *0.05_sl1s*
exposure_time = 2 exposure_time = 2
@ -5758,6 +5881,31 @@ material_vendor = Peopoly
## 0.1 SL1S ## 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] [sla_material:Prusa Orange Tough @0.1 SL1S]
inherits = *0.1_sl1s* inherits = *0.1_sl1s*
exposure_time = 2.6 exposure_time = 2.6
@ -6573,7 +6721,7 @@ nozzle_diameter = 0.6
max_layer_height = 0.40 max_layer_height = 0.40
min_layer_height = 0.15 min_layer_height = 0.15
default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
retract_length = 3.5 retract_length = 3.2
retract_before_travel = 1.5 retract_before_travel = 1.5
[printer:Original Prusa MINI & MINI+ 0.8 nozzle] [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); float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
float width = 1.5 * i_scales.x; 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);
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);
vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz; 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); 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()); this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
int vertices_count = 0; 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]; const stl_facet &facet = mesh.stl.facet_start[i];
for (int j = 0; j < 3; ++j) 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_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); 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> 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) { for (stl_vertex &v_dst : its.vertices) {
stl_vertex v_src = v_dst; stl_vertex v_src = v_dst;

View File

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

View File

@ -21,6 +21,7 @@
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/spirit/include/karma.hpp> #include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
@ -32,6 +33,8 @@ namespace pt = boost::property_tree;
#include <Eigen/Dense> #include <Eigen/Dense>
#include "miniz_extension.hpp" #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, // Slightly faster than sprintf("%.9g"), but there is an issue with the karma floating point formatter,
// https://github.com/boostorg/spirit/pull/586 // https://github.com/boostorg/spirit/pull/586
// where the exported string is one digit shorter than it should be to guarantee lossless round trip. // 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) 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); float value = 0.0f;
return (text != nullptr) ? (float)::atof(text) : 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) 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); int value = 0;
return (text != nullptr) ? ::atoi(text) : 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) 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); assert(m600_extruder_before_layer >= 0);
// Color Change or Tool Change as Color Change. // Color Change or Tool Change as Color Change.
// add tag for processor // 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"; 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 if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
// && !MMU1 // && !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 INCHES_TO_MM = 25.4f;
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2 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 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 float DEFAULT_TRAVEL_ACCELERATION = 1250.0f;
static const size_t MIN_EXTRUDERS_COUNT = 5; static const size_t MIN_EXTRUDERS_COUNT = 5;
@ -184,10 +182,8 @@ void GCodeProcessor::TimeMachine::reset()
enabled = false; enabled = false;
acceleration = 0.0f; acceleration = 0.0f;
max_acceleration = 0.0f; max_acceleration = 0.0f;
#if ENABLE_RETRACT_ACCELERATION
retract_acceleration = 0.0f; retract_acceleration = 0.0f;
max_retract_acceleration = 0.0f; max_retract_acceleration = 0.0f;
#endif // ENABLE_RETRACT_ACCELERATION
travel_acceleration = 0.0f; travel_acceleration = 0.0f;
max_travel_acceleration = 0.0f; max_travel_acceleration = 0.0f;
extrude_factor_override_percentage = 1.0f; extrude_factor_override_percentage = 1.0f;
@ -740,9 +736,7 @@ void GCodeProcessor::Result::reset() {
extruder_colors = std::vector<std::string>(); extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER); filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY); 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>(); custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
time = 0; time = 0;
} }
#else #else
@ -756,9 +750,7 @@ void GCodeProcessor::Result::reset() {
extruder_colors = std::vector<std::string>(); extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER); filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY); 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>(); custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
} }
#endif // ENABLE_GCODE_VIEWER_STATISTICS #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); 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].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_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); 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].max_retract_acceleration = max_retract_acceleration;
m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_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); 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].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_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); 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].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_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); 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].max_retract_acceleration = max_retract_acceleration;
m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_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); 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].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_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_result.id = ++s_result_id;
m_use_volumetric_e = false; m_use_volumetric_e = false;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_last_default_color_id = 0; m_last_default_color_id = 0;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
#if ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.reset(); m_options_z_corrector.reset();
@ -1741,7 +1727,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// color change tag // color change tag
if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) { if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) {
unsigned char extruder_id = 0; unsigned char extruder_id = 0;
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
static std::vector<std::string> Default_Colors = { static std::vector<std::string> Default_Colors = {
"#0B2C7A", // { 0.043f, 0.173f, 0.478f }, // bluish "#0B2C7A", // { 0.043f, 0.173f, 0.478f }, // bluish
"#1C8891", // { 0.110f, 0.533f, 0.569f }, "#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()) if (m_last_default_color_id == Default_Colors.size())
m_last_default_color_id = 0; 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()) 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 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) { if (m_extruder_id == extruder_id) {
m_cp_color.current = m_extruder_colors[extruder_id]; m_cp_color.current = m_extruder_colors[extruder_id];
store_move_vertex(EMoveType::Color_change); 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, "" }; 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); m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z #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 #endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
process_custom_gcode_time(CustomGCode::ColorChange); process_custom_gcode_time(CustomGCode::ColorChange);
process_filaments(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; return;
} }
// pause print tag // pause print tag
if (comment == reserved_tag(ETags::Pause_Print)) { if (comment == reserved_tag(ETags::Pause_Print)) {
store_move_vertex(EMoveType::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, "", "" }; 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); m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.set(); m_options_z_corrector.set();
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
process_custom_gcode_time(CustomGCode::PausePrint); process_custom_gcode_time(CustomGCode::PausePrint);
return; return;
} }
@ -1846,13 +1812,11 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// custom code tag // custom code tag
if (comment == reserved_tag(ETags::Custom_Code)) { if (comment == reserved_tag(ETags::Custom_Code)) {
store_move_vertex(EMoveType::Custom_GCode); 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, "", "" }; 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); m_result.custom_gcode_per_print_z.emplace_back(item);
#if ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_FIX_PREVIEW_OPTIONS_Z
m_options_z_corrector.set(); m_options_z_corrector.set();
#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_PREVIEW_OPTIONS_Z
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
return; return;
} }
@ -2943,22 +2907,14 @@ void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('T', value)) if (line.has_value('T', value))
#if ENABLE_RETRACT_ACCELERATION
set_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); 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 { else {
// New acceleration format, compatible with the upstream Marlin. // New acceleration format, compatible with the upstream Marlin.
if (line.has_value('P', value)) if (line.has_value('P', value))
set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('R', value)) if (line.has_value('R', value))
#if ENABLE_RETRACT_ACCELERATION
set_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); 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)) if (line.has_value('T', value))
// Interpret the T value as the travel acceleration in the new Marlin format. // Interpret the T value as the travel acceleration in the new Marlin format.
set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value); 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 float GCodeProcessor::get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{ {
size_t id = static_cast<size_t>(mode); 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; 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) void GCodeProcessor::set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
{ {
size_t id = static_cast<size_t>(mode); 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); std::min(value, m_time_processor.machines[id].max_retract_acceleration);
} }
} }
#endif // ENABLE_RETRACT_ACCELERATION
float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{ {

View File

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

View File

@ -1,7 +1,13 @@
#include "LocalesUtils.hpp" #include "LocalesUtils.hpp"
#ifdef _WIN32
#include <charconv>
#endif
#include <stdexcept> #include <stdexcept>
#include <fast_float/fast_float.h>
namespace Slic3r { namespace Slic3r {
@ -11,15 +17,15 @@ CNumericLocalesSetter::CNumericLocalesSetter()
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE); _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
m_orig_numeric_locale = std::setlocale(LC_NUMERIC, nullptr); m_orig_numeric_locale = std::setlocale(LC_NUMERIC, nullptr);
std::setlocale(LC_NUMERIC, "C"); 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_original_locale = uselocale((locale_t)0);
m_new_locale = duplocale(m_original_locale); m_new_locale = duplocale(m_original_locale);
m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_new_locale); m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_new_locale);
uselocale(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 #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 string_to_double_decimal_point(const std::string& str, size_t* pos /* = nullptr*/)
{ {
double out; double out;
std::istringstream stream(str); size_t p = fast_float::from_chars(str.data(), str.data() + str.size(), out).ptr - str.data();
if (! (stream >> out)) if (pos)
throw std::invalid_argument("string_to_double_decimal_point conversion failed."); *pos = p;
if (pos) {
if (stream.eof())
*pos = str.size();
else
*pos = stream.tellg();
}
return out; return out;
} }
std::string float_to_string_decimal_point(double value, int precision/* = -1*/) 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; std::stringstream buf;
if (precision >= 0) if (precision >= 0)
buf << std::fixed << std::setprecision(precision); buf << std::fixed << std::setprecision(precision);
buf << value; buf << value;
return buf.str(); return buf.str();
#endif
} }

View File

@ -9,7 +9,6 @@
#include "Format/AMF.hpp" #include "Format/AMF.hpp"
#include "Format/OBJ.hpp" #include "Format/OBJ.hpp"
#include "Format/PRUS.hpp"
#include "Format/STL.hpp" #include "Format/STL.hpp"
#include "Format/3mf.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")) else if (boost::algorithm::iends_with(input_file, ".3mf"))
//FIXME options & LoadAttribute::CheckVersion ? //FIXME options & LoadAttribute::CheckVersion ?
result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false); 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 else
throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension."); 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; size_t num = 0;
for (const ModelVolume *v : this->volumes) for (const ModelVolume *v : this->volumes)
if (v->is_model_part()) if (v->is_model_part())
num += v->mesh().stl.stats.number_of_facets; num += v->mesh().facets_count();
return num; 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 Transform3d mv = mi * v->get_matrix();
const TriangleMesh& hull = v->get_convex_hull(); 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) 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); 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 Transform3d mv = mi * v->get_matrix();
const TriangleMesh& hull = v->get_convex_hull(); 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) 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); 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_x = " << bb.max(0) << endl;
cout << "max_y = " << bb.max(1) << endl; cout << "max_y = " << bb.max(1) << endl;
cout << "max_z = " << bb.max(2) << 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; cout << "manifold = " << (mesh.is_manifold() ? "yes" : "no") << endl;
mesh.repair(); // this calculates number_of_parts mesh.repair(); // this calculates number_of_parts
if (mesh.needed_repair()) { if (mesh.needed_repair()) {
mesh.repair(); mesh.repair();
if (mesh.stl.stats.degenerate_facets > 0) if (mesh.stats().degenerate_facets > 0)
cout << "degenerate_facets = " << mesh.stl.stats.degenerate_facets << endl; cout << "degenerate_facets = " << mesh.stats().degenerate_facets << endl;
if (mesh.stl.stats.edges_fixed > 0) if (mesh.stats().edges_fixed > 0)
cout << "edges_fixed = " << mesh.stl.stats.edges_fixed << endl; cout << "edges_fixed = " << mesh.stats().edges_fixed << endl;
if (mesh.stl.stats.facets_removed > 0) if (mesh.stats().facets_removed > 0)
cout << "facets_removed = " << mesh.stl.stats.facets_removed << endl; cout << "facets_removed = " << mesh.stats().facets_removed << endl;
if (mesh.stl.stats.facets_added > 0) if (mesh.stats().facets_added > 0)
cout << "facets_added = " << mesh.stl.stats.facets_added << endl; cout << "facets_added = " << mesh.stats().facets_added << endl;
if (mesh.stl.stats.facets_reversed > 0) if (mesh.stats().facets_reversed > 0)
cout << "facets_reversed = " << mesh.stl.stats.facets_reversed << endl; cout << "facets_reversed = " << mesh.stats().facets_reversed << endl;
if (mesh.stl.stats.backwards_edges > 0) if (mesh.stats().backwards_edges > 0)
cout << "backwards_edges = " << mesh.stl.stats.backwards_edges << endl; 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; cout << "volume = " << mesh.volume() << endl;
} }
@ -1630,7 +1627,7 @@ std::string ModelObject::get_export_filename() const
stl_stats ModelObject::get_object_stl_stats() const stl_stats ModelObject::get_object_stl_stats() const
{ {
if (this->volumes.size() == 1) if (this->volumes.size() == 1)
return this->volumes[0]->mesh().stl.stats; return this->volumes[0]->mesh().stats();
stl_stats full_stats; stl_stats full_stats;
full_stats.volume = 0.f; 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 // fill full_stats from all objet's meshes
for (ModelVolume* volume : this->volumes) 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) // initialize full_stats (for repaired errors)
full_stats.degenerate_facets += stats.degenerate_facets; full_stats.degenerate_facets += stats.degenerate_facets;
@ -1734,7 +1731,7 @@ void ModelVolume::calculate_convex_hull()
int ModelVolume::get_mesh_errors_count() const 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 + return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges; 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->supported_facets.id());
assert(this->id() != this->seam_facets.id()); assert(this->id() != this->seam_facets.id());
assert(this->id() != this->mmu_segmentation_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(); calculate_convex_hull();
} }
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) : 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()); assert(this->config.id() == other.config.id());
this->set_material_id(other.material_id()); this->set_material_id(other.material_id());
this->config.set_new_unique_id(); this->config.set_new_unique_id();
if (mesh.stl.stats.number_of_facets > 1) if (mesh.facets_count() > 1)
calculate_convex_hull(); calculate_convex_hull();
assert(this->config.id().valid()); assert(this->config.id().valid());
assert(this->config.id() != other.config.id()); 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); 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. // Precondition: Print::validate() requires the Print::apply() to be called its invocation.
std::string Print::validate(std::string* warning) const std::string Print::validate(std::string* warning) const
{ {
@ -526,42 +528,11 @@ std::string Print::validate(std::string* warning) const
} }
if (has_custom_layering) { 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) { for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
if (idx_object == tallest_object_idx) if (idx_object == tallest_object_idx)
continue; continue;
const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object]; if (layer_height_profiles[idx_object] != layer_height_profiles[tallest_object_idx])
// 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)
return L("The Wipe tower is only supported if all objects have the same variable layer height"); 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; 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. // Slice single triangle mesh.
static std::vector<ExPolygons> slice_volume( static std::vector<ExPolygons> slice_volume(
const ModelVolume &volume, const ModelVolume &volume,
@ -65,7 +48,7 @@ static std::vector<ExPolygons> slice_volume(
{ {
std::vector<ExPolygons> layers; std::vector<ExPolygons> layers;
if (! zs.empty()) { 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) { if (its.indices.size() > 0) {
MeshSlicingParamsEx params2 { params }; MeshSlicingParamsEx params2 { params };
params2.trafo = params2.trafo * volume.get_matrix(); 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 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: // By Florens Waserfall aka @platch:
// This constant essentially describes the volumetric error at the surface which is induced // This constant essentially describes the volumetric error at the surface which is induced
// by stacking "elliptic" extrusion threads. It is empirically determined by // 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()); mesh.transform(first_instance.get_matrix(), first_instance.is_left_handed());
// 1) Collect faces from mesh. // 1) Collect faces from mesh.
m_faces.reserve(mesh.stl.stats.number_of_facets); m_faces.reserve(mesh.facets_count());
for (const stl_facet &face : mesh.stl.facet_start) { for (stl_triangle_vertex_indices face : mesh.its.indices) {
Vec3f n = face.normal.normalized(); stl_vertex vertex[3] = { mesh.its.vertices[face[0]], mesh.its.vertices[face[1]], mesh.its.vertices[face[2]] };
m_faces.emplace_back(FaceZ({ face_z_span(face), std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) })); 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. // 2) Sort faces lexicographically by their Z span.

View File

@ -41,14 +41,6 @@
//==================== //====================
#define ENABLE_2_4_0_ALPHA1 1 #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 // 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) #define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA1)
// Enable rendering seams (and other options) in preview using models // 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 // 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) #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 // 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 // Enable replacing a missing file during reload from disk command
#define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2) #define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2)
// Enable changes in preview layout // Enable changes in preview layout

View File

@ -187,6 +187,10 @@ void TriangleMesh::repair(bool update_shared_vertices)
this->repaired = true; 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"; BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() finished";
// This call should be quite cheap, a lot of code requires the indexed_triangle_set data structure, // 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; return mesh;
} }
indexed_triangle_set its_make_cone(double r, double h, double fa)
TriangleMesh make_cone(double r, double h, double fa)
{ {
Pointf3s vertices; indexed_triangle_set mesh;
std::vector<Vec3i> facets; auto& vertices = mesh.vertices;
vertices.reserve(3+size_t(2*PI/fa)); auto& facets = mesh.indices;
vertices.reserve(3+2*size_t(2*PI/fa)); 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; size_t i = 0;
for (double angle=0; angle<2*PI; angle+=fa) { for (double angle=0; angle<2*PI; angle+=fa) {
vertices.emplace_back(r*std::cos(angle), r*std::sin(angle), 0.); 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(0, 2, i+1); // close the shape
facets.emplace_back(1, i+1, 2); facets.emplace_back(1, i+1, 2);
TriangleMesh mesh(std::move(vertices), std::move(facets));
mesh.repair();
return mesh; 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 // Generates mesh for a sphere centered about the origin, using the generated angle
// to determine the granularity. // to determine the granularity.
@ -1218,7 +1228,6 @@ TriangleMesh make_sphere(double radius, double fa)
{ {
TriangleMesh mesh(its_make_sphere(radius, fa)); TriangleMesh mesh(its_make_sphere(radius, fa));
mesh.repair(); mesh.repair();
return mesh; 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); 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 } // namespace Slic3r

View File

@ -52,7 +52,6 @@ public:
TriangleMeshPtrs split() const; TriangleMeshPtrs split() const;
void merge(const TriangleMesh &mesh); void merge(const TriangleMesh &mesh);
ExPolygons horizontal_projection() const; 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. // 2D convex hull of a 3D mesh projected into the Z=0 plane.
Polygon convex_hull(); Polygon convex_hull();
BoundingBoxf3 bounding_box() const; BoundingBoxf3 bounding_box() const;
@ -80,10 +79,14 @@ public:
// Restore optional data possibly released by release_optional(). // Restore optional data possibly released by release_optional().
void restore_optional(); void restore_optional();
stl_file stl; const stl_stats& stats() const { return this->stl.stats; }
indexed_triangle_set its; indexed_triangle_set its;
bool repaired; bool repaired;
//private:
stl_file stl;
private: private:
std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const; 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 std::vector<Vec3f> &triangles);
void its_merge(indexed_triangle_set &A, const Pointf3s &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); indexed_triangle_set its_make_cube(double x, double y, double z);
TriangleMesh 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)); 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)); TriangleMesh make_cylinder(double r, double h, double fa=(2*PI/360));
indexed_triangle_set its_make_cone(double r, double h, double fa=(2*PI/360));
indexed_triangle_set its_make_sphere(double rho, double fa=(2*PI/360));
TriangleMesh 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)); TriangleMesh make_sphere(double rho, double fa=(2*PI/360));
inline BoundingBoxf3 bounding_box(const TriangleMesh &m) { return m.bounding_box(); } inline BoundingBoxf3 bounding_box(const TriangleMesh &m) { return m.bounding_box(); }

View File

@ -9,16 +9,6 @@
namespace Slic3r { 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 #ifndef NDEBUG
bool TriangleSelector::verify_triangle_midpoints(const Triangle &tr) const 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()) if (!m_triangles[facet_idx].valid())
return -1; 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)); assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
return this->select_unsplit_triangle(hit, 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 (! visited[facet]) {
if (select_triangle(facet, new_state, triangle_splitting)) { if (select_triangle(facet, new_state, triangle_splitting)) {
// add neighboring facets to list to be proccessed later // 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))) if (neighbor_idx >=0 && (m_cursor.type == SPHERE || faces_camera(neighbor_idx)))
facets_to_check.push_back(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) if (current_facet < m_orig_size_indices)
// Propagate over the original triangles. // 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); assert(neighbor_idx >= -1);
if (neighbor_idx >= 0 && !visited[neighbor_idx]) { 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. // 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 &n1 = m_face_normals[m_triangles[neighbor_idx].source_triangle];
const Vec3f &n2 = m_mesh->stl.facet_start[m_triangles[current_facet].source_triangle].normal; 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) if (std::clamp(n1.dot(n2), 0.f, 1.f) >= facet_angle_limit)
facet_queue.push(neighbor_idx); 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(m_triangles.size(), Vec3i(-1, -1, -1));
std::vector<Vec3i> neighbors_propagated(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) { 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]; neighbors_propagated[facet_idx] = neighbors[facet_idx];
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx])); assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx]));
if (m_triangles[facet_idx].is_split()) 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()) if (! m_triangles[facet_idx].valid())
return false; 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)); assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
if (! select_triangle_recursive(facet_idx, neighbors, type, triangle_splitting)) 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 bool TriangleSelector::faces_camera(int facet) const
{ {
assert(facet < m_orig_size_indices); assert(facet < m_orig_size_indices);
// The normal is cached in mesh->stl, use it. Vec3f n = m_face_normals[facet];
Vec3f normal = m_mesh->stl.facet_start[facet].normal; if (! m_cursor.uniform_scaling)
n = m_cursor.trafo_normal * n;
if (! m_cursor.uniform_scaling) { return n.dot(m_cursor.dir) < 0.;
// Transform the normal into world coords.
normal = m_cursor.trafo_normal * normal;
}
return (normal.dot(m_cursor.dir) < 0.);
} }
@ -1094,7 +1080,7 @@ void TriangleSelector::garbage_collect()
} }
TriangleSelector::TriangleSelector(const TriangleMesh& mesh) 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(); reset();
} }
@ -1107,16 +1093,17 @@ void TriangleSelector::reset()
m_invalid_triangles = 0; m_invalid_triangles = 0;
m_free_triangles_head = -1; m_free_triangles_head = -1;
m_free_vertices_head = -1; m_free_vertices_head = -1;
m_vertices.reserve(m_mesh->its.vertices.size()); m_vertices.reserve(m_mesh.its.vertices.size());
for (const stl_vertex& vert : m_mesh->its.vertices) for (const stl_vertex& vert : m_mesh.its.vertices)
m_vertices.emplace_back(vert); m_vertices.emplace_back(vert);
m_triangles.reserve(m_mesh->its.indices.size()); m_triangles.reserve(m_mesh.its.indices.size());
for (size_t i = 0; i < m_mesh->its.indices.size(); ++i) { for (size_t i = 0; i < m_mesh.its.indices.size(); ++i) {
const stl_triangle_vertex_indices &ind = m_mesh->its.indices[i]; const stl_triangle_vertex_indices &ind = m_mesh.its.indices[i];
push_triangle(ind[0], ind[1], ind[2], int(i)); push_triangle(ind[0], ind[1], ind[2], int(i));
} }
m_orig_size_vertices = int(m_vertices.size()); m_orig_size_vertices = int(m_vertices.size());
m_orig_size_indices = int(m_triangles.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) 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 (auto &triangle : out.indices)
for (int i = 0; i < 3; ++ i) 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> TriangleSelector::get_seed_fill_contour() const {
std::vector<Vec2i> edges_out; std::vector<Vec2i> edges_out;
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) { 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)); assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
this->get_seed_fill_contour_recursive(facet_idx, neighbors, neighbors, edges_out); 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. // 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. // 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. // 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. // 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. // Vector to store all parents that have offsprings.
struct ProcessingInfo { struct ProcessingInfo {
@ -1565,7 +1552,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
if (is_split) { if (is_split) {
// root is split, add it into list of parents and split it. // root is split, add it into list of parents and split it.
// then go to the next. // 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}); parents.push_back({triangle_id, neighbors, 0, num_of_children});
m_triangles[triangle_id].set_division(num_of_split_sides, special_side); m_triangles[triangle_id].set_division(num_of_split_sides, special_side);
perform_split(triangle_id, neighbors, EnforcerBlockerType::NONE); perform_split(triangle_id, neighbors, EnforcerBlockerType::NONE);

View File

@ -161,7 +161,9 @@ protected:
// Lists of vertices and triangles, both original and new // Lists of vertices and triangles, both original and new
std::vector<Vertex> m_vertices; std::vector<Vertex> m_vertices;
std::vector<Triangle> m_triangles; 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). // Number of invalid triangles (to trigger garbage collection).
int m_invalid_triangles; int m_invalid_triangles;

View File

@ -9,9 +9,7 @@
#include "3DScene.hpp" #include "3DScene.hpp"
#include "GLShader.hpp" #include "GLShader.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#if ENABLE_ENVIRONMENT_MAP || ENABLE_SINKING_CONTOURS
#include "Plater.hpp" #include "Plater.hpp"
#endif // ENABLE_ENVIRONMENT_MAP || ENABLE_SINKING_CONTOURS
#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp" #include "libslic3r/ExtrusionEntityCollection.hpp"
@ -25,9 +23,7 @@
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "libslic3r/ClipperUtils.hpp" #include "libslic3r/ClipperUtils.hpp"
#if ENABLE_SINKING_CONTOURS
#include "libslic3r/Tesselate.hpp" #include "libslic3r/Tesselate.hpp"
#endif // ENABLE_SINKING_CONTOURS
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -158,22 +154,27 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh& mesh)
} }
else { else {
#endif // ENABLE_SMOOTH_NORMALS #endif // ENABLE_SMOOTH_NORMALS
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count()); this->load_its_flat_shading(mesh.its);
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;
}
#if ENABLE_SMOOTH_NORMALS #if ENABLE_SMOOTH_NORMALS
} }
#endif // 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) void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized)
{ {
assert(this->vertices_and_normals_interleaved_VBO_id == 0); assert(this->vertices_and_normals_interleaved_VBO_id == 0);
@ -288,7 +289,6 @@ void GLIndexedVertexArray::render(
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
#if ENABLE_SINKING_CONTOURS
const float GLVolume::SinkingContours::HalfWidth = 0.25f; const float GLVolume::SinkingContours::HalfWidth = 0.25f;
void GLVolume::SinkingContours::render() void GLVolume::SinkingContours::render()
@ -357,7 +357,6 @@ void GLVolume::SinkingContours::update()
else else
m_model.reset(); 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::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 }; 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) GLVolume::GLVolume(float r, float g, float b, float a)
: m_transformed_bounding_box_dirty(true) : m_sla_shift_z(0.0)
, m_sla_shift_z(0.0)
, m_transformed_convex_hull_bounding_box_dirty(true)
#if ENABLE_SINKING_CONTOURS
, m_sinking_contours(*this) , m_sinking_contours(*this)
#endif // ENABLE_SINKING_CONTOURS
// geometry_id == 0 -> invalid // geometry_id == 0 -> invalid
, geometry_id(std::pair<size_t, size_t>(0, 0)) , geometry_id(std::pair<size_t, size_t>(0, 0))
, extruder_id(0) , extruder_id(0)
@ -399,9 +394,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, force_transparent(false) , force_transparent(false)
, force_native_color(false) , force_native_color(false)
, force_neutral_color(false) , force_neutral_color(false)
#if ENABLE_SINKING_CONTOURS
, force_sinking_contours(false) , force_sinking_contours(false)
#endif // ENABLE_SINKING_CONTOURS
, tverts_range(0, size_t(-1)) , tverts_range(0, size_t(-1))
, qverts_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 const BoundingBoxf3& GLVolume::transformed_bounding_box() const
{ {
if (!m_transformed_bounding_box.has_value()) {
const BoundingBoxf3& box = bounding_box(); 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)); 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);
BoundingBoxf3* transformed_bounding_box = const_cast<BoundingBoxf3*>(&m_transformed_bounding_box); *trans_box = box.transformed(world_matrix());
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;
} }
return *transformed_bounding_box; return *m_transformed_bounding_box;
} }
const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const
{ {
BoundingBoxf3* transformed_convex_hull_bounding_box = const_cast<BoundingBoxf3*>(&m_transformed_convex_hull_bounding_box); if (!m_transformed_convex_hull_bounding_box.has_value()) {
bool* transformed_convex_hull_bounding_box_dirty = const_cast<bool*>(&m_transformed_convex_hull_bounding_box_dirty); std::optional<BoundingBoxf3>* trans_box = const_cast<std::optional<BoundingBoxf3>*>(&m_transformed_convex_hull_bounding_box);
if (*transformed_convex_hull_bounding_box_dirty) { *trans_box = transformed_convex_hull_bounding_box(world_matrix());
*transformed_convex_hull_bounding_box = this->transformed_convex_hull_bounding_box(world_matrix());
*transformed_convex_hull_bounding_box_dirty = false;
} }
return *transformed_convex_hull_bounding_box; return *m_transformed_convex_hull_bounding_box;
} }
BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &trafo) const 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) : m_convex_hull->transformed_bounding_box(trafo) :
bounding_box().transformed(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; return transformed_convex_hull_bounding_box().max.z() < 0.0;
} }
#if ENABLE_SINKING_CONTOURS
void GLVolume::render_sinking_contours() void GLVolume::render_sinking_contours()
{ {
m_sinking_contours.render(); m_sinking_contours.render();
} }
#endif // ENABLE_SINKING_CONTOURS
std::vector<int> GLVolumeCollection::load_object( std::vector<int> GLVolumeCollection::load_object(
const ModelObject *model_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); 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); brim_mesh.translate(-brim_width, -brim_width, 0.f);
mesh.merge(brim_mesh); mesh.merge(brim_mesh);
mesh.repair();
volumes.emplace_back(new GLVolume(color)); volumes.emplace_back(new GLVolume(color));
GLVolume& v = *volumes.back(); 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 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); GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
if (to_render.empty()) if (to_render.empty())
return; return;
#endif // ENABLE_SINKING_CONTOURS
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr) if (shader == nullptr)
@ -853,7 +838,6 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
if (disable_cullface) if (disable_cullface)
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
#if ENABLE_SINKING_CONTOURS
for (GLVolumeWithIdAndZ& volume : to_render) { for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->set_render_color(); volume.first->set_render_color();
@ -903,7 +887,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
} }
if (m_show_sinking_contours) if (m_show_sinking_contours) {
for (GLVolumeWithIdAndZ& volume : to_render) { for (GLVolumeWithIdAndZ& volume : to_render) {
// render sinking contours of hovered/displaced volumes // render sinking contours of hovered/displaced volumes
if (volume.first->is_sinking() && !volume.first->is_below_printbed() && 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(); 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) if (disable_cullface)
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));

View File

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

View File

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

View File

@ -977,7 +977,7 @@ void Choice::BUILD() {
propagate_value(); propagate_value();
} ); } );
temp->Bind(wxEVT_TEXT_ENTER, [this, temp](wxEvent& e) { temp->Bind(wxEVT_TEXT_ENTER, [this](wxEvent& e) {
EnterPressed enter(this); EnterPressed enter(this);
propagate_value(); 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). // 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))); 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()) if (wxGetApp().is_gcode_viewer())
m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z; 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); load_toolpaths(gcode_result);
@ -744,9 +742,7 @@ void GCodeViewer::reset()
m_layers_z_range = { 0, 0 }; m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>(); m_roles = std::vector<ExtrusionRole>();
m_print_statistics.reset(); m_print_statistics.reset();
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
m_custom_gcode_per_print_z = std::vector<CustomGCode::Item>(); 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(); m_sequential_view.gcode_window.reset();
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
m_statistics.reset_all(); 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"; 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, 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 }, 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, double used_filament_m = 0.0, double used_filament_g = 0.0,
std::function<void()> callback = nullptr) { std::function<void()> callback = nullptr) {
@ -3446,11 +3446,7 @@ void GCodeViewer::render_legend(float& legend_height)
} }
case EViewType::ColorPrint: 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; 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; size_t total_items = 1;
for (unsigned char i : m_extruder_ids) { for (unsigned char i : m_extruder_ids) {
total_items += color_print_ranges(i, custom_gcode_per_print_z).size(); 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) { auto generate_partial_times = [this, get_used_filament_from_volume](const TimesList& times, const std::vector<double>& used_filaments) {
PartialTimes items; 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; 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(); int extruders_count = wxGetApp().extruders_edited_cnt();
std::vector<Color> last_color(extruders_count); std::vector<Color> last_color(extruders_count);
for (int i = 0; i < extruders_count; ++i) { for (int i = 0; i < extruders_count; ++i) {

View File

@ -783,9 +783,7 @@ private:
GCodeProcessor::Result::SettingsIds m_settings_ids; GCodeProcessor::Result::SettingsIds m_settings_ids;
std::array<SequentialRangeCap, 2> m_sequential_range_caps; 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; std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
public: public:
GCodeViewer(); GCodeViewer();
@ -834,10 +832,8 @@ public:
void toggle_gcode_window_visibility() { m_sequential_view.gcode_window.toggle_visibility(); } 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; } 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; } size_t get_extruders_count() { return m_extruders_count; }
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
private: private:
void load_toolpaths(const GCodeProcessor::Result& gcode_result); 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)); glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
_render_background(); _render_background();
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_objects(GLVolumeCollection::ERenderType::Opaque); _render_objects(GLVolumeCollection::ERenderType::Opaque);
#else
_render_objects();
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
if (!m_main_toolbar.is_enabled()) if (!m_main_toolbar.is_enabled())
_render_gcode(); _render_gcode();
_render_sla_slices(); _render_sla_slices();
_render_selection(); _render_selection();
_render_bed(!camera.is_looking_downward(), true); _render_bed(!camera.is_looking_downward(), true);
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_objects(GLVolumeCollection::ERenderType::Transparent); _render_objects(GLVolumeCollection::ERenderType::Transparent);
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
_render_sequential_clearance(); _render_sequential_clearance();
#if ENABLE_RENDER_SELECTION_CENTER #if ENABLE_RENDER_SELECTION_CENTER
@ -2932,7 +2926,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return; return;
} }
#if ENABLE_SINKING_CONTOURS
for (GLVolume* volume : m_volumes.volumes) { for (GLVolume* volume : m_volumes.volumes) {
volume->force_sinking_contours = false; volume->force_sinking_contours = false;
} }
@ -2944,7 +2937,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
m_dirty = true; m_dirty = true;
}; };
#endif // ENABLE_SINKING_CONTOURS
if (m_gizmos.on_mouse(evt)) { if (m_gizmos.on_mouse(evt)) {
if (wxWindow::FindFocus() != m_canvas) if (wxWindow::FindFocus() != m_canvas)
@ -2970,7 +2962,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
default: { break; } default: { break; }
} }
} }
#if ENABLE_SINKING_CONTOURS
else if (evt.Dragging()) { else if (evt.Dragging()) {
switch (m_gizmos.get_current_type()) switch (m_gizmos.get_current_type())
{ {
@ -2984,7 +2975,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
default: { break; } default: { break; }
} }
} }
#endif // ENABLE_SINKING_CONTOURS
return; return;
} }
@ -3294,10 +3284,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else else
evt.Skip(); evt.Skip();
#if ENABLE_SINKING_CONTOURS
if (m_moving) if (m_moving)
show_sinking_contours(); show_sinking_contours();
#endif // ENABLE_SINKING_CONTOURS
#ifdef __WXMSW__ #ifdef __WXMSW__
if (on_enter_workaround) 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); wxGetApp().plater()->get_bed().render_for_picking(*this, bottom, scale_factor);
} }
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type)
#else
void GLCanvas3D::_render_objects()
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
{ {
if (m_volumes.empty()) if (m_volumes.empty())
return; return;
@ -5108,20 +5091,14 @@ void GLCanvas3D::_render_objects()
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
switch (type) switch (type)
{ {
default: default:
case GLVolumeCollection::ERenderType::Opaque: 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)) { 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; 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) { 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? // Which volume to paint without the layer height profile shader?
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
}); });
@ -5130,11 +5107,7 @@ void GLCanvas3D::_render_objects()
} }
else { else {
// do not cull backfaces to show broken geometry, if any // 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) { 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); return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
}); });
} }
@ -5153,7 +5126,6 @@ void GLCanvas3D::_render_objects()
shader->start_using(); shader->start_using();
} }
} }
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
break; break;
} }
case GLVolumeCollection::ERenderType::Transparent: case GLVolumeCollection::ERenderType::Transparent:
@ -5162,9 +5134,6 @@ void GLCanvas3D::_render_objects()
break; 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(); shader->stop_using();
} }
@ -5673,11 +5642,8 @@ void GLCanvas3D::_update_volumes_hover_state()
} }
} }
} }
#if ENABLE_SINKING_CONTOURS
else if (volume.selected) else if (volume.selected)
volume.hover = GLVolume::HS_Hover; 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_toolpath_view_type(GCodeViewer::EViewType type);
void set_volumes_z_range(const std::array<double, 2>& range); void set_volumes_z_range(const std::array<double, 2>& range);
void set_toolpaths_z_range(const std::array<unsigned int, 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(); } 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(); } 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 ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
std::vector<int> load_object(const Model& model, int obj_idx); std::vector<int> load_object(const Model& model, int obj_idx);
@ -895,11 +893,7 @@ private:
void _render_background() const; void _render_background() const;
void _render_bed(bool bottom, bool show_axes); void _render_bed(bool bottom, bool show_axes);
void _render_bed_for_picking(bool bottom); void _render_bed_for_picking(bool bottom);
#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void _render_objects(GLVolumeCollection::ERenderType type); void _render_objects(GLVolumeCollection::ERenderType type);
#else
void _render_objects();
#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING
void _render_gcode(); void _render_gcode();
void _render_selection() const; void _render_selection() const;
void _render_sequential_clearance(); void _render_sequential_clearance();

View File

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

View File

@ -6,13 +6,13 @@
#include <vector> #include <vector>
#include <string> #include <string>
struct indexed_triangle_set;
namespace Slic3r { namespace Slic3r {
class TriangleMesh; class TriangleMesh;
#if ENABLE_SINKING_CONTOURS
class Polygon; class Polygon;
using Polygons = std::vector<Polygon>; using Polygons = std::vector<Polygon>;
#endif // ENABLE_SINKING_CONTOURS
namespace GUI { namespace GUI {
@ -70,10 +70,9 @@ namespace GUI {
virtual ~GLModel() { reset(); } virtual ~GLModel() { reset(); }
void init_from(const InitializationData& data); void init_from(const InitializationData& data);
void init_from(const TriangleMesh& mesh); void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox);
#if ENABLE_SINKING_CONTOURS void init_from(const indexed_triangle_set& its);
void init_from(const Polygons& polygons, float z); void init_from(const Polygons& polygons, float z);
#endif // ENABLE_SINKING_CONTOURS
bool init_from_file(const std::string& filename); bool init_from_file(const std::string& filename);
// if entity_id == -1 set the color of all entities // 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; float right = left + scaled_icons_size;
unsigned int tex_id = m_arrow_texture.texture.get_id(); 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 // arrow width and height
float arr_tex_width = (float)m_arrow_texture.texture.get_width(); float arr_tex_width = (float)m_arrow_texture.texture.get_width();
float arr_tex_height = (float)m_arrow_texture.texture.get_height(); 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 // the following line messes up the popup size the first time it is shown on wxWidgets 3.1.3
// comboCtrl->EnablePopupAnimation(false); // comboCtrl->EnablePopupAnimation(false);
#ifdef _WIN32
popup->SetFont(comboCtrl->GetFont()); popup->SetFont(comboCtrl->GetFont());
#endif // _WIN32
comboCtrl->SetPopupControl(popup); comboCtrl->SetPopupControl(popup);
wxString title = from_u8(text); wxString title = from_u8(text);
max_width = std::max(max_width, 60 + comboCtrl->GetTextExtent(title).x); 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_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ",
/* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML", /* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML",
/* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;", /* 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_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_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF",
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ", /* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",

View File

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

View File

@ -689,7 +689,7 @@ wxMenuItem* MenuFactory::append_menu_item_fix_through_netfabb(wxMenu* menu)
return nullptr; return nullptr;
wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Fix through the Netfabb"), "", wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Fix through the Netfabb"), "",
[](wxCommandEvent&) { obj_list()->fix_through_netfabb(); }, "", menu, [](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; 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"), "", wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Simplify model"), "",
[](wxCommandEvent&) { obj_list()->simplify(); }, "", menu, [](wxCommandEvent&) { obj_list()->simplify(); }, "", menu,
[]() {return plater()->can_simplify(); }, plater()); []() {return plater()->can_simplify(); }, m_parent);
menu->AppendSeparator(); menu->AppendSeparator();
return menu_item; 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"), 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); // menu->AppendSubMenu(extruder_selection_menu, name);
} }
@ -1061,6 +1061,7 @@ wxMenu* MenuFactory::multi_selection_menu()
wxMenu* menu = new MenuWithSeparators(); wxMenu* menu = new MenuWithSeparators();
append_menu_item_fix_through_netfabb(menu);
append_menu_item_reload_from_disk(menu); append_menu_item_reload_from_disk(menu);
append_menu_items_convert_unit(menu); append_menu_items_convert_unit(menu);
if (obj_list()->can_merge_to_multipart_object()) if (obj_list()->can_merge_to_multipart_object())

View File

@ -19,6 +19,7 @@
#include "Selection.hpp" #include "Selection.hpp"
#include "format.hpp" #include "format.hpp"
#include "NotificationManager.hpp" #include "NotificationManager.hpp"
#include "MsgDialog.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <wx/progdlg.h> #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()); 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 ? const stl_stats& stats = vol_idx == -1 ?
(*m_objects)[obj_idx]->get_object_stl_stats() : (*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) 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"; 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() void ObjectList::fix_through_netfabb()
{ {
int obj_idx, vol_idx; // Do not fix anything when a gizmo is open. There might be issues with updates
get_selected_item_indexes(obj_idx, vol_idx); // 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_item_error_icon(obj_idx, vol_idx);
update_info_items(obj_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() 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(); update_layers_slider_mode();
Plater* plater = wxGetApp().plater(); Plater* plater = wxGetApp().plater();
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
CustomGCode::Info ticks_info_from_model; CustomGCode::Info ticks_info_from_model;
if (wxGetApp().is_editor()) if (wxGetApp().is_editor())
ticks_info_from_model = plater->model().custom_gcode_per_print_z; 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.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_model.gcodes = m_canvas->get_custom_gcode_per_print_z(); 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); 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 //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)); 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); m_layers_slider->SetSliderValues(layers_z);
assert(m_layers_slider->GetMinValue() == 0); assert(m_layers_slider->GetMinValue() == 0);
m_layers_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1); 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); colors = wxGetApp().plater()->get_colors_for_color_print(m_gcode_result);
if (!gcode_preview_data_valid) { if (!gcode_preview_data_valid) {
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (wxGetApp().is_editor()) if (wxGetApp().is_editor())
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
else else
color_print_values = m_canvas->get_custom_gcode_per_print_z(); 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 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(); zs = m_canvas->get_gcode_layers_zs();
m_loaded = true; m_loaded = true;
} }
#if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
else if (wxGetApp().is_editor()) { 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. // Load the initial preview based on slices, not the final G-code.
m_canvas->load_preview(colors, color_print_values); m_canvas->load_preview(colors, color_print_values);
m_left_sizer->Hide(m_bottom_toolbar_panel); 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); 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) { if (!zs.empty() && !m_keep_current_preview_type) {
unsigned int number_extruders = wxGetApp().is_editor() ? unsigned int number_extruders = wxGetApp().is_editor() ?
(unsigned int)print->extruders().size() : (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_PREVIEW_LAYOUT
} }
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
if (zs.empty()) { if (zs.empty()) {
// all layers filtered out // all layers filtered out
@ -1030,23 +1011,6 @@ void Preview::load_print_as_fff(bool keep_z_range)
} else } else
update_layers_slider(zs, keep_z_range); 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() 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) { if (! cube_initialized) {
// This cannot be done in constructor, OpenGL is not yet // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
TriangleMesh mesh = make_cube(1., 1., 1.); indexed_triangle_set mesh = its_make_cube(1., 1., 1.);
mesh.translate(Vec3f(-0.5, -0.5, -0.5)); its_translate(mesh, Vec3f(-0.5, -0.5, -0.5));
const_cast<GLModel&>(cube).init_from(mesh); 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; 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_base_color = DEFAULT_BASE_COLOR;
m_drag_color = DEFAULT_DRAG_COLOR; m_drag_color = DEFAULT_DRAG_COLOR;
m_highlight_color = DEFAULT_HIGHLIGHT_COLOR; m_highlight_color = DEFAULT_HIGHLIGHT_COLOR;
m_cone.init_from(make_cone(1., 1., 2 * PI / 24)); m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24));
m_sphere.init_from(make_sphere(1., (2 * M_PI) / 24.)); m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.));
m_cylinder.init_from(make_cylinder(1., 1., 2 * PI / 24.)); m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.));
} }
void GLGizmoBase::set_hover_id(int id) void GLGizmoBase::set_hover_id(int id)

View File

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

View File

@ -2,11 +2,9 @@
#define slic3r_GLGizmoCut_hpp_ #define slic3r_GLGizmoCut_hpp_
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
#if ENABLE_SINKING_CONTOURS
#include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GLModel.hpp"
#include "libslic3r/TriangleMesh.hpp" #include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/ObjectID.hpp" #include "libslic3r/ObjectID.hpp"
#endif // ENABLE_SINKING_CONTOURS
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -26,7 +24,6 @@ class GLGizmoCut : public GLGizmoBase
bool m_keep_lower{ true }; bool m_keep_lower{ true };
bool m_rotate_lower{ false }; bool m_rotate_lower{ false };
#if ENABLE_SINKING_CONTOURS
struct CutContours struct CutContours
{ {
TriangleMesh mesh; TriangleMesh mesh;
@ -39,7 +36,6 @@ class GLGizmoCut : public GLGizmoBase
}; };
CutContours m_cut_contours; CutContours m_cut_contours;
#endif // ENABLE_SINKING_CONTOURS
public: public:
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
@ -66,9 +62,7 @@ private:
void perform_cut(const Selection& selection); void perform_cut(const Selection& selection);
double calc_projection(const Linef3& mouse_ray) const; double calc_projection(const Linef3& mouse_ray) const;
BoundingBoxf3 bounding_box() const; BoundingBoxf3 bounding_box() const;
#if ENABLE_SINKING_CONTOURS
void update_contours(); void update_contours();
#endif // ENABLE_SINKING_CONTOURS
}; };
} // namespace GUI } // 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); float dot_limit = limit.dot(down);
// Now calculate dot product of vert_direction and facets' normals. // Now calculate dot product of vert_direction and facets' normals.
int idx = -1; int idx = 0;
for (const stl_facet &facet : mv->mesh().stl.facet_start) { const indexed_triangle_set &its = mv->mesh().its;
++idx; for (stl_triangle_vertex_indices face : its.indices) {
if (facet.normal.dot(down) > dot_limit) { 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[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER);
m_triangle_selectors.back()->request_update_render_data(); 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. // 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. // 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<int> facet_queue(num_of_facets, 0);
std::vector<bool> facet_visited(num_of_facets, false); std::vector<bool> facet_visited(num_of_facets, false);
int facet_queue_cnt = 0; int facet_queue_cnt = 0;
@ -154,7 +156,7 @@ void GLGizmoFlatten::update_planes()
if (!facet_visited[facet_idx]) { if (!facet_visited[facet_idx]) {
facet_queue[facet_queue_cnt ++] = facet_idx; facet_queue[facet_queue_cnt ++] = facet_idx;
facet_visited[facet_idx] = true; facet_visited[facet_idx] = true;
normal_ptr = &ch.stl.facet_start[facet_idx].normal; normal_ptr = &face_normals[facet_idx];
m_planes.emplace_back(); m_planes.emplace_back();
break; break;
} }
@ -163,20 +165,18 @@ void GLGizmoFlatten::update_planes()
while (facet_queue_cnt > 0) { while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt]; 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) { 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) 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; facet_visited[facet_idx] = true;
for (int j = 0; j < 3; ++ j) { for (int j = 0; j < 3; ++ j)
int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j]; if (int neighbor_idx = face_neighbors[facet_idx][j]; neighbor_idx >= 0 && ! facet_visited[neighbor_idx])
if (! facet_visited[neighbor_idx])
facet_queue[facet_queue_cnt ++] = neighbor_idx; facet_queue[facet_queue_cnt ++] = neighbor_idx;
} }
} }
}
m_planes.back().normal = normal_ptr->cast<double>(); m_planes.back().normal = normal_ptr->cast<double>();
Pointf3s& verts = m_planes.back().vertices; 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) GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, 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(""); m_imgui->text("");
ImGui::Separator(); ImGui::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("first_color")); m_imgui->text(m_desc.at("first_color"));
ImGui::SameLine(combo_label_width); ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_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)) 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}; 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")); m_imgui->text(m_desc.at("second_color"));
ImGui::SameLine(combo_label_width); ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_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::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("tool_type")); 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; 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::NewLine();
ImGui::AlignTextToFramePadding();
ImGui::SameLine(tool_type_offset + m_imgui->scaled(0.f)); ImGui::SameLine(tool_type_offset + m_imgui->scaled(0.f));
ImGui::PushItemWidth(tool_type_radio_brush); ImGui::PushItemWidth(tool_type_radio_brush);
if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == GLGizmoMmuSegmentation::ToolType::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(); ImGui::Separator();
if(m_tool_type == ToolType::BRUSH) { if(m_tool_type == ToolType::BRUSH) {
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type")); m_imgui->text(m_desc.at("cursor_type"));
ImGui::NewLine(); 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; 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::SameLine(cursor_type_offset + m_imgui->scaled(0.f));
ImGui::PushItemWidth(cursor_type_radio_sphere); ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::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(); ImGui::Separator();
} else if(m_tool_type == ToolType::SMART_FILL) { } else if(m_tool_type == ToolType::SMART_FILL) {
m_imgui->text(m_desc["smart_fill_angle"] + ":");
ImGui::AlignTextToFramePadding(); 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," 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."); "placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_width); 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_center(Vec3d::Zero())
, m_starting_box_bottom_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 std::string GLGizmoMove3D::get_tooltip() const

View File

@ -8,8 +8,9 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Model.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) : GLGizmoBase(parent, icon_filename, sprite_id)
{ {
// Make sphere and save it into a vertex buffer. // Make sphere and save it into a vertex buffer.
const TriangleMesh sphere_mesh = make_sphere(1., (2*M_PI)/24.); m_vbo_sphere.load_its_flat_shading(its_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.finalize_geometry(true); m_vbo_sphere.finalize_geometry(true);
} }
// port of 948bc382655993721d93d3b9fce9b0186fcfb211 // port of 948bc382655993721d93d3b9fce9b0186fcfb211
void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate) 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; GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers;
int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt;
const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v;
for (int i = 0; i < 3; ++i) const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v;
iva.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); 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); iva.push_triangle(cnt, cnt + 1, cnt + 2);
cnt += 3; 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) 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 // Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into. // 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 " 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) ClippingPlane(const Vec3d& direction, double offset)
{ {
Vec3d norm_dir = direction.normalized(); set_normal(direction);
m_data[0] = norm_dir(0); set_offset(offset);
m_data[1] = norm_dir(1);
m_data[2] = norm_dir(2);
m_data[3] = offset;
} }
bool operator==(const ClippingPlane& cp) const { bool operator==(const ClippingPlane& cp) const {
@ -48,7 +45,13 @@ public:
} }
bool is_point_clipped(const Vec3d& point) const { return distance(point) < 0.; } 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; } void set_offset(double offset) { m_data[3] = offset; }
Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); } 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; } bool is_active() const { return m_data[3] != DBL_MAX; }
@ -113,10 +116,8 @@ public:
// during MeshRaycaster existence. // during MeshRaycaster existence.
MeshRaycaster(const TriangleMesh& mesh) MeshRaycaster(const TriangleMesh& mesh)
: m_emesh(mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length : 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, 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() void NotificationManager::SlicingProgressNotification::on_cancel_button()
{ {
if (m_cancel_callback){ if (m_cancel_callback){
m_cancel_callback(); if (!m_cancel_callback()) {
set_progress_state(SlicingProgressState::SP_NO_SLICING);
}
} }
} }
int NotificationManager::SlicingProgressNotification::get_duration() 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) { for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) { 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_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); void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
// slicing progress // 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 // percentage negative = canceled, <0-1) = progress, 1 = completed
void set_slicing_progress_percentage(const std::string& text, float percentage); void set_slicing_progress_percentage(const std::string& text, float percentage);
// hides slicing progress notification imidietly // hides slicing progress notification imidietly
@ -496,7 +496,7 @@ private:
SP_CANCELLED, // fades after 10 seconds, simple message 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 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) : ProgressBarNotification(n, id_provider, evt_handler)
, m_cancel_callback(callback) , m_cancel_callback(callback)
{ {
@ -507,7 +507,7 @@ private:
// sets text of notification - call after setting progress state // sets text of notification - call after setting progress state
void set_status_text(const std::string& text); void set_status_text(const std::string& text);
// sets cancel button callback // 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; } bool has_cancel_callback() const { return m_cancel_callback != nullptr; }
// sets SlicingProgressState, negative percent means canceled // sets SlicingProgressState, negative percent means canceled
void set_progress_state(float percent); void set_progress_state(float percent);
@ -545,7 +545,8 @@ private:
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
void on_cancel_button(); void on_cancel_button();
int get_duration() override; 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 }; SlicingProgressState m_sp_state { SlicingProgressState::SP_PROGRESS };
bool m_has_print_info { false }; bool m_has_print_info { false };
std::string m_print_info; 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 LayerRootIcon[] = "edit_layers_all";
static constexpr char LayerIcon[] = "edit_layers_some"; static constexpr char LayerIcon[] = "edit_layers_some";
static constexpr char WarningIcon[] = "exclamation"; static constexpr char WarningIcon[] = "exclamation";
static constexpr char InfoIcon[] = "objlist_info";
struct InfoItemAtributes { struct InfoItemAtributes {
std::string name; std::string name;

View File

@ -1722,7 +1722,6 @@ struct Plater::priv
#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE #endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE
void replace_with_stl(); void replace_with_stl();
void reload_all_from_disk(); 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 create_simplify_notification(const std::vector<size_t>& obj_ids);
void set_current_panel(wxPanel* panel); 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) { void Plater::priv::create_simplify_notification(const std::vector<size_t>& obj_ids) {
const uint32_t triangles_to_suggest_simplify = 1000000; const uint32_t triangles_to_suggest_simplify = 1000000;
@ -4041,12 +4019,14 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
if (evt.error()) { if (evt.error()) {
std::pair<std::string, bool> message = evt.format_error_message(); std::pair<std::string, bool> message = evt.format_error_message();
if (evt.critical_error()) { 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 don't want to pop-up a message box when tracking a pop-up menu.
// We postpone the error message instead. // We postpone the error message instead.
q->m_tracking_popup_menu_error_message = message.first; q->m_tracking_popup_menu_error_message = message.first;
else } else {
show_error(q, message.first, message.second); show_error(q, message.first, message.second);
notification_manager->set_slicing_progress_hidden();
}
} else } else
notification_manager->push_slicing_error_notification(message.first); notification_manager->push_slicing_error_notification(message.first);
// this->statusbar()->set_status_text(from_u8(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() || const bool is_some_full_instances = get_selection().is_single_full_instance() ||
get_selection().is_single_full_object() || get_selection().is_single_full_object() ||
get_selection().is_multiple_full_instance(); 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(); notification_manager->init();
auto cancel_callback = [this]() { auto cancel_callback = [this]() {
if (this->background_process.idle())
return false;
this->background_process.stop(); this->background_process.stop();
return true;
}; };
notification_manager->init_slicing_progress_notification(cancel_callback); notification_manager->init_slicing_progress_notification(cancel_callback);
notification_manager->set_fff(printer_technology == ptFFF); 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 bool Plater::priv::can_fix_through_netfabb() const
{ {
int obj_idx = get_selected_object_idx(); std::vector<int> obj_idxs, vol_idxs;
if (obj_idx < 0) sidebar->obj_list()->get_selection_indexes(obj_idxs, vol_idxs);
return false;
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); 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()); 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) { if (wxGetApp().is_gcode_viewer() && result != nullptr) {
for (const CustomGCode::Item& code : result->custom_gcode_per_print_z) { for (const CustomGCode::Item& code : result->custom_gcode_per_print_z) {
if (code.type == CustomGCode::ColorChange) if (code.type == CustomGCode::ColorChange)
@ -6241,14 +6235,11 @@ std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessor
} }
} }
else { else {
#endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER
for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z.gcodes) { for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z.gcodes) {
if (code.type == CustomGCode::ColorChange) if (code.type == CustomGCode::ColorChange)
colors.emplace_back(code.color); 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; return colors;
} }
@ -6472,7 +6463,6 @@ void Plater::suppress_background_process(const bool stop_background_process)
this->p->suppressed_backround_processing_update = true; 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::mirror(Axis axis) { p->mirror(axis); }
void Plater::split_object() { p->split_object(); } void Plater::split_object() { p->split_object(); }
void Plater::split_volume() { p->split_volume(); } void Plater::split_volume() { p->split_volume(); }

View File

@ -235,7 +235,6 @@ public:
void schedule_background_process(bool schedule = true); void schedule_background_process(bool schedule = true);
bool is_background_process_update_scheduled() const; bool is_background_process_update_scheduled() const;
void suppress_background_process(const bool stop_background_process) ; 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 send_gcode();
void eject_drive(); 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"; m_values["old_settings_layout_mode"] = (id == 0) ? "1" : "0";
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
if (!disable_new_layout) if (!disable_new_layout)
m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0";
#endif #endif
m_values["new_settings_layout_mode"] = (id == 1) ? "1" : "0";
m_values["dlg_settings_layout_mode"] = (id == dlg_id) ? "1" : "0"; m_values["dlg_settings_layout_mode"] = (id == dlg_id) ? "1" : "0";
}); });
id++; id++;

View File

@ -620,24 +620,54 @@ const GLVolume* Selection::get_volume(unsigned int volume_idx) const
const BoundingBoxf3& Selection::get_bounding_box() const const BoundingBoxf3& Selection::get_bounding_box() const
{ {
if (m_bounding_box_dirty) if (!m_bounding_box.has_value()) {
calc_bounding_box(); std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_bounding_box);
*bbox = BoundingBoxf3();
return m_bounding_box; 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 const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const
{ {
if (m_unscaled_instance_bounding_box_dirty) if (!m_unscaled_instance_bounding_box.has_value()) {
calc_unscaled_instance_bounding_box(); std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box);
return 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 const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
{ {
if (m_scaled_instance_bounding_box_dirty) if (!m_scaled_instance_bounding_box.has_value()) {
calc_scaled_instance_bounding_box(); std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box);
return 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() void Selection::start_dragging()
@ -823,10 +853,10 @@ void Selection::flattening_rotate(const Vec3d& normal)
} }
#if !DISABLE_INSTANCES_SYNCH #if !DISABLE_INSTANCES_SYNCH
// we want to synchronize z-rotation as well, otherwise the flattening behaves funny // Apply the same transformation also to other instances,
// when applied on one of several identical instances // but respect their possibly diffrent z-rotation.
if (m_mode == Instance) if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_FULL); synchronize_unselected_instances(SYNC_ROTATION_GENERAL);
#endif // !DISABLE_INSTANCES_SYNCH #endif // !DISABLE_INSTANCES_SYNCH
this->set_bounding_boxes_dirty(); 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 void Selection::render_selected_volumes() const
{ {
float color[3] = { 1.0f, 1.0f, 1.0f }; 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()); v->set_instance_offset(Z, volume->get_instance_offset().z());
break; 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: case SYNC_ROTATION_GENERAL:
// generic rotation -> update instance z with the delta of the rotation. // 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()); 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_ #ifndef slic3r_GUI_Selection_hpp_
#define slic3r_GUI_Selection_hpp_ #define slic3r_GUI_Selection_hpp_
#include <set>
#include "libslic3r/Geometry.hpp" #include "libslic3r/Geometry.hpp"
#include "GLModel.hpp" #include "GLModel.hpp"
#include <set>
#include <optional>
namespace Slic3r { namespace Slic3r {
class Shader; class Shader;
@ -203,14 +205,11 @@ private:
IndicesList m_list; IndicesList m_list;
Cache m_cache; Cache m_cache;
Clipboard m_clipboard; Clipboard m_clipboard;
BoundingBoxf3 m_bounding_box; std::optional<BoundingBoxf3> m_bounding_box;
bool m_bounding_box_dirty;
// Bounding box of a selection, with no instance scaling applied. This 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. // is useful for absolute scaling of tilted objects in world coordinate space.
BoundingBoxf3 m_unscaled_instance_bounding_box; std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
bool m_unscaled_instance_bounding_box_dirty; std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
BoundingBoxf3 m_scaled_instance_bounding_box;
bool m_scaled_instance_bounding_box_dirty;
#if ENABLE_RENDER_SELECTION_CENTER #if ENABLE_RENDER_SELECTION_CENTER
GLModel m_vbo_sphere; GLModel m_vbo_sphere;
@ -359,10 +358,7 @@ private:
void do_remove_volume(unsigned int volume_idx); void do_remove_volume(unsigned int volume_idx);
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx); void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
void do_remove_object(unsigned int object_idx); void do_remove_object(unsigned int object_idx);
void calc_bounding_box() const; void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
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 render_selected_volumes() const; void render_selected_volumes() const;
void render_synchronized_volumes() const; void render_synchronized_volumes() const;
void render_bounding_box(const BoundingBoxf3& box, float* color) const; void render_bounding_box(const BoundingBoxf3& box, float* color) const;
@ -375,10 +371,8 @@ public:
enum SyncRotationType { enum SyncRotationType {
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis. // Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
SYNC_ROTATION_NONE = 0, 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. // 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_instances(SyncRotationType sync_rotation_type);
void synchronize_unselected_volumes(); void synchronize_unselected_volumes();

View File

@ -318,7 +318,10 @@ public:
const char* what() const throw() { return "Model repair has been canceled"; } 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::mutex mutex;
std::condition_variable condition; std::condition_variable condition;
@ -337,11 +340,6 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
else else
volumes.emplace_back(model_object.volumes[volume_idx]); 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. // 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). // (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
bool success = false; bool success = false;
@ -423,21 +421,23 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
}); });
while (! finished) { while (! finished) {
condition.wait_for(lock, std::chrono::milliseconds(500), [&progress]{ return progress.updated; }); 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; canceled = true;
else
progress_dialog.Fit();
progress.updated = false; progress.updated = false;
} }
if (canceled) { if (canceled) {
// Nothing to show. // Nothing to show.
} else if (success) { } else if (success) {
Slic3r::GUI::MessageDialog dlg(nullptr, _L("Model repaired successfully"), _L("Model Repair by the Netfabb service"), wxICON_INFORMATION | wxOK); fix_result = "";
dlg.ShowModal();
} else { } else {
Slic3r::GUI::MessageDialog dlg(nullptr, _L("Model repair failed:") + " \n" + _(progress.message), _L("Model Repair by the Netfabb service"), wxICON_ERROR | wxOK); fix_result = progress.message;
dlg.ShowModal();
} }
worker_thread.join(); worker_thread.join();
return !canceled;
} }
} // namespace Slic3r } // namespace Slic3r

View File

@ -3,6 +3,8 @@
#include <string> #include <string>
class wxProgressDialog;
namespace Slic3r { namespace Slic3r {
class Model; class Model;
@ -12,12 +14,14 @@ class Print;
#ifdef HAS_WIN10SDK #ifdef HAS_WIN10SDK
extern bool is_windows10(); 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 */ #else /* HAS_WIN10SDK */
inline bool is_windows10() { return false; } 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 */ #endif /* HAS_WIN10SDK */

View File

@ -342,7 +342,7 @@ SCENARIO( "TriangleMesh: Mesh merge functions") {
cube.merge(cube2); cube.merge(cube2);
cube.repair(); cube.repair();
THEN( "There are twice as many facets in the merged mesh as the original.") { 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/AMF.hpp"
#include "libslic3r/Format/3mf.hpp" #include "libslic3r/Format/3mf.hpp"
#include "libslic3r/Format/OBJ.hpp" #include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/PRUS.hpp"
#include "libslic3r/Format/STL.hpp" #include "libslic3r/Format/STL.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
%} %}