mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
Merge branch 'main' into dev/cut-keep-paint
This commit is contained in:
@@ -34,7 +34,7 @@ public:
|
||||
void intersect_ray(const indexed_triangle_set &its,
|
||||
const Vec3d & s,
|
||||
const Vec3d & dir,
|
||||
igl::Hit & hit)
|
||||
igl::Hit<float> & hit)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_first_hit(its.vertices, its.indices,
|
||||
m_tree, s, dir, hit, m_triangle_ray_epsilon);
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
void intersect_ray(const indexed_triangle_set &its,
|
||||
const Vec3d & s,
|
||||
const Vec3d & dir,
|
||||
std::vector<igl::Hit> & hits)
|
||||
std::vector<igl::Hit<float>> & hits)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_all_hits(its.vertices, its.indices,
|
||||
m_tree, s, dir, hits, m_triangle_ray_epsilon);
|
||||
@@ -152,7 +152,7 @@ AABBMesh::hit_result
|
||||
AABBMesh::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
||||
{
|
||||
assert(is_approx(dir.norm(), 1.));
|
||||
igl::Hit hit{-1, -1, 0.f, 0.f, 0.f};
|
||||
igl::Hit<float> hit{-1, -1, 0.f, 0.f, 0.f};
|
||||
hit.t = std::numeric_limits<float>::infinity();
|
||||
|
||||
#ifdef SLIC3R_HOLE_RAYCASTER
|
||||
@@ -181,23 +181,23 @@ std::vector<AABBMesh::hit_result>
|
||||
AABBMesh::query_ray_hits(const Vec3d &s, const Vec3d &dir) const
|
||||
{
|
||||
std::vector<AABBMesh::hit_result> outs;
|
||||
std::vector<igl::Hit> hits;
|
||||
std::vector<igl::Hit<float>> hits;
|
||||
m_aabb->intersect_ray(*m_tm, s, dir, hits);
|
||||
|
||||
// The sort is necessary, the hits are not always sorted.
|
||||
std::sort(hits.begin(), hits.end(),
|
||||
[](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
|
||||
[](const igl::Hit<float>& a, const igl::Hit<float>& b) { return a.t < b.t; });
|
||||
|
||||
// Remove duplicates. They sometimes appear, for example when the ray is cast
|
||||
// along an axis of a cube due to floating-point approximations in igl (?)
|
||||
hits.erase(std::unique(hits.begin(), hits.end(),
|
||||
[](const igl::Hit& a, const igl::Hit& b)
|
||||
[](const igl::Hit<float>& a, const igl::Hit<float>& b)
|
||||
{ return a.t == b.t; }),
|
||||
hits.end());
|
||||
|
||||
// Convert the igl::Hit into hit_result
|
||||
// Convert the igl::Hit<float> into hit_result
|
||||
outs.reserve(hits.size());
|
||||
for (const igl::Hit& hit : hits) {
|
||||
for (const igl::Hit<float>& hit : hits) {
|
||||
outs.emplace_back(AABBMesh::hit_result(*this));
|
||||
outs.back().m_t = double(hit.t);
|
||||
outs.back().m_dir = dir;
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace detail {
|
||||
|
||||
template<typename VertexType, typename IndexedFaceType, typename TreeType, typename VectorType>
|
||||
struct RayIntersectorHits : RayIntersector<VertexType, IndexedFaceType, TreeType, VectorType> {
|
||||
std::vector<igl::Hit> hits;
|
||||
std::vector<igl::Hit<float> > hits;
|
||||
};
|
||||
|
||||
//FIXME implement SSE for float AABB trees with float ray queries.
|
||||
@@ -397,7 +397,7 @@ namespace detail {
|
||||
RayIntersectorType &ray_intersector,
|
||||
size_t node_idx,
|
||||
Scalar min_t,
|
||||
igl::Hit &hit)
|
||||
igl::Hit<float> &hit)
|
||||
{
|
||||
const auto &node = ray_intersector.tree.node(node_idx);
|
||||
assert(node.is_valid());
|
||||
@@ -414,7 +414,7 @@ namespace detail {
|
||||
ray_intersector.vertices[face(0)], ray_intersector.vertices[face(1)], ray_intersector.vertices[face(2)],
|
||||
t, u, v, ray_intersector.eps)
|
||||
&& t > 0.) {
|
||||
hit = igl::Hit { int(node.idx), -1, float(u), float(v), float(t) };
|
||||
hit = igl::Hit<float> { int(node.idx), -1, float(u), float(v), float(t) };
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
@@ -422,8 +422,8 @@ namespace detail {
|
||||
// Left / right child node index.
|
||||
size_t left = node_idx * 2 + 1;
|
||||
size_t right = left + 1;
|
||||
igl::Hit left_hit;
|
||||
igl::Hit right_hit;
|
||||
igl::Hit<float> left_hit;
|
||||
igl::Hit<float> right_hit;
|
||||
bool left_ret = intersect_ray_recursive_first_hit(ray_intersector, left, min_t, left_hit);
|
||||
if (left_ret && left_hit.t < min_t) {
|
||||
min_t = left_hit.t;
|
||||
@@ -459,7 +459,7 @@ namespace detail {
|
||||
ray_intersector.vertices[face(0)], ray_intersector.vertices[face(1)], ray_intersector.vertices[face(2)],
|
||||
t, u, v, ray_intersector.eps)
|
||||
&& t > 0.) {
|
||||
ray_intersector.hits.emplace_back(igl::Hit{ int(node.idx), -1, float(u), float(v), float(t) });
|
||||
ray_intersector.hits.emplace_back(igl::Hit<float>{ int(node.idx), -1, float(u), float(v), float(t) });
|
||||
}
|
||||
} else {
|
||||
// Left / right child node index.
|
||||
@@ -732,7 +732,7 @@ inline bool intersect_ray_first_hit(
|
||||
// Direction of the ray.
|
||||
const VectorType &dir,
|
||||
// First intersection of the ray with the indexed triangle set.
|
||||
igl::Hit &hit,
|
||||
igl::Hit<float> &hit,
|
||||
// Epsilon for the ray-triangle intersection, it should be proportional to an average triangle edge length.
|
||||
const double eps = 0.000001)
|
||||
{
|
||||
@@ -764,7 +764,7 @@ inline bool intersect_ray_all_hits(
|
||||
// Direction of the ray.
|
||||
const VectorType &dir,
|
||||
// All intersections of the ray with the indexed triangle set, sorted by parameter t.
|
||||
std::vector<igl::Hit> &hits,
|
||||
std::vector<igl::Hit<float> > &hits,
|
||||
// Epsilon for the ray-triangle intersection, it should be proportional to an average triangle edge length.
|
||||
const double eps = 0.000001)
|
||||
{
|
||||
|
||||
@@ -484,7 +484,7 @@ if (APPLE)
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_library(libslic3r STATIC ${lisbslic3r_sources}
|
||||
add_library(libslic3r STATIC ${lisbslic3r_sources}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h"
|
||||
${OpenVDBUtils_SOURCES})
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${lisbslic3r_sources})
|
||||
@@ -500,7 +500,7 @@ find_package(CGAL REQUIRED)
|
||||
find_package(OpenCV REQUIRED core)
|
||||
cmake_policy(POP)
|
||||
|
||||
add_library(libslic3r_cgal STATIC
|
||||
add_library(libslic3r_cgal STATIC
|
||||
CutSurface.hpp CutSurface.cpp
|
||||
IntersectionPoints.hpp IntersectionPoints.cpp
|
||||
MeshBoolean.hpp MeshBoolean.cpp
|
||||
@@ -525,7 +525,7 @@ if (_opts)
|
||||
target_compile_options(libslic3r_cgal PRIVATE "${_opts_bad}")
|
||||
endif()
|
||||
|
||||
target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} eigen admesh libigl mcut boost_libs)
|
||||
target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} admesh libigl mcut boost_libs)
|
||||
|
||||
if (MSVC AND "${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") # 32 bit MSVC workaround
|
||||
target_compile_definitions(libslic3r_cgal PRIVATE CGAL_DO_NOT_USE_MPZF)
|
||||
@@ -576,6 +576,7 @@ set(OCCT_LIBS
|
||||
|
||||
target_link_libraries(libslic3r
|
||||
PUBLIC
|
||||
Eigen3::Eigen
|
||||
admesh
|
||||
libigl
|
||||
libnest2d
|
||||
@@ -590,7 +591,6 @@ target_link_libraries(libslic3r
|
||||
clipper
|
||||
Clipper2
|
||||
draco::draco
|
||||
eigen
|
||||
glu-libtess
|
||||
JPEG::JPEG
|
||||
libslic3r_cgal
|
||||
|
||||
@@ -3925,6 +3925,17 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
|
||||
|
||||
// New Marlin uses M205 J[mm] for junction deviation (only apply if it is > 0)
|
||||
file.write_format(writer().set_junction_deviation(config().machine_max_junction_deviation.values.front()).c_str());
|
||||
|
||||
// Orca: Override input shaping values
|
||||
if (print.config().input_shaping_emit.value && flavor != gcfMarlinLegacy) {
|
||||
const bool input_shaping_disable = print.config().input_shaping_type.value == InputShaperType::Disable;
|
||||
file.write_format(writer().set_input_shaping('X', print.config().input_shaping_damp_x.value,
|
||||
print.config().input_shaping_freq_x.value, print.config().opt_serialize("input_shaping_type")).c_str());
|
||||
if (flavor != gcfRepRapFirmware && !input_shaping_disable) {
|
||||
file.write_format(writer().set_input_shaping('Y', print.config().input_shaping_damp_y.value,
|
||||
print.config().input_shaping_freq_y.value, "").c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ std::vector<float> raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra
|
||||
[&triangles, &precomputed_sample_directions, model_contains_negative_parts, negative_volumes_start_index,
|
||||
&raycasting_tree, &result, &samples, seam_position](tbb::blocked_range<size_t> r) {
|
||||
// Maintaining hits memory outside of the loop, so it does not have to be reallocated for each query.
|
||||
std::vector<igl::Hit> hits;
|
||||
std::vector<igl::Hit<float>> hits;
|
||||
for (size_t s_idx = r.begin(); s_idx < r.end(); ++s_idx) {
|
||||
result[s_idx] = 1.0f;
|
||||
constexpr float decrease_step = 1.0f
|
||||
@@ -174,7 +174,7 @@ std::vector<float> raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra
|
||||
for (const auto &dir : precomputed_sample_directions) {
|
||||
Vec3f final_ray_dir = (f.to_world(dir));
|
||||
if (!model_contains_negative_parts) {
|
||||
igl::Hit hitpoint;
|
||||
igl::Hit<float> hitpoint;
|
||||
// FIXME: This AABBTTreeIndirect query will not compile for float ray origin and
|
||||
// direction.
|
||||
Vec3d final_ray_dir_d = final_ray_dir.cast<double>();
|
||||
|
||||
@@ -350,7 +350,7 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
|
||||
|
||||
std::string GCodeWriter::set_junction_deviation(double junction_deviation){
|
||||
std::ostringstream gcode;
|
||||
if (FLAVOR_IS(gcfMarlinFirmware) && junction_deviation > 0 && m_max_junction_deviation > 0) {
|
||||
if (FLAVOR_IS(gcfMarlinFirmware) && m_max_junction_deviation > 0 && junction_deviation > 0) {
|
||||
// Clamp the junction deviation to the allowed maximum.
|
||||
gcode << "M205 J";
|
||||
if (junction_deviation <= m_max_junction_deviation) {
|
||||
@@ -390,68 +390,88 @@ std::string GCodeWriter::set_pressure_advance(double pa) const
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
// Orca: input shaping support
|
||||
std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq, std::string type) const
|
||||
{
|
||||
if (FLAVOR_IS(gcfMarlinLegacy))
|
||||
throw std::runtime_error("Input shaping is not supported by Marlin < 2.1.2.\nCheck your firmware version and update your G-code flavor to ´Marlin 2´");
|
||||
if (freq < 0.0f || damp < 0.f || damp > 1.0f || (axis != 'X' && axis != 'Y' && axis != 'Z' && axis != 'A'))// A = all axis
|
||||
{
|
||||
throw std::runtime_error("Invalid input shaping parameters: freq=" + std::to_string(freq) + ", damp=" + std::to_string(damp));
|
||||
bool disable = type == "Disable";
|
||||
if (disable){
|
||||
freq = 0.0f;
|
||||
damp = 0.0f;
|
||||
axis = 'A';
|
||||
type = "Default";
|
||||
} else if (freq < 0.0f || damp < 0.f || damp > 1.0f || (axis != 'X' && axis != 'Y' && axis != 'Z' && axis != 'A')) { // A = all axis
|
||||
throw std::runtime_error("Invalid input shaping parameters: axis=" + std::string(1, axis) + ", freq=" + std::to_string(freq) + ", damp=" + std::to_string(damp));
|
||||
}
|
||||
std::ostringstream gcode;
|
||||
if (FLAVOR_IS(gcfKlipper)) {
|
||||
gcode << "SET_INPUT_SHAPER";
|
||||
std::ostringstream params;
|
||||
switch (this->config.gcode_flavor) {
|
||||
case gcfKlipper: {
|
||||
if (!type.empty() && type != "Default") {
|
||||
gcode << " SHAPER_TYPE=" << type;
|
||||
params << " SHAPER_TYPE=" << type;
|
||||
}
|
||||
if (axis != 'A')
|
||||
{
|
||||
if (freq > 0.0f) {
|
||||
gcode << " SHAPER_FREQ_" << axis << "=" << std::fixed << std::setprecision(2) << freq;
|
||||
}
|
||||
if (damp > 0.0f){
|
||||
gcode << " DAMPING_RATIO_" << axis << "=" << std::fixed << std::setprecision(3) << damp;
|
||||
}
|
||||
} else {
|
||||
if (freq > 0.0f) {
|
||||
gcode << " SHAPER_FREQ_X=" << std::fixed << std::setprecision(2) << freq << " SHAPER_FREQ_Y=" << std::fixed << std::setprecision(2) << freq;
|
||||
params << " SHAPER_FREQ_" << axis << "=" << std::fixed << std::setprecision(2) << freq;
|
||||
}
|
||||
if (damp > 0.0f) {
|
||||
gcode << " DAMPING_RATIO_X=" << std::fixed << std::setprecision(3) << damp << " DAMPING_RATIO_Y=" << std::fixed << std::setprecision(3) << damp;
|
||||
params << " DAMPING_RATIO_" << axis << "=" << std::fixed << std::setprecision(3) << damp;
|
||||
}
|
||||
} else {
|
||||
if (freq > 0.0f || disable) {
|
||||
params << " SHAPER_FREQ_X=" << std::fixed << std::setprecision(2) << freq << " SHAPER_FREQ_Y=" << std::fixed << std::setprecision(2) << freq;
|
||||
}
|
||||
if (damp > 0.0f || disable) {
|
||||
params << " DAMPING_RATIO_X=" << std::fixed << std::setprecision(3) << damp << " DAMPING_RATIO_Y=" << std::fixed << std::setprecision(3) << damp;
|
||||
}
|
||||
}
|
||||
} else if (FLAVOR_IS(gcfRepRapFirmware)) {
|
||||
gcode << "M593";
|
||||
if (!params.str().empty()) {
|
||||
gcode << "SET_INPUT_SHAPER" << params.str();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gcfRepRapFirmware: {
|
||||
if (!type.empty() && type != "Default" && type != "DAA") {
|
||||
gcode << " P\"" << type << "\"";
|
||||
params << " P\"" << type << "\"";
|
||||
}
|
||||
if (freq > 0.0f) {
|
||||
gcode << " F" << std::fixed << std::setprecision(2) << freq;
|
||||
if (freq > 0.0f || disable) {
|
||||
params << " F" << std::fixed << std::setprecision(2) << freq;
|
||||
}
|
||||
if (damp > 0.0f){
|
||||
gcode << " S" << std::fixed << std::setprecision(3) << damp;
|
||||
if (damp > 0.0f || disable) {
|
||||
params << " S" << std::fixed << std::setprecision(3) << damp;
|
||||
}
|
||||
} else if (FLAVOR_IS(gcfMarlinFirmware)) {
|
||||
gcode << "M593";
|
||||
if (axis != 'A')
|
||||
{
|
||||
gcode << " " << axis;
|
||||
if (!params.str().empty()) {
|
||||
gcode << "M593" << params.str();
|
||||
}
|
||||
if (freq > 0.0f)
|
||||
{
|
||||
gcode << " F" << std::fixed << std::setprecision(2) << freq;
|
||||
break;
|
||||
}
|
||||
case gcfMarlinFirmware: {
|
||||
if (axis != 'A') {
|
||||
params << " " << axis;
|
||||
}
|
||||
if (damp > 0.0f)
|
||||
{
|
||||
gcode << " D" << std::fixed << std::setprecision(3) << damp;
|
||||
if (freq > 0.0f || disable) {
|
||||
params << " F" << std::fixed << std::setprecision(2) << freq;
|
||||
}
|
||||
} else {
|
||||
if (damp > 0.0f || disable) {
|
||||
params << " D" << std::fixed << std::setprecision(3) << damp;
|
||||
}
|
||||
if (!params.str().empty()) {
|
||||
gcode << "M593" << params.str();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gcfMarlinLegacy: {
|
||||
throw std::runtime_error("Input shaping is not supported by Marlin < 2.1.2.\nCheck your firmware version and update your G-code flavor to ´Marlin 2´");
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Input shaping is only supported by Klipper, RepRapFirmware and Marlin 2");
|
||||
}
|
||||
if (GCodeWriter::full_gcode_comment){
|
||||
gcode << " ; Override input shaping";
|
||||
if (!gcode.str().empty()) {
|
||||
if (GCodeWriter::full_gcode_comment) {
|
||||
gcode << " ; Override input shaping";
|
||||
}
|
||||
gcode << "\n";
|
||||
}
|
||||
gcode << "\n";
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -1318,6 +1318,8 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
"machine_max_junction_deviation",
|
||||
//resonance avoidance ported from qidi slicer
|
||||
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed",
|
||||
// Orca: input shaping
|
||||
"input_shaping_emit", "input_shaping_type", "input_shaping_freq_x", "input_shaping_freq_y", "input_shaping_damp_x", "input_shaping_damp_y",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
|
||||
@@ -60,6 +60,7 @@ const char *PresetBundle::ORCA_DEFAULT_PRINTER_MODEL = "MyKlipper 0.4 nozzle";
|
||||
const char *PresetBundle::ORCA_DEFAULT_PRINTER_VARIANT = "0.4";
|
||||
const char *PresetBundle::ORCA_DEFAULT_FILAMENT = "Generic PLA @System";
|
||||
const char *PresetBundle::ORCA_FILAMENT_LIBRARY = "OrcaFilamentLibrary";
|
||||
const char *PresetBundle::ORCA_DEFAULT_FILAMENT_PLACEHOLDER = "Default Filament";
|
||||
|
||||
DynamicPrintConfig PresetBundle::construct_full_config(
|
||||
Preset& in_printer_preset,
|
||||
@@ -317,7 +318,7 @@ std::string PresetBundle::find_preset_vendor(const std::string &preset_name, Pre
|
||||
|
||||
PresetBundle::PresetBundle()
|
||||
: prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()))
|
||||
, filaments(Preset::TYPE_FILAMENT, Preset::filament_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()), "Default Filament")
|
||||
, filaments(Preset::TYPE_FILAMENT, Preset::filament_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()), ORCA_DEFAULT_FILAMENT_PLACEHOLDER)
|
||||
, sla_materials(Preset::TYPE_SLA_MATERIAL, Preset::sla_material_options(), static_cast<const SLAMaterialConfig &>(SLAFullPrintConfig::defaults()))
|
||||
, sla_prints(Preset::TYPE_SLA_PRINT, Preset::sla_print_options(), static_cast<const SLAPrintObjectConfig &>(SLAFullPrintConfig::defaults()))
|
||||
, printers(Preset::TYPE_PRINTER, Preset::printer_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()), "Default Printer")
|
||||
@@ -2634,7 +2635,10 @@ void PresetBundle::update_selections(AppConfig &config)
|
||||
|
||||
std::string first_visible_filament_name;
|
||||
for (auto & fp : filament_presets) {
|
||||
if (auto it = filaments.find_preset_internal(fp); it == filaments.end() || !it->is_visible || !it->is_compatible) {
|
||||
// Orca: also match the ORCA_DEFAULT_FILAMENT_PLACEHOLDER placeholder. update_compatible_internal
|
||||
// iterates from m_num_default_presets, so the placeholder's is_compatible flag
|
||||
// stays true and the not-found/visible/compatible predicate alone would miss it.
|
||||
if (auto it = filaments.find_preset_internal(fp); fp == ORCA_DEFAULT_FILAMENT_PLACEHOLDER || it == filaments.end() || !it->is_visible || !it->is_compatible) {
|
||||
if (first_visible_filament_name.empty())
|
||||
first_visible_filament_name = filaments.first_compatible().name;
|
||||
fp = first_visible_filament_name;
|
||||
@@ -2685,13 +2689,13 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
|
||||
initial_print_profile_name = prefered_print_profile;
|
||||
|
||||
const std::vector<std::string>& prefered_filament_profiles = preferred_printer->config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
||||
if ((!initial_filament_profile_name.compare("Default Filament")) && (prefered_filament_profiles.size() > 0)) {
|
||||
if ((!initial_filament_profile_name.compare(ORCA_DEFAULT_FILAMENT_PLACEHOLDER)) && (prefered_filament_profiles.size() > 0)) {
|
||||
// Check if preferred filament is visible
|
||||
const Preset* preferred_preset = this->filaments.find_preset(prefered_filament_profiles[0], false);
|
||||
if (preferred_preset && preferred_preset->is_visible) {
|
||||
initial_filament_profile_name = prefered_filament_profiles[0];
|
||||
}
|
||||
// If not visible, keep the default "Default Filament" which will be resolved later
|
||||
// If not visible, keep the default ORCA_DEFAULT_FILAMENT_PLACEHOLDER which will be resolved later
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2792,7 +2796,8 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
|
||||
|
||||
std::string first_visible_filament_name;
|
||||
for (auto & fp : filament_presets) {
|
||||
if (auto it = filaments.find_preset_internal(fp); it == filaments.end() || !it->is_visible || !it->is_compatible) {
|
||||
// Orca: also match the ORCA_DEFAULT_FILAMENT_PLACEHOLDER placeholder — see update_selections.
|
||||
if (auto it = filaments.find_preset_internal(fp); fp == ORCA_DEFAULT_FILAMENT_PLACEHOLDER || it == filaments.end() || !it->is_visible || !it->is_compatible) {
|
||||
if (first_visible_filament_name.empty())
|
||||
first_visible_filament_name = filaments.first_compatible().name;
|
||||
fp = first_visible_filament_name;
|
||||
@@ -5034,19 +5039,22 @@ void PresetBundle::update_multi_material_filament_presets(size_t to_delete_filam
|
||||
if (printers.get_edited_preset().printer_technology() != ptFFF)
|
||||
return;
|
||||
|
||||
// BBS
|
||||
#if 0
|
||||
// Orca: when the number of existing filament presets is less than the number of extruders, we will append new filament presets with the
|
||||
// same value as the last existing one.
|
||||
//
|
||||
// Verify and select the filament presets.
|
||||
auto *nozzle_diameter = static_cast<const ConfigOptionFloats*>(printers.get_edited_preset().config.option("nozzle_diameter"));
|
||||
size_t num_extruders = nozzle_diameter->values.size();
|
||||
// Verify validity of the current filament presets.
|
||||
for (size_t i = 0; i < std::min(this->filament_presets.size(), num_extruders); ++ i)
|
||||
this->filament_presets[i] = this->filaments.find_preset(this->filament_presets[i], true)->name;
|
||||
// Append the rest of filament presets.
|
||||
this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name : this->filament_presets.back());
|
||||
#else
|
||||
size_t num_filaments = this->filament_presets.size();
|
||||
#endif
|
||||
|
||||
auto* nozzle_diameter = static_cast<const ConfigOptionFloats*>(printers.get_edited_preset().config.option("nozzle_diameter"));
|
||||
size_t num_extruders = nozzle_diameter->values.size();
|
||||
if (num_extruders > num_filaments) { // Verify validity of the current filament presets.
|
||||
for (size_t i = 0; i < std::min(this->filament_presets.size(), num_extruders); ++i)
|
||||
this->filament_presets[i] = this->filaments.find_preset(this->filament_presets[i], true)->name;
|
||||
// Append the rest of filament presets.
|
||||
this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name :
|
||||
this->filament_presets.back());
|
||||
num_filaments = this->filament_presets.size();
|
||||
}
|
||||
if (to_delete_filament_id == -1)
|
||||
to_delete_filament_id = num_filaments;
|
||||
|
||||
@@ -5081,7 +5089,14 @@ void PresetBundle::update_multi_material_filament_presets(size_t to_delete_filam
|
||||
unsigned int old_i = i >= to_delete_filament_id ? i + 1 : i;
|
||||
unsigned int old_j = j >= to_delete_filament_id ? j + 1 : j;
|
||||
for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) {
|
||||
new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = old_matrix[old_i * old_number_of_filaments + old_j + old_matrix_size * nozzle_id];
|
||||
// Orca: only copy from old_matrix when the old layout actually has data
|
||||
// for this nozzle slot; otherwise initialize from the per-filament
|
||||
// flush volumes the same way the (i,j) out-of-range branch does.
|
||||
if (nozzle_id < old_nozzle_nums) {
|
||||
new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = old_matrix[old_i * old_number_of_filaments + old_j + old_matrix_size * nozzle_id];
|
||||
} else {
|
||||
new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = (i == j ? 0. : filaments[2 * i] + filaments[2 * j + 1]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) {
|
||||
|
||||
@@ -465,6 +465,7 @@ public:
|
||||
static const char *ORCA_DEFAULT_PRINTER_VARIANT;
|
||||
static const char *ORCA_DEFAULT_FILAMENT;
|
||||
static const char *ORCA_FILAMENT_LIBRARY;
|
||||
static const char *ORCA_DEFAULT_FILAMENT_PLACEHOLDER;
|
||||
|
||||
|
||||
static std::array<Preset::Type, 3> types_list(PrinterTechnology pt) {
|
||||
|
||||
@@ -91,6 +91,25 @@ size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Orca: input shaping values types by flavor
|
||||
std::vector<std::string> get_shaper_type_values_for_flavor(GCodeFlavor flavor)
|
||||
{
|
||||
switch (flavor) {
|
||||
case GCodeFlavor::gcfKlipper:
|
||||
return {"Default", "MZV", "ZV", "ZVD", "EI", "2HUMP_EI", "3HUMP_EI"};
|
||||
case GCodeFlavor::gcfRepRapFirmware:
|
||||
return {"Default", "MZV", "ZV", "ZVD", "ZVDD", "ZVDDD", "EI2", "EI3", "DAA"};
|
||||
case GCodeFlavor::gcfMarlinFirmware:
|
||||
return {"ZV"};
|
||||
case GCodeFlavor::gcfMarlinLegacy:
|
||||
return {};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {"Default"};
|
||||
}
|
||||
|
||||
static t_config_enum_names enum_names_from_keys_map(const t_config_enum_values &enum_keys_map)
|
||||
{
|
||||
t_config_enum_names names;
|
||||
@@ -481,6 +500,23 @@ static t_config_enum_values s_keys_map_PrinterStructure {
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrinterStructure)
|
||||
|
||||
static t_config_enum_values s_keys_map_InputShaperType {
|
||||
{"Default", int(InputShaperType::Default)},
|
||||
{"MZV", int(InputShaperType::MZV)},
|
||||
{"ZV", int(InputShaperType::ZV)},
|
||||
{"ZVD", int(InputShaperType::ZVD)},
|
||||
{"ZVDD", int(InputShaperType::ZVDD)},
|
||||
{"ZVDDD", int(InputShaperType::ZVDDD)},
|
||||
{"EI", int(InputShaperType::EI)},
|
||||
{"EI2", int(InputShaperType::EI2)},
|
||||
{"2HUMP_EI",int(InputShaperType::TwoHumpEI)},
|
||||
{"EI3", int(InputShaperType::EI3)},
|
||||
{"3HUMP_EI",int(InputShaperType::ThreeHumpEI)},
|
||||
{"DAA", int(InputShaperType::DAA)},
|
||||
{"Disable", int(InputShaperType::Disable)}
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InputShaperType)
|
||||
|
||||
static t_config_enum_values s_keys_map_PerimeterGeneratorType{
|
||||
{ "classic", int(PerimeterGeneratorType::Classic) },
|
||||
{ "arachne", int(PerimeterGeneratorType::Arachne) }
|
||||
@@ -4243,8 +4279,8 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("emit_machine_limits_to_gcode", coBool);
|
||||
def->label = L("Emit limits to G-code");
|
||||
def->category = L("Machine limits");
|
||||
def->tooltip = L("If enabled, the machine limits will be emitted to G-code file.\nThis option will be ignored if the G-code flavor is "
|
||||
"set to Klipper.");
|
||||
def->tooltip = L("If enabled, the machine limits will be emitted to G-code file.\nThis option will be ignored if the G-code flavor is "
|
||||
"set to Klipper.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
@@ -4455,6 +4491,56 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(120));
|
||||
|
||||
// Orca: Input Shaping support
|
||||
def = this->add("input_shaping_emit", coBool);
|
||||
def->label = L("Emit input shaping");
|
||||
def->tooltip = L("Override firmware input shaping settings.\nIf disabled, firmware settings are used.");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("input_shaping_type", coEnum);
|
||||
def->label = L("Input shaper type");
|
||||
def->tooltip = L("Choose the input shaper algorithm.\nDefault uses the firmware default settings.\nDisable turns off input shaping in the firmware.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<InputShaperType>::get_enum_values();
|
||||
def->enum_values = {"Default", "MZV", "ZV", "ZVD", "ZVDD", "ZVDDD", "EI", "EI2", "2HUMP_EI", "EI3", "3HUMP_EI", "DAA", "Disable"};
|
||||
def->enum_labels = {L("Default"), L("MZV"), L("ZV"), L("ZVD"), L("ZVDD"), L("ZVDDD"), L("EI"), L("EI2"), L("2HUMP_EI"), L("EI3"), L("3HUMP_EI"), L("DAA"), L("Disable")};
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionEnum<InputShaperType>(InputShaperType::Default));
|
||||
|
||||
def = this->add("input_shaping_freq_x", coFloat);
|
||||
def->label = L("X");
|
||||
def->tooltip = L("Resonant frequency for the X axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
||||
def->sidetext = "Hz";
|
||||
def->min = 0;
|
||||
def->max = 1000;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("input_shaping_freq_y", coFloat);
|
||||
def->label = L("Y");
|
||||
def->tooltip = L("Resonant frequency for the Y axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.");
|
||||
def->sidetext = "Hz";
|
||||
def->min = 0;
|
||||
def->max = 1000;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("input_shaping_damp_x", coFloat);
|
||||
def->label = L("X");
|
||||
def->tooltip = L("Damping ratio for the X axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
||||
def->min = 0;
|
||||
def->max = 1;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||
|
||||
def = this->add("input_shaping_damp_y", coFloat);
|
||||
def->label = L("Y");
|
||||
def->tooltip = L("Damping ratio for the Y axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.");
|
||||
def->min = 0;
|
||||
def->max = 1;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||
|
||||
def = this->add("fan_max_speed", coFloats);
|
||||
def->label = L("Fan speed");
|
||||
def->tooltip = L("Part cooling fan speed may be increased when auto cooling is enabled. "
|
||||
|
||||
@@ -362,6 +362,22 @@ enum PrinterStructure {
|
||||
psDelta
|
||||
};
|
||||
|
||||
enum class InputShaperType : unsigned char {
|
||||
Default = 0,
|
||||
MZV,
|
||||
ZV,
|
||||
ZVD,
|
||||
ZVDD,
|
||||
ZVDDD,
|
||||
EI,
|
||||
EI2,
|
||||
TwoHumpEI,
|
||||
EI3,
|
||||
ThreeHumpEI,
|
||||
DAA,
|
||||
Disable
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum ZHopType {
|
||||
zhtAuto = 0,
|
||||
@@ -525,6 +541,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TimelapseType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SkirtType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InputShaperType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat)
|
||||
@@ -1259,6 +1276,14 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionBool, resonance_avoidance))
|
||||
((ConfigOptionFloat, min_resonance_avoidance_speed))
|
||||
((ConfigOptionFloat, max_resonance_avoidance_speed))
|
||||
|
||||
//Orca: Input shaping
|
||||
((ConfigOptionBool, input_shaping_emit))
|
||||
((ConfigOptionEnum<InputShaperType>, input_shaping_type))
|
||||
((ConfigOptionFloat, input_shaping_freq_x))
|
||||
((ConfigOptionFloat, input_shaping_freq_y))
|
||||
((ConfigOptionFloat, input_shaping_damp_x))
|
||||
((ConfigOptionFloat, input_shaping_damp_y))
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::GCode.
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void intersect_ray(const indexed_triangle_set &its,
|
||||
const Vec3d & s,
|
||||
const Vec3d & dir,
|
||||
igl::Hit & hit)
|
||||
igl::Hit<float> & hit)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_first_hit(its.vertices, its.indices,
|
||||
m_tree, s, dir, hit, m_triangle_ray_epsilon);
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
void intersect_ray(const indexed_triangle_set &its,
|
||||
const Vec3d & s,
|
||||
const Vec3d & dir,
|
||||
std::vector<igl::Hit> & hits)
|
||||
std::vector<igl::Hit<float>> & hits)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_all_hits(its.vertices, its.indices,
|
||||
m_tree, s, dir, hits, m_triangle_ray_epsilon);
|
||||
@@ -146,7 +146,7 @@ IndexedMesh::hit_result
|
||||
IndexedMesh::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
||||
{
|
||||
assert(is_approx(dir.norm(), 1.));
|
||||
igl::Hit hit{-1, -1, 0.f, 0.f, 0.f};
|
||||
igl::Hit<float> hit{-1, -1, 0.f, 0.f, 0.f};
|
||||
hit.t = std::numeric_limits<float>::infinity();
|
||||
|
||||
#ifdef SLIC3R_HOLE_RAYCASTER
|
||||
@@ -175,24 +175,24 @@ std::vector<IndexedMesh::hit_result>
|
||||
IndexedMesh::query_ray_hits(const Vec3d &s, const Vec3d &dir) const
|
||||
{
|
||||
std::vector<IndexedMesh::hit_result> outs;
|
||||
std::vector<igl::Hit> hits;
|
||||
std::vector<igl::Hit<float>> hits;
|
||||
m_aabb->intersect_ray(*m_tm, s, dir, hits);
|
||||
|
||||
// The sort is necessary, the hits are not always sorted.
|
||||
std::sort(hits.begin(), hits.end(),
|
||||
[](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
|
||||
[](const igl::Hit<float>& a, const igl::Hit<float>& b) { return a.t < b.t; });
|
||||
|
||||
// Remove duplicates. They sometimes appear, for example when the ray is cast
|
||||
// along an axis of a cube due to floating-point approximations in igl (?)
|
||||
// BBS: STUDIO-2591 A mesh with overlapping faces cannot be painted
|
||||
//hits.erase(std::unique(hits.begin(), hits.end(),
|
||||
// [](const igl::Hit& a, const igl::Hit& b)
|
||||
// [](const igl::Hit<float>& a, const igl::Hit<float>& b)
|
||||
// { return a.t == b.t; }),
|
||||
// hits.end());
|
||||
|
||||
// Convert the igl::Hit into hit_result
|
||||
// Convert the igl::Hit<float> into hit_result
|
||||
outs.reserve(hits.size());
|
||||
for (const igl::Hit& hit : hits) {
|
||||
for (const igl::Hit<float>& hit : hits) {
|
||||
outs.emplace_back(IndexedMesh::hit_result(*this));
|
||||
outs.back().m_t = double(hit.t);
|
||||
outs.back().m_dir = dir;
|
||||
|
||||
@@ -1,55 +1,41 @@
|
||||
#include "TriangleMeshDeal.hpp"
|
||||
|
||||
#include <igl/read_triangle_mesh.h>
|
||||
#include <igl/loop.h>
|
||||
#include <igl/upsample.h>
|
||||
#include <igl/false_barycentric_subdivision.h>
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
TriangleMesh TriangleMeshDeal::smooth_triangle_mesh(const TriangleMesh &mesh, bool &ok)
|
||||
TriangleMesh TriangleMeshDeal::smooth_triangle_mesh(const TriangleMesh& mesh, bool& ok)
|
||||
{
|
||||
{
|
||||
using namespace std;
|
||||
using namespace igl;
|
||||
Eigen::MatrixXi OF, F;
|
||||
Eigen::MatrixXd OV, V;
|
||||
auto vertices_count = mesh.its.vertices.size();
|
||||
OV = Eigen::MatrixXd(vertices_count, 3);
|
||||
for (int i = 0; i < vertices_count; i++) {
|
||||
auto v = mesh.its.vertices[i];
|
||||
OV.row(i) << v[0], v[1], v[2];
|
||||
}
|
||||
auto indices_count = mesh.its.indices.size();
|
||||
OF = Eigen::MatrixXi(indices_count, 3);
|
||||
for (int i = 0; i < indices_count; i++) {
|
||||
auto face = mesh.its.indices[i];
|
||||
OF.row(i) << face[0], face[1], face[2];
|
||||
}
|
||||
//igl:: read_triangle_mesh( "E:/Download/libigl-2.6.0/out/build/x64-Debug/_deps/libigl_tutorial_data-src/decimated-knight.off", OV, OF);
|
||||
V = OV;
|
||||
F = OF;
|
||||
{
|
||||
using namespace igl;
|
||||
typedef Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::DontAlign | Eigen::RowMajor> RowMatrixX3f;
|
||||
typedef Eigen::Matrix<int, Eigen::Dynamic, 3, Eigen::DontAlign | Eigen::RowMajor> RowMatrixX3i;
|
||||
|
||||
//igl::upsample(Eigen::MatrixXd(V), Eigen::MatrixXi(F), V, F);
|
||||
ok = true;
|
||||
if (!igl::loop(Eigen::MatrixXd(V), Eigen::MatrixXi(F), V, F)) {
|
||||
ok = false;
|
||||
return TriangleMesh();
|
||||
}
|
||||
//igl::false_barycentric_subdivision(Eigen::MatrixXd(V), Eigen::MatrixXi(F), V, F);
|
||||
indexed_triangle_set its;
|
||||
int vertex_count = V.rows();
|
||||
its.vertices.resize(vertex_count);
|
||||
for (int i = 0; i < vertex_count; i++) {
|
||||
its.vertices[i] = V.row(i).cast<float>();
|
||||
}
|
||||
int indice_count = F.rows();
|
||||
its.indices.resize(indice_count);
|
||||
for (int i = 0; i < indice_count; i++) {
|
||||
auto cur = F.row(i);
|
||||
its.indices[i] = Slic3r::Vec3i32(cur[0], cur[1], cur[2]);
|
||||
}
|
||||
TriangleMesh result_mesh(its);
|
||||
return result_mesh;
|
||||
}
|
||||
auto vertices_count = mesh.its.vertices.size();
|
||||
auto indices_count = mesh.its.indices.size();
|
||||
// Use Map to map the vertices and indicies into Matrixes without requiring a copy.
|
||||
const Eigen::Map<const RowMatrixX3f> OV(mesh.its.vertices[0].data(), vertices_count, 3);
|
||||
const Eigen::Map<const RowMatrixX3i> OF(mesh.its.indices[0].data(), indices_count, 3);
|
||||
Eigen::MatrixX3f V;
|
||||
Eigen::MatrixX3i F;
|
||||
|
||||
ok = true;
|
||||
// TODO: add validation checks for the input mesh? Is this really necessary?
|
||||
// if ( <not OK> ) {
|
||||
// ok = false;
|
||||
// return TriangleMesh();
|
||||
// }
|
||||
loop(OV, OF, V, F);
|
||||
|
||||
indexed_triangle_set its;
|
||||
auto iterv = V.rowwise();
|
||||
auto iterf = F.rowwise();
|
||||
its.vertices.assign(iterv.cbegin(), iterv.cend());
|
||||
its.indices.assign(iterf.cbegin(), iterf.cend());
|
||||
TriangleMesh result_mesh(its);
|
||||
return result_mesh;
|
||||
}
|
||||
}
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -114,12 +114,13 @@ void set_logging_level(unsigned int level)
|
||||
{
|
||||
logSeverity = level_to_boost(level);
|
||||
|
||||
// Force at debug level logging for pre-release builds.
|
||||
// Orca: force at info or lower level logging for pre-release builds.
|
||||
// Note: not setting to debug or trace as they might affect long time usage especially with BBL printers.
|
||||
const std::string version = SoftFever_VERSION;
|
||||
if (boost::algorithm::icontains(version, "dev") ||
|
||||
boost::algorithm::icontains(version, "alpha") ||
|
||||
boost::algorithm::icontains(version, "beta")) {
|
||||
logSeverity = boost::log::trivial::debug;
|
||||
if (level > (unsigned int) boost::log::trivial::info &&
|
||||
(boost::algorithm::icontains(version, "dev") || boost::algorithm::icontains(version, "alpha") ||
|
||||
boost::algorithm::icontains(version, "beta"))) {
|
||||
logSeverity = boost::log::trivial::info;
|
||||
}
|
||||
|
||||
boost::log::core::get()->set_filter
|
||||
|
||||
Reference in New Issue
Block a user