Merge branch 'master' into dk_remote_devices

This commit is contained in:
David Kocik 2019-12-17 14:27:37 +01:00
commit 92c6f30094
18 changed files with 429 additions and 315 deletions

View File

@ -6,4 +6,10 @@ prusaslicer_add_cmake_project(
# URL https://github.com/CGAL/cgal/archive/releases/CGAL-5.0.zip # URL https://github.com/CGAL/cgal/archive/releases/CGAL-5.0.zip
# URL_HASH SHA256=bd9327be903ab7ee379a8a7a0609eba0962f5078d2497cf8e13e8e1598584154 # URL_HASH SHA256=bd9327be903ab7ee379a8a7a0609eba0962f5078d2497cf8e13e8e1598584154
DEPENDS dep_boost dep_GMP dep_MPFR DEPENDS dep_boost dep_GMP dep_MPFR
)
ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix
DEPENDEES install
COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake
WORKING_DIRECTORY "${DESTDIR}/usr/local/lib/cmake/CGAL"
) )

2
deps/GMP/GMP.cmake vendored
View File

@ -20,7 +20,7 @@ else ()
ExternalProject_Add(dep_GMP ExternalProject_Add(dep_GMP
URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2 URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2
BUILD_IN_SOURCE ON BUILD_IN_SOURCE ON
CONFIGURE_COMMAND ./configure --enable-shared=no --enable-static=yes "--prefix=${DESTDIR}/usr/local" --with-pic CONFIGURE_COMMAND ./configure --enable-shared=no --enable-cxx=yes --enable-static=yes "--prefix=${DESTDIR}/usr/local" --with-pic
BUILD_COMMAND make -j BUILD_COMMAND make -j
INSTALL_COMMAND make install INSTALL_COMMAND make install
) )

View File

@ -15,5 +15,5 @@ add_library(hidapi STATIC ${HIDAPI_IMPL})
if (CMAKE_SYSTEM_NAME STREQUAL "Linux") if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely. # Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely.
# target_link_libraries(hidapi udev) # target_link_libraries(hidapi udev)
target_link_libraries(hidapi) target_link_libraries(hidapi dl)
endif() endif()

5
src/hidapi/README.md Normal file
View File

@ -0,0 +1,5 @@
** hidapi is a c++ library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows.**
For more information go to https://github.com/libusb/hidapi
THIS DIRECTORY CONTAINS THE hidapi-0.9.0 7da5cc9 SOURCE DISTRIBUTION.

View File

@ -43,6 +43,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_closest_point(std::vector<En
assert(next_idx < end_points.size()); assert(next_idx < end_points.size());
EndPointType &end_point = end_points[next_idx]; EndPointType &end_point = end_points[next_idx];
end_point.chain_id = 1; end_point.chain_id = 1;
out.emplace_back(next_idx / 2, (next_idx & 1) != 0);
this_idx = next_idx ^ 1; this_idx = next_idx ^ 1;
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -72,7 +73,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
else if (num_segments == 1) else if (num_segments == 1)
{ {
// Just sort the end points so that the first point visited is closest to start_near. // Just sort the end points so that the first point visited is closest to start_near.
out.emplace_back(0, start_near != nullptr && out.emplace_back(0, could_reverse_func(0) && start_near != nullptr &&
(end_point_func(0, true) - *start_near).template cast<double>().squaredNorm() < (end_point_func(0, false) - *start_near).template cast<double>().squaredNorm()); (end_point_func(0, true) - *start_near).template cast<double>().squaredNorm() < (end_point_func(0, false) - *start_near).template cast<double>().squaredNorm());
} }
else else
@ -999,13 +1000,13 @@ std::vector<std::pair<size_t, bool>> chain_extrusion_entities(std::vector<Extrus
auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); }; auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); };
auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); }; auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); };
std::vector<std::pair<size_t, bool>> out = chain_segments_greedy_constrained_reversals<Point, decltype(segment_end_point), decltype(could_reverse)>(segment_end_point, could_reverse, entities.size(), start_near); std::vector<std::pair<size_t, bool>> out = chain_segments_greedy_constrained_reversals<Point, decltype(segment_end_point), decltype(could_reverse)>(segment_end_point, could_reverse, entities.size(), start_near);
for (size_t i = 0; i < entities.size(); ++ i) { for (std::pair<size_t, bool> &segment : out) {
ExtrusionEntity *ee = entities[i]; ExtrusionEntity *ee = entities[segment.first];
if (ee->is_loop()) if (ee->is_loop())
// Ignore reversals for loops, as the start point equals the end point. // Ignore reversals for loops, as the start point equals the end point.
out[i].second = false; segment.second = false;
// Is can_reverse() respected by the reversals? // Is can_reverse() respected by the reversals?
assert(entities[i]->can_reverse() || ! out[i].second); assert(ee->can_reverse() || ! segment.second);
} }
return out; return out;
} }

View File

@ -224,38 +224,14 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
// Based on the work of @platsch // Based on the work of @platsch
// Fill layer_height_profile by heights ensuring a prescribed maximum cusp height. // Fill layer_height_profile by heights ensuring a prescribed maximum cusp height.
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slicing_params, const ModelObject& object, float quality_factor)
std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slicing_params,
const ModelObject& object, float cusp_value)
#else
std::vector<coordf_t> layer_height_profile_adaptive(
const SlicingParameters &slicing_params,
const t_layer_config_ranges & /* layer_config_ranges */,
const ModelVolumePtrs &volumes)
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
{ {
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// 1) Initialize the SlicingAdaptive class with the object meshes. // 1) Initialize the SlicingAdaptive class with the object meshes.
SlicingAdaptive as; SlicingAdaptive as;
as.set_slicing_parameters(slicing_params); as.set_slicing_parameters(slicing_params);
as.set_object(object); as.prepare(object);
#else
// 1) Initialize the SlicingAdaptive class with the object meshes.
SlicingAdaptive as;
as.set_slicing_parameters(slicing_params);
for (const ModelVolume* volume : volumes)
if (volume->is_model_part())
as.add_mesh(&volume->mesh());
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
as.prepare();
// 2) Generate layers using the algorithm of @platsch // 2) Generate layers using the algorithm of @platsch
// loop until we have at least one layer and the max slice_z reaches the object height
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
double cusp_value = 0.2;
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
std::vector<double> layer_height_profile; std::vector<double> layer_height_profile;
layer_height_profile.push_back(0.0); layer_height_profile.push_back(0.0);
layer_height_profile.push_back(slicing_params.first_object_layer_height); layer_height_profile.push_back(slicing_params.first_object_layer_height);
@ -263,39 +239,41 @@ std::vector<coordf_t> layer_height_profile_adaptive(
layer_height_profile.push_back(slicing_params.first_object_layer_height); layer_height_profile.push_back(slicing_params.first_object_layer_height);
layer_height_profile.push_back(slicing_params.first_object_layer_height); layer_height_profile.push_back(slicing_params.first_object_layer_height);
} }
double slice_z = slicing_params.first_object_layer_height; double print_z = slicing_params.first_object_layer_height;
int current_facet = 0; // last facet visited by the as.next_layer_height() function, where the facets are sorted by their increasing Z span.
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE size_t current_facet = 0;
while (slice_z <= slicing_params.object_print_z_height()) { // loop until we have at least one layer and the max slice_z reaches the object height
double height = slicing_params.max_layer_height; while (print_z + EPSILON < slicing_params.object_print_z_height()) {
#else float height = slicing_params.max_layer_height;
double height = slicing_params.first_object_layer_height;
while ((slice_z - height) <= slicing_params.object_print_z_height()) {
height = 999.0;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Slic3r::debugf "\n Slice layer: %d\n", $id; // Slic3r::debugf "\n Slice layer: %d\n", $id;
// determine next layer height // determine next layer height
double cusp_height = as.cusp_height((float)slice_z, cusp_value, current_facet); float cusp_height = as.next_layer_height(float(print_z), quality_factor, current_facet);
#if 0
// check for horizontal features and object size // check for horizontal features and object size
/* if (this->config.match_horizontal_surfaces.value) {
if($self->config->get_value('match_horizontal_surfaces')) { coordf_t horizontal_dist = as.horizontal_facet_distance(print_z + height, min_layer_height);
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height); if ((horizontal_dist < min_layer_height) && (horizontal_dist > 0)) {
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) { #ifdef SLIC3R_DEBUG
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist; std::cout << "Horizontal feature ahead, distance: " << horizontal_dist << std::endl;
# can we shrink the current layer a bit? #endif
if($cusp_height-($min_height-$horizontal_dist) > $min_height) { // can we shrink the current layer a bit?
# yes we can if (height-(min_layer_height - horizontal_dist) > min_layer_height) {
$cusp_height = $cusp_height-($min_height-$horizontal_dist); // yes we can
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height; height -= (min_layer_height - horizontal_dist);
}else{ #ifdef SLIC3R_DEBUG
# no, current layer would become too thin std::cout << "Shrink layer height to " << height << std::endl;
$cusp_height = $cusp_height+$horizontal_dist; #endif
Slic3r::debugf "Widen layer height to %f\n", $cusp_height; } else {
// no, current layer would become too thin
height += horizontal_dist;
#ifdef SLIC3R_DEBUG
std::cout << "Widen layer height to " << height << std::endl;
#endif
} }
} }
} }
*/ #endif
height = std::min(cusp_height, height); height = std::min(cusp_height, height);
// apply z-gradation // apply z-gradation
@ -308,22 +286,22 @@ std::vector<coordf_t> layer_height_profile_adaptive(
// look for an applicable custom range // look for an applicable custom range
/* /*
if (my $range = first { $_->[0] <= $slice_z && $_->[1] > $slice_z } @{$self->layer_height_ranges}) { if (my $range = first { $_->[0] <= $print_z && $_->[1] > $print_z } @{$self->layer_height_ranges}) {
$height = $range->[2]; $height = $range->[2];
# if user set custom height to zero we should just skip the range and resume slicing over it # if user set custom height to zero we should just skip the range and resume slicing over it
if ($height == 0) { if ($height == 0) {
$slice_z += $range->[1] - $range->[0]; $print_z += $range->[1] - $range->[0];
next; next;
} }
} }
*/ */
layer_height_profile.push_back(slice_z); layer_height_profile.push_back(print_z);
layer_height_profile.push_back(height); layer_height_profile.push_back(height);
slice_z += height; print_z += height;
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
layer_height_profile.push_back(slice_z); layer_height_profile.push_back(print_z);
layer_height_profile.push_back(height); layer_height_profile.push_back(height);
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
} }
@ -722,11 +700,7 @@ int generate_layer_height_texture(
const Vec3crd &color1 = palette_raw[idx1]; const Vec3crd &color1 = palette_raw[idx1];
const Vec3crd &color2 = palette_raw[idx2]; const Vec3crd &color2 = palette_raw[idx2];
coordf_t z = cell_to_z * coordf_t(cell); coordf_t z = cell_to_z * coordf_t(cell);
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE assert(lo - EPSILON <= z && z <= hi + EPSILON);
assert((lo - EPSILON <= z) && (z <= hi + EPSILON));
#else
assert(z >= lo && z <= hi);
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Intensity profile to visualize the layers. // Intensity profile to visualize the layers.
coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h); coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h);
// Color mapping from layer height to RGB. // Color mapping from layer height to RGB.

View File

@ -18,12 +18,7 @@ namespace Slic3r
class PrintConfig; class PrintConfig;
class PrintObjectConfig; class PrintObjectConfig;
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
class ModelObject; class ModelObject;
#else
class ModelVolume;
typedef std::vector<ModelVolume*> ModelVolumePtrs;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Parameters to guide object slicing and support generation. // Parameters to guide object slicing and support generation.
// The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow // The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow
@ -142,10 +137,9 @@ extern std::vector<coordf_t> layer_height_profile_from_ranges(
const SlicingParameters &slicing_params, const SlicingParameters &slicing_params,
const t_layer_config_ranges &layer_config_ranges); const t_layer_config_ranges &layer_config_ranges);
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
extern std::vector<double> layer_height_profile_adaptive( extern std::vector<double> layer_height_profile_adaptive(
const SlicingParameters& slicing_params, const SlicingParameters& slicing_params,
const ModelObject& object, float cusp_value); const ModelObject& object, float quality_factor);
struct HeightProfileSmoothingParams struct HeightProfileSmoothingParams
{ {
@ -159,12 +153,6 @@ struct HeightProfileSmoothingParams
extern std::vector<double> smooth_height_profile( extern std::vector<double> smooth_height_profile(
const std::vector<double>& profile, const SlicingParameters& slicing_params, const std::vector<double>& profile, const SlicingParameters& slicing_params,
const HeightProfileSmoothingParams& smoothing_params); const HeightProfileSmoothingParams& smoothing_params);
#else
extern std::vector<coordf_t> layer_height_profile_adaptive(
const SlicingParameters &slicing_params,
const t_layer_config_ranges &layer_config_ranges,
const ModelVolumePtrs &volumes);
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
enum LayerHeightEditActionType : unsigned int { enum LayerHeightEditActionType : unsigned int {
LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0, LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0,

View File

@ -1,156 +1,211 @@
#include "libslic3r.h" #include "libslic3r.h"
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
#include "Model.hpp" #include "Model.hpp"
#else
#include "TriangleMesh.hpp" #include "TriangleMesh.hpp"
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
#include "SlicingAdaptive.hpp" #include "SlicingAdaptive.hpp"
#include <boost/log/trivial.hpp>
// Based on the work of Florens Waserfall (@platch on github)
// and his paper
// Florens Wasserfall, Norman Hendrich, Jianwei Zhang:
// Adaptive Slicing for the FDM Process Revisited
// 13th IEEE Conference on Automation Science and Engineering (CASE-2017), August 20-23, Xi'an, China. DOI: 10.1109/COASE.2017.8256074
// https://tams.informatik.uni-hamburg.de/publications/2017/Adaptive%20Slicing%20for%20the%20FDM%20Process%20Revisited.pdf
// Vojtech believes that there is a bug in @platch's derivation of the triangle area error metric.
// Following Octave code paints graphs of recommended layer height versus surface slope angle.
#if 0
adeg=0:1:85;
a=adeg*pi/180;
t=tan(a);
tsqr=sqrt(tan(a));
lerr=1./cos(a);
lerr2=1./(0.3+cos(a));
plot(adeg, t, 'b', adeg, sqrt(t), 'g', adeg, 0.5 * lerr, 'm', adeg, 0.5 * lerr2, 'r')
xlabel("angle(deg), 0 - horizontal wall, 90 - vertical wall");
ylabel("layer height");
legend("tan(a) as cura - topographic lines distance limit", "sqrt(tan(a)) as PrusaSlicer - error triangle area limit", "old slic3r - max distance metric", "new slic3r - Waserfall paper");
#endif
#ifndef NDEBUG
#define ADAPTIVE_LAYER_HEIGHT_DEBUG
#endif /* NDEBUG */
namespace Slic3r namespace Slic3r
{ {
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static inline std::pair<float, float> face_z_span(const stl_facet &f)
void SlicingAdaptive::clear()
{
m_meshes.clear();
m_faces.clear();
m_face_normal_z.clear();
}
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
std::pair<float, float> face_z_span(const stl_facet *f)
{ {
return std::pair<float, float>( return std::pair<float, float>(
std::min(std::min(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)), 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))); std::max(std::max(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)));
} }
void SlicingAdaptive::prepare() // By Florens Waserfall aka @platch:
// This constant essentially describes the volumetric error at the surface which is induced
// by stacking "elliptic" extrusion threads. It is empirically determined by
// 1. measuring the surface profile of printed parts to find
// the ratio between layer height and profile height and then
// 2. computing the geometric difference between the model-surface and the elliptic profile.
//
// The definition of the roughness formula is in
// https://tams.informatik.uni-hamburg.de/publications/2017/Adaptive%20Slicing%20for%20the%20FDM%20Process%20Revisited.pdf
// (page 51, formula (8))
// Currenty @platch's error metric formula is not used.
static constexpr double SURFACE_CONST = 0.18403;
// for a given facet, compute maximum height within the allowed surface roughness / stairstepping deviation
static inline float layer_height_from_slope(const SlicingAdaptive::FaceZ &face, float max_surface_deviation)
{ {
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // @platch's formula, see his paper "Adaptive Slicing for the FDM Process Revisited".
if (m_object == nullptr) // return float(max_surface_deviation / (SURFACE_CONST + 0.5 * std::abs(normal_z)));
return;
// Constant stepping in horizontal direction, as used by Cura.
// return (face.n_cos > 1e-5) ? float(max_surface_deviation * face.n_sin / face.n_cos) : FLT_MAX;
m_faces.clear(); // Constant error measured as an area of the surface error triangle, Vojtech's formula.
m_face_normal_z.clear(); // return (face.n_cos > 1e-5) ? float(1.44 * max_surface_deviation * sqrt(face.n_sin / face.n_cos)) : FLT_MAX;
m_mesh = m_object->raw_mesh(); // Constant error measured as an area of the surface error triangle, Vojtech's formula with clamping to roughness at 90 degrees.
const ModelInstance* first_instance = m_object->instances.front(); return std::min(max_surface_deviation / 0.184f, (face.n_cos > 1e-5) ? float(1.44 * max_surface_deviation * sqrt(face.n_sin / face.n_cos)) : FLT_MAX);
m_mesh.transform(first_instance->get_matrix(), first_instance->is_left_handed());
// Constant stepping along the surface, equivalent to the "surface roughness" metric by Perez and later Pandey et all, see @platch's paper for references.
// return float(max_surface_deviation * face.n_sin);
}
void SlicingAdaptive::clear()
{
m_faces.clear();
}
void SlicingAdaptive::prepare(const ModelObject &object)
{
this->clear();
TriangleMesh mesh = object.raw_mesh();
const ModelInstance &first_instance = *object.instances.front();
mesh.transform(first_instance.get_matrix(), first_instance.is_left_handed());
// 1) Collect faces from mesh. // 1) Collect faces from mesh.
m_faces.reserve(m_mesh.stl.stats.number_of_facets); m_faces.reserve(mesh.stl.stats.number_of_facets);
for (stl_facet& face : m_mesh.stl.facet_start) for (const stl_facet &face : mesh.stl.facet_start) {
{ Vec3f n = face.normal.normalized();
face.normal.normalize(); m_faces.emplace_back(FaceZ({ face_z_span(face), std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
m_faces.emplace_back(&face);
} }
#else
// 1) Collect faces of all meshes.
int nfaces_total = 0;
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
nfaces_total += (*it_mesh)->stl.stats.number_of_facets;
m_faces.reserve(nfaces_total);
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
for (const stl_facet& face : (*it_mesh)->stl.facet_start)
m_faces.emplace_back(&face);
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// 2) Sort faces lexicographically by their Z span. // 2) Sort faces lexicographically by their Z span.
std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { return face_z_span(f1) < face_z_span(f2); }); std::sort(m_faces.begin(), m_faces.end(), [](const FaceZ &f1, const FaceZ &f2) { return f1.z_span < f2.z_span; });
// 3) Generate Z components of the facet normals.
m_face_normal_z.assign(m_faces.size(), 0.0f);
for (size_t iface = 0; iface < m_faces.size(); ++ iface)
m_face_normal_z[iface] = m_faces[iface]->normal(2);
} }
float SlicingAdaptive::cusp_height(float z, float cusp_value, int &current_facet) // current_facet is in/out parameter, rememebers the index of the last face of m_faces visited,
// where this function will start from.
// print_z - the top print surface of the previous layer.
// returns height of the next layer.
float SlicingAdaptive::next_layer_height(const float print_z, float quality_factor, size_t &current_facet)
{ {
float height = (float)m_slicing_params.max_layer_height; float height = (float)m_slicing_params.max_layer_height;
bool first_hit = false;
float max_surface_deviation;
{
#if 0
// @platch's formula for quality:
double delta_min = SURFACE_CONST * m_slicing_params.min_layer_height;
double delta_mid = (SURFACE_CONST + 0.5) * m_slicing_params.layer_height;
double delta_max = (SURFACE_CONST + 0.5) * m_slicing_params.max_layer_height;
#else
// Vojtech's formula for triangle area error metric.
double delta_min = m_slicing_params.min_layer_height;
double delta_mid = m_slicing_params.layer_height;
double delta_max = m_slicing_params.max_layer_height;
#endif
max_surface_deviation = (quality_factor < 0.5f) ?
lerp(delta_min, delta_mid, 2. * quality_factor) :
lerp(delta_max, delta_mid, 2. * (1. - quality_factor));
}
// find all facets intersecting the slice-layer // find all facets intersecting the slice-layer
int ordered_id = current_facet; size_t ordered_id = current_facet;
for (; ordered_id < int(m_faces.size()); ++ ordered_id) { {
std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); bool first_hit = false;
// facet's minimum is higher than slice_z -> end loop for (; ordered_id < m_faces.size(); ++ ordered_id) {
if (zspan.first >= z) const std::pair<float, float> &zspan = m_faces[ordered_id].z_span;
break; // facet's minimum is higher than slice_z -> end loop
// facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point if (zspan.first >= print_z)
if (zspan.second > z) { break;
// first event? // facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
if (! first_hit) { if (zspan.second > print_z) {
first_hit = true; // first event?
current_facet = ordered_id; if (! first_hit) {
} first_hit = true;
// skip touching facets which could otherwise cause small cusp values current_facet = ordered_id;
if (zspan.second <= z + EPSILON) }
continue; // skip touching facets which could otherwise cause small cusp values
// compute cusp-height for this facet and store minimum of all heights if (zspan.second < print_z + EPSILON)
float normal_z = m_face_normal_z[ordered_id]; continue;
height = std::min(height, (normal_z == 0.0f) ? (float)m_slicing_params.max_layer_height : std::abs(cusp_value / normal_z)); // compute cusp-height for this facet and store minimum of all heights
} height = std::min(height, layer_height_from_slope(m_faces[ordered_id], max_surface_deviation));
}
}
} }
// lower height limit due to printer capabilities // lower height limit due to printer capabilities
height = std::max(height, float(m_slicing_params.min_layer_height)); height = std::max(height, float(m_slicing_params.min_layer_height));
// check for sloped facets inside the determined layer and correct height if necessary // check for sloped facets inside the determined layer and correct height if necessary
if (height > m_slicing_params.min_layer_height) { if (height > float(m_slicing_params.min_layer_height)) {
for (; ordered_id < int(m_faces.size()); ++ ordered_id) { for (; ordered_id < m_faces.size(); ++ ordered_id) {
std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]); const std::pair<float, float> &zspan = m_faces[ordered_id].z_span;
// facet's minimum is higher than slice_z + height -> end loop // facet's minimum is higher than slice_z + height -> end loop
if (zspan.first >= z + height) if (zspan.first >= print_z + height)
break; break;
// skip touching facets which could otherwise cause small cusp values // skip touching facets which could otherwise cause small cusp values
if (zspan.second <= z + EPSILON) if (zspan.second < print_z + EPSILON)
continue; continue;
// Compute cusp-height for this facet and check against height. // Compute cusp-height for this facet and check against height.
float normal_z = m_face_normal_z[ordered_id]; float reduced_height = layer_height_from_slope(m_faces[ordered_id], max_surface_deviation);
float cusp = (normal_z == 0.0f) ? (float)m_slicing_params.max_layer_height : std::abs(cusp_value / normal_z);
float z_diff = zspan.first - z; float z_diff = zspan.first - print_z;
if (reduced_height < z_diff) {
// handle horizontal facets assert(z_diff < height + EPSILON);
if (normal_z > 0.999f) { // The currently visited triangle's slope limits the next layer height so much, that
// Slic3r::debugf "cusp computation, height is reduced from %f", $height; // the lowest point of the currently visible triangle is already above the newly proposed layer height.
// This means, that we need to limit the layer height so that the offending newly visited triangle
// is just above of the new layer.
#ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
BOOST_LOG_TRIVIAL(trace) << "cusp computation, height is reduced from " << height << "to " << z_diff << " due to z-diff";
#endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
height = z_diff; height = z_diff;
// Slic3r::debugf "to %f due to near horizontal facet\n", $height; } else if (reduced_height < height) {
} else if (cusp > z_diff) { #ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
if (cusp < height) { BOOST_LOG_TRIVIAL(trace) << "adaptive layer computation: height is reduced from " << height << "to " << reduced_height << " due to higher facet";
// Slic3r::debugf "cusp computation, height is reduced from %f", $height; #endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
height = cusp; height = reduced_height;
// Slic3r::debugf "to %f due to new cusp height\n", $height;
}
} else {
// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
height = z_diff;
// Slic3r::debugf "to z-diff: %f\n", $height;
} }
} }
// lower height limit due to printer capabilities again // lower height limit due to printer capabilities again
height = std::max(height, float(m_slicing_params.min_layer_height)); height = std::max(height, float(m_slicing_params.min_layer_height));
} }
// Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height; #ifdef ADAPTIVE_LAYER_HEIGHT_DEBUG
BOOST_LOG_TRIVIAL(trace) << "adaptive layer computation, layer-bottom at z:" << print_z << ", quality_factor:" << quality_factor << ", resulting layer height:" << height;
#endif /* ADAPTIVE_LAYER_HEIGHT_DEBUG */
return height; return height;
} }
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Returns the distance to the next horizontal facet in Z-dir // Returns the distance to the next horizontal facet in Z-dir
// to consider horizontal object features in slice thickness // to consider horizontal object features in slice thickness
float SlicingAdaptive::horizontal_facet_distance(float z) float SlicingAdaptive::horizontal_facet_distance(float z)
{ {
for (size_t i = 0; i < m_faces.size(); ++ i) { for (size_t i = 0; i < m_faces.size(); ++ i) {
std::pair<float, float> zspan = face_z_span(m_faces[i]); std::pair<float, float> zspan = m_faces[i].z_span;
// facet's minimum is higher than max forward distance -> end loop // facet's minimum is higher than max forward distance -> end loop
if (zspan.first > z + m_slicing_params.max_layer_height) if (zspan.first > z + m_slicing_params.max_layer_height)
break; break;
// min_z == max_z -> horizontal facet // min_z == max_z -> horizontal facet
if ((zspan.first > z) && (zspan.first == zspan.second)) if (zspan.first > z && zspan.first == zspan.second)
return zspan.first - z; return zspan.first - z;
} }
@ -158,6 +213,5 @@ float SlicingAdaptive::horizontal_facet_distance(float z)
return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ? return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ?
std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height; std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height;
} }
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
}; // namespace Slic3r }; // namespace Slic3r

View File

@ -5,50 +5,36 @@
#include "Slicing.hpp" #include "Slicing.hpp"
#include "admesh/stl.h" #include "admesh/stl.h"
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
#include "TriangleMesh.hpp"
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
namespace Slic3r namespace Slic3r
{ {
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
class ModelVolume; class ModelVolume;
#else
class TriangleMesh;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
class SlicingAdaptive class SlicingAdaptive
{ {
public: public:
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void clear();
void clear(); void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; }
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void prepare(const ModelObject &object);
void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; } // Return next layer height starting from the last print_z, using a quality measure
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // (quality in range from 0 to 1, 0 - highest quality at low layer heights, 1 - lowest print quality at high layer heights).
void set_object(const ModelObject& object) { m_object = &object; } // The layer height curve shall be centered roughly around the default profile's layer height for quality 0.5.
#else float next_layer_height(const float print_z, float quality, size_t &current_facet);
void add_mesh(const TriangleMesh* mesh) { m_meshes.push_back(mesh); }
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void prepare();
float cusp_height(float z, float cusp_value, int &current_facet);
#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
float horizontal_facet_distance(float z); float horizontal_facet_distance(float z);
#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
struct FaceZ {
std::pair<float, float> z_span;
// Cosine of the normal vector towards the Z axis.
float n_cos;
// Sine of the normal vector towards the Z axis.
float n_sin;
};
protected: protected:
SlicingParameters m_slicing_params; SlicingParameters m_slicing_params;
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE std::vector<FaceZ> m_faces;
const ModelObject* m_object;
TriangleMesh m_mesh;
#else
std::vector<const TriangleMesh*> m_meshes;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Collected faces of all meshes, sorted by raising Z of the bottom most face.
std::vector<const stl_facet*> m_faces;
// Z component of face normals, normalized.
std::vector<float> m_face_normal_z;
}; };
}; // namespace Slic3r }; // namespace Slic3r

View File

@ -53,4 +53,7 @@
// Enable selection for missing files in reload from disk command // Enable selection for missing files in reload from disk command
#define ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION (1 && ENABLE_2_2_0_ALPHA1) #define ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION (1 && ENABLE_2_2_0_ALPHA1)
// Enable closing 3Dconnextion imgui settings dialog by clicking on [X] and [Close] buttons
#define ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG (1 && ENABLE_2_2_0_ALPHA1)
#endif // _technologies_h_ #endif // _technologies_h_

View File

@ -133,7 +133,7 @@ GLCanvas3D::LayersEditing::LayersEditing()
, m_slicing_parameters(nullptr) , m_slicing_parameters(nullptr)
, m_layer_height_profile_modified(false) , m_layer_height_profile_modified(false)
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
, m_adaptive_cusp(0.0f) , m_adaptive_quality(0.5f)
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
, state(Unknown) , state(Unknown)
, band_width(2.0f) , band_width(2.0f)
@ -268,24 +268,24 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
ImGui::Separator(); ImGui::Separator();
if (imgui.button(_(L("Adaptive")))) if (imgui.button(_(L("Adaptive"))))
wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_cusp)); wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_quality));
ImGui::SameLine(); ImGui::SameLine();
float text_align = ImGui::GetCursorPosX(); float text_align = ImGui::GetCursorPosX();
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
imgui.text(_(L("Cusp (mm)"))); imgui.text(_(L("Quality / Speed")));
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::TextUnformatted(_(L("I am a tooltip"))); ImGui::TextUnformatted(_(L("Higher print quality versus higher print speed.")));
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(); ImGui::SameLine();
float widget_align = ImGui::GetCursorPosX(); float widget_align = ImGui::GetCursorPosX();
ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f); ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f);
m_adaptive_cusp = clamp(0.0f, 0.5f * (float)m_slicing_parameters->layer_height, m_adaptive_cusp); m_adaptive_quality = clamp(0.0f, 1.f, m_adaptive_quality);
ImGui::SliderFloat("", &m_adaptive_cusp, 0.0f, 0.5f * (float)m_slicing_parameters->layer_height, "%.3f"); ImGui::SliderFloat("", &m_adaptive_quality, 0.0f, 1.f, "%.2f");
ImGui::Separator(); ImGui::Separator();
if (imgui.button(_(L("Smooth")))) if (imgui.button(_(L("Smooth"))))
@ -645,10 +645,10 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
} }
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp) void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor)
{ {
this->update_slicing_parameters(); this->update_slicing_parameters();
m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, cusp); m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, quality_factor);
const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile; const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile;
m_layers_texture.valid = false; m_layers_texture.valid = false;
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
@ -712,11 +712,6 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters()
m_slicing_parameters = new SlicingParameters(); m_slicing_parameters = new SlicingParameters();
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z); *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z);
} }
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
if (m_adaptive_cusp == 0.0f)
m_adaptive_cusp = 0.25f * m_slicing_parameters->layer_height;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
} }
float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas) float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas)
@ -1688,10 +1683,10 @@ void GLCanvas3D::reset_layer_height_profile()
m_dirty = true; m_dirty = true;
} }
void GLCanvas3D::adaptive_layer_height_profile(float cusp) void GLCanvas3D::adaptive_layer_height_profile(float quality_factor)
{ {
wxGetApp().plater()->take_snapshot(_(L("Variable layer height - Adaptive"))); wxGetApp().plater()->take_snapshot(_(L("Variable layer height - Adaptive")));
m_layers_editing.adaptive_layer_height_profile(*this, cusp); m_layers_editing.adaptive_layer_height_profile(*this, quality_factor);
m_layers_editing.state = LayersEditing::Completed; m_layers_editing.state = LayersEditing::Completed;
m_dirty = true; m_dirty = true;
} }
@ -1925,7 +1920,11 @@ void GLCanvas3D::render()
m_camera.debug_render(); m_camera.debug_render();
#endif // ENABLE_CAMERA_STATISTICS #endif // ENABLE_CAMERA_STATISTICS
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
#else
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height()); wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
wxGetApp().imgui()->render(); wxGetApp().imgui()->render();
@ -2633,8 +2632,8 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
if (m_extra_frame_requested || mouse3d_controller_applied) if (m_extra_frame_requested || mouse3d_controller_applied)
{ {
m_dirty = true; m_dirty = true;
evt.RequestMore();
m_extra_frame_requested = false; m_extra_frame_requested = false;
evt.RequestMore();
} }
else else
m_dirty = false; m_dirty = false;

View File

@ -185,7 +185,7 @@ private:
bool m_layer_height_profile_modified; bool m_layer_height_profile_modified;
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
mutable float m_adaptive_cusp; mutable float m_adaptive_quality;
mutable HeightProfileSmoothingParams m_smooth_params; mutable HeightProfileSmoothingParams m_smooth_params;
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
@ -236,8 +236,8 @@ private:
void accept_changes(GLCanvas3D& canvas); void accept_changes(GLCanvas3D& canvas);
void reset_layer_height_profile(GLCanvas3D& canvas); void reset_layer_height_profile(GLCanvas3D& canvas);
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp); void adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor);
void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_paramsn); void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params);
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
static float get_cursor_z_relative(const GLCanvas3D& canvas); static float get_cursor_z_relative(const GLCanvas3D& canvas);
@ -541,7 +541,7 @@ public:
#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void reset_layer_height_profile(); void reset_layer_height_profile();
void adaptive_layer_height_profile(float cusp); void adaptive_layer_height_profile(float quality_factor);
void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params); void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params);
#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE

View File

@ -254,6 +254,16 @@ bool ImGuiWrapper::begin(const wxString &name, int flags)
return begin(into_u8(name), flags); return begin(into_u8(name), flags);
} }
bool ImGuiWrapper::begin(const std::string& name, bool* close, int flags)
{
return ImGui::Begin(name.c_str(), close, (ImGuiWindowFlags)flags);
}
bool ImGuiWrapper::begin(const wxString& name, bool* close, int flags)
{
return begin(into_u8(name), close, flags);
}
void ImGuiWrapper::end() void ImGuiWrapper::end()
{ {
ImGui::End(); ImGui::End();

View File

@ -56,6 +56,8 @@ public:
bool begin(const std::string &name, int flags = 0); bool begin(const std::string &name, int flags = 0);
bool begin(const wxString &name, int flags = 0); bool begin(const wxString &name, int flags = 0);
bool begin(const std::string& name, bool* close, int flags = 0);
bool begin(const wxString& name, bool* close, int flags = 0);
void end(); void end();
bool button(const wxString &label); bool button(const wxString &label);

View File

@ -5,6 +5,9 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "PresetBundle.hpp" #include "PresetBundle.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
#include "GLCanvas3D.hpp"
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
@ -184,7 +187,10 @@ Mouse3DController::Mouse3DController()
, m_device(nullptr) , m_device(nullptr)
, m_device_str("") , m_device_str("")
, m_running(false) , m_running(false)
, m_settings_dialog(false) , m_show_settings_dialog(false)
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
, m_settings_dialog_closed_by_user(false)
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
{ {
m_last_time = std::chrono::high_resolution_clock::now(); m_last_time = std::chrono::high_resolution_clock::now();
} }
@ -229,8 +235,11 @@ bool Mouse3DController::apply(Camera& camera)
if (!m_running && is_device_connected()) if (!m_running && is_device_connected())
{ {
disconnect_device(); disconnect_device();
// hides the settings dialog if the user re-plug the device // hides the settings dialog if the user un-plug the device
m_settings_dialog = false; m_show_settings_dialog = false;
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
m_settings_dialog_closed_by_user = false;
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
} }
// check if the user plugged the device // check if the user plugged the device
@ -240,88 +249,144 @@ bool Mouse3DController::apply(Camera& camera)
return is_device_connected() ? m_state.apply(camera) : false; return is_device_connected() ? m_state.apply(camera) : false;
} }
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
void Mouse3DController::render_settings_dialog(GLCanvas3D& canvas) const
#else
void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
{ {
if (!m_running || !m_settings_dialog) if (!m_running || !m_show_settings_dialog)
return; return;
ImGuiWrapper& imgui = *wxGetApp().imgui(); #if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
// when the user clicks on [X] or [Close] button we need to trigger
imgui.set_next_window_pos(0.5f * (float)canvas_width, 0.5f * (float)canvas_height, ImGuiCond_Always, 0.5f, 0.5f); // an extra frame to let the dialog disappear
if (m_settings_dialog_closed_by_user)
imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator);
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Device:")));
ImGui::PopStyleColor();
ImGui::SameLine();
imgui.text(m_device_str);
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Speed:")));
ImGui::PopStyleColor();
float translation_scale = (float)m_state.get_translation_scale() / State::DefaultTranslationScale;
if (imgui.slider_float(_(L("Translation")) + "##1", &translation_scale, 0.5f, 2.0f, "%.1f"))
m_state.set_translation_scale(State::DefaultTranslationScale * (double)translation_scale);
float rotation_scale = m_state.get_rotation_scale() / State::DefaultRotationScale;
if (imgui.slider_float(_(L("Rotation")) + "##1", &rotation_scale, 0.5f, 2.0f, "%.1f"))
m_state.set_rotation_scale(State::DefaultRotationScale * rotation_scale);
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Deadzone:")));
ImGui::PopStyleColor();
float translation_deadzone = (float)m_state.get_translation_deadzone();
if (imgui.slider_float(_(L("Translation")) + "##2", &translation_deadzone, 0.0f, (float)State::MaxTranslationDeadzone, "%.2f"))
m_state.set_translation_deadzone((double)translation_deadzone);
float rotation_deadzone = m_state.get_rotation_deadzone();
if (imgui.slider_float(_(L("Rotation")) + "##2", &rotation_deadzone, 0.0f, State::MaxRotationDeadzone, "%.2f"))
m_state.set_rotation_deadzone(rotation_deadzone);
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
ImGui::Separator();
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text("DEBUG:");
imgui.text("Vectors:");
ImGui::PopStyleColor();
Vec3f translation = m_state.get_translation().cast<float>();
Vec3f rotation = m_state.get_rotation();
ImGui::InputFloat3("Translation##3", translation.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
ImGui::InputFloat3("Rotation##3", rotation.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text("Queue size:");
ImGui::PopStyleColor();
int translation_size[2] = { (int)m_state.get_translation_queue_size(), (int)m_state.get_translation_queue_max_size() };
int rotation_size[2] = { (int)m_state.get_rotation_queue_size(), (int)m_state.get_rotation_queue_max_size() };
int buttons_size[2] = { (int)m_state.get_buttons_queue_size(), (int)m_state.get_buttons_queue_max_size() };
ImGui::InputInt2("Translation##4", translation_size, ImGuiInputTextFlags_ReadOnly);
ImGui::InputInt2("Rotation##4", rotation_size, ImGuiInputTextFlags_ReadOnly);
ImGui::InputInt2("Buttons", buttons_size, ImGuiInputTextFlags_ReadOnly);
int queue_size = (int)m_state.get_queues_max_size();
if (ImGui::InputInt("Max size", &queue_size, 1, 1, ImGuiInputTextFlags_ReadOnly))
{ {
if (queue_size > 0) m_show_settings_dialog = false;
m_state.set_queues_max_size(queue_size); m_settings_dialog_closed_by_user = false;
canvas.request_extra_frame();
return;
} }
ImGui::Separator(); Size cnv_size = canvas.get_canvas_size();
ImGui::PushStyleColor(ImGuiCol_Text, color); #endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
imgui.text("Camera:");
ImGui::PopStyleColor(); ImGuiWrapper& imgui = *wxGetApp().imgui();
Vec3f target = wxGetApp().plater()->get_camera().get_target().cast<float>(); #if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
ImGui::InputFloat3("Target", target.data(), "%.3f", ImGuiInputTextFlags_ReadOnly); imgui.set_next_window_pos(0.5f * (float)cnv_size.get_width(), 0.5f * (float)cnv_size.get_height(), ImGuiCond_Always, 0.5f, 0.5f);
#else
imgui.set_next_window_pos(0.5f * (float)canvas_width, 0.5f * (float)canvas_height, ImGuiCond_Always, 0.5f, 0.5f);
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
static ImVec2 last_win_size(0.0f, 0.0f);
bool shown = true;
if (imgui.begin(_(L("3Dconnexion settings")), &shown, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse))
{
if (shown)
{
ImVec2 win_size = ImGui::GetWindowSize();
if ((last_win_size.x != win_size.x) || (last_win_size.y != win_size.y))
{
// when the user clicks on [X] button, the next time the dialog is shown
// has a dummy size, so we trigger an extra frame to let it have the correct size
last_win_size = win_size;
canvas.request_extra_frame();
}
#else
imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator);
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Device:")));
ImGui::PopStyleColor();
ImGui::SameLine();
imgui.text(m_device_str);
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Speed:")));
ImGui::PopStyleColor();
float translation_scale = (float)m_state.get_translation_scale() / State::DefaultTranslationScale;
if (imgui.slider_float(_(L("Translation")) + "##1", &translation_scale, 0.5f, 2.0f, "%.1f"))
m_state.set_translation_scale(State::DefaultTranslationScale * (double)translation_scale);
float rotation_scale = m_state.get_rotation_scale() / State::DefaultRotationScale;
if (imgui.slider_float(_(L("Rotation")) + "##1", &rotation_scale, 0.5f, 2.0f, "%.1f"))
m_state.set_rotation_scale(State::DefaultRotationScale * rotation_scale);
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text(_(L("Deadzone:")));
ImGui::PopStyleColor();
float translation_deadzone = (float)m_state.get_translation_deadzone();
if (imgui.slider_float(_(L("Translation")) + "##2", &translation_deadzone, 0.0f, (float)State::MaxTranslationDeadzone, "%.2f"))
m_state.set_translation_deadzone((double)translation_deadzone);
float rotation_deadzone = m_state.get_rotation_deadzone();
if (imgui.slider_float(_(L("Rotation")) + "##2", &rotation_deadzone, 0.0f, State::MaxRotationDeadzone, "%.2f"))
m_state.set_rotation_deadzone(rotation_deadzone);
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
ImGui::Separator();
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text("DEBUG:");
imgui.text("Vectors:");
ImGui::PopStyleColor();
Vec3f translation = m_state.get_translation().cast<float>();
Vec3f rotation = m_state.get_rotation();
ImGui::InputFloat3("Translation##3", translation.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
ImGui::InputFloat3("Rotation##3", rotation.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text("Queue size:");
ImGui::PopStyleColor();
int translation_size[2] = { (int)m_state.get_translation_queue_size(), (int)m_state.get_translation_queue_max_size() };
int rotation_size[2] = { (int)m_state.get_rotation_queue_size(), (int)m_state.get_rotation_queue_max_size() };
int buttons_size[2] = { (int)m_state.get_buttons_queue_size(), (int)m_state.get_buttons_queue_max_size() };
ImGui::InputInt2("Translation##4", translation_size, ImGuiInputTextFlags_ReadOnly);
ImGui::InputInt2("Rotation##4", rotation_size, ImGuiInputTextFlags_ReadOnly);
ImGui::InputInt2("Buttons", buttons_size, ImGuiInputTextFlags_ReadOnly);
int queue_size = (int)m_state.get_queues_max_size();
if (ImGui::InputInt("Max size", &queue_size, 1, 1, ImGuiInputTextFlags_ReadOnly))
{
if (queue_size > 0)
m_state.set_queues_max_size(queue_size);
}
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, color);
imgui.text("Camera:");
ImGui::PopStyleColor();
Vec3f target = wxGetApp().plater()->get_camera().get_target().cast<float>();
ImGui::InputFloat3("Target", target.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT #endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
ImGui::Separator();
if (imgui.button(_(L("Close"))))
{
// the user clicked on the [Close] button
m_settings_dialog_closed_by_user = true;
canvas.set_as_dirty();
}
}
else
{
// the user clicked on the [X] button
m_settings_dialog_closed_by_user = true;
canvas.set_as_dirty();
}
}
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
imgui.end(); imgui.end();
} }

View File

@ -18,6 +18,9 @@ namespace Slic3r {
namespace GUI { namespace GUI {
struct Camera; struct Camera;
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
class GLCanvas3D;
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
class Mouse3DController class Mouse3DController
{ {
@ -130,7 +133,13 @@ class Mouse3DController
hid_device* m_device; hid_device* m_device;
std::string m_device_str; std::string m_device_str;
bool m_running; bool m_running;
bool m_settings_dialog; #if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
mutable bool m_show_settings_dialog;
// set to true when ther user closes the dialog by clicking on [X] or [Close] buttons
mutable bool m_settings_dialog_closed_by_user;
#else
bool m_show_settings_dialog;
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
std::chrono::time_point<std::chrono::high_resolution_clock> m_last_time; std::chrono::time_point<std::chrono::high_resolution_clock> m_last_time;
public: public:
@ -146,9 +155,13 @@ public:
bool apply(Camera& camera); bool apply(Camera& camera);
bool is_settings_dialog_shown() const { return m_settings_dialog; } bool is_settings_dialog_shown() const { return m_show_settings_dialog; }
void show_settings_dialog(bool show) { m_settings_dialog = show && is_running(); } void show_settings_dialog(bool show) { m_show_settings_dialog = show && is_running(); }
#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
void render_settings_dialog(GLCanvas3D& canvas) const;
#else
void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const; void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const;
#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
private: private:
bool connect_device(); bool connect_device();

View File

@ -3282,22 +3282,30 @@ void Plater::priv::reload_from_disk()
input_paths.push_back(sel_filename_path); input_paths.push_back(sel_filename_path);
missing_input_paths.pop_back(); missing_input_paths.pop_back();
std::string sel_path = fs::path(sel_filename_path).remove_filename().string(); fs::path sel_path = fs::path(sel_filename_path).remove_filename().string();
std::vector<fs::path>::iterator it = missing_input_paths.begin(); std::vector<fs::path>::iterator it = missing_input_paths.begin();
while (it != missing_input_paths.end()) while (it != missing_input_paths.end())
{ {
// try to use the path of the selected file with all remaining missing files // try to use the path of the selected file with all remaining missing files
std::string repathed_filename = sel_path + "/" + it->filename().string(); fs::path repathed_filename = sel_path;
repathed_filename /= it->filename();
if (fs::exists(repathed_filename)) if (fs::exists(repathed_filename))
{ {
input_paths.push_back(repathed_filename); input_paths.push_back(repathed_filename.string());
it = missing_input_paths.erase(it); it = missing_input_paths.erase(it);
} }
else else
++it; ++it;
} }
} }
else
{
wxString message = _(L("It is not allowed to change the file to reload")) + " (" + from_u8(fs::path(search).filename().string())+ ").\n" + _(L("Do you want to retry")) + " ?";
wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES)
return;
}
} }
#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION #endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION

View File

@ -3,7 +3,7 @@
set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_NAME "PrusaSlicer")
set(SLIC3R_APP_KEY "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer")
set(SLIC3R_VERSION "2.1.0") set(SLIC3R_VERSION "2.2.0-alpha0")
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
set(SLIC3R_RC_VERSION "2,1,0,0") set(SLIC3R_RC_VERSION "2,2,0,0")
set(SLIC3R_RC_VERSION_DOTS "2.1.0.0") set(SLIC3R_RC_VERSION_DOTS "2.2.0.0")