|
10 | 10 | #include "PrintConfig.hpp" |
11 | 11 | #include "Support/SupportMaterial.hpp" |
12 | 12 | #include "Support/SupportSpotsGenerator.hpp" |
13 | | -#include "Support/TreeSupport.hpp" |
| 13 | +#ifdef HAS_RUST_TREE_SUPPORTS |
| 14 | +#include "Support/TreeSupportRust/include/orca_tree_supports.h" |
| 15 | +#endif |
14 | 16 | #include "Surface.hpp" |
15 | 17 | #include "Slicing.hpp" |
16 | 18 | #include "Tesselate.hpp" |
@@ -77,9 +79,7 @@ namespace Slic3r { |
77 | 79 | // Constructor is called from the main thread, therefore all Model / ModelObject / ModelIntance data are valid. |
78 | 80 | PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transform3d& trafo, PrintInstances&& instances) : |
79 | 81 | PrintObjectBaseWithState(print, model_object), |
80 | | - m_trafo(trafo), |
81 | | - // BBS |
82 | | - m_tree_support_preview_cache(nullptr) |
| 82 | + m_trafo(trafo) |
83 | 83 | { |
84 | 84 | // Compute centering offet to be applied to our meshes so that we work with smaller coordinates |
85 | 85 | // requiring less bits to represent Clipper coordinates. |
@@ -965,16 +965,6 @@ void PrintObject::clear_support_layers() |
965 | 965 | } |
966 | 966 | } |
967 | 967 |
|
968 | | -std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache() |
969 | | -{ |
970 | | - if (!m_tree_support_preview_cache) { |
971 | | - const coordf_t xy_distance = m_config.support_object_xy_distance.value; |
972 | | - m_tree_support_preview_cache = std::make_shared<TreeSupportData>(*this, xy_distance, g_config_tree_support_collision_resolution); |
973 | | - } |
974 | | - |
975 | | - return m_tree_support_preview_cache; |
976 | | -} |
977 | | - |
978 | 968 | SupportLayer* PrintObject::add_tree_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z) |
979 | 969 | { |
980 | 970 | m_support_layers.emplace_back(new SupportLayer(id, 0, this, height, print_z, slice_z)); |
@@ -3944,9 +3934,114 @@ void PrintObject::combine_infill() |
3944 | 3934 | void PrintObject::_generate_support_material() |
3945 | 3935 | { |
3946 | 3936 | if (is_tree(m_config.support_type.value)) { |
3947 | | - TreeSupport tree_support(*this, m_slicing_params); |
3948 | | - tree_support.throw_on_cancel = [this]() { this->throw_if_canceled(); }; |
3949 | | - tree_support.generate(); |
| 3937 | +#ifdef HAS_RUST_TREE_SUPPORTS |
| 3938 | + // Use Rust tree support generation via FFI |
| 3939 | + if (m_model_object->volumes.empty()) { |
| 3940 | + BOOST_LOG_TRIVIAL(error) << "Tree support generation: model object has no volumes"; |
| 3941 | + return; |
| 3942 | + } |
| 3943 | + |
| 3944 | + // Default values for tree support parameters not exposed in OrcaSlicer UI |
| 3945 | + constexpr double TREE_SUPPORT_RESOLUTION_MM = 0.025; |
| 3946 | + constexpr double TREE_SUPPORT_MIN_FEATURE_SIZE_MM = 0.1; |
| 3947 | + constexpr double TREE_SUPPORT_XY_OVERHANGS_MM = 0.2; |
| 3948 | + constexpr double TREE_SUPPORT_INTERFACE_SKIP_HEIGHT_MM = 0.3; |
| 3949 | + constexpr double TREE_SUPPORT_BP_DIAMETER_MM = 7.5; // buildplate contact diameter |
| 3950 | + constexpr double TREE_SUPPORT_MIN_BOTTOM_AREA_MM = 1.0; |
| 3951 | + constexpr double TREE_SUPPORT_MAX_DIAMETER_INCREASE_MM = 1.0; // max diameter increase per merge |
| 3952 | + constexpr double TREE_SUPPORT_MIN_HEIGHT_TO_MODEL_MM = 1.0; |
| 3953 | + |
| 3954 | + // Populate tree support config from OrcaSlicer print settings |
| 3955 | + TreeSupportConfig cfg = {}; |
| 3956 | + cfg.layer_height = scaled<int64_t>(m_slicing_params.layer_height); |
| 3957 | + cfg.resolution = scaled<int64_t>(TREE_SUPPORT_RESOLUTION_MM); |
| 3958 | + cfg.min_feature_size = scaled<int64_t>(TREE_SUPPORT_MIN_FEATURE_SIZE_MM); |
| 3959 | + cfg.support_angle = m_config.support_angle.value * M_PI / 180.0; |
| 3960 | + cfg.support_line_width = scaled<int64_t>(m_config.support_line_width.get_abs_value(m_config.line_width.value)); |
| 3961 | + cfg.support_roof_line_width = scaled<int64_t>(m_config.support_line_width.get_abs_value(m_config.line_width.value)); |
| 3962 | + cfg.support_bottom_enable = m_config.support_interface_bottom_layers.value > 0; |
| 3963 | + cfg.support_bottom_height = scaled<int64_t>(m_config.support_bottom_z_distance.value); |
| 3964 | + cfg.support_material_buildplate_only = m_config.support_on_build_plate_only.value; |
| 3965 | + cfg.support_xy_distance = scaled<int64_t>(m_config.support_object_xy_distance.value); |
| 3966 | + cfg.support_xy_distance_first_layer = scaled<int64_t>(m_config.support_object_xy_distance.value); |
| 3967 | + cfg.support_xy_distance_overhang = scaled<int64_t>(TREE_SUPPORT_XY_OVERHANGS_MM); |
| 3968 | + cfg.support_top_distance = scaled<int64_t>(m_config.support_top_z_distance.value); |
| 3969 | + cfg.support_bottom_distance = scaled<int64_t>(m_config.support_bottom_z_distance.value); |
| 3970 | + cfg.support_interface_skip_height = scaled<int64_t>(TREE_SUPPORT_INTERFACE_SKIP_HEIGHT_MM); |
| 3971 | + cfg.support_roof_enable = m_config.support_interface_top_layers.value > 0; |
| 3972 | + cfg.support_roof_layers = static_cast<int32_t>(m_config.support_interface_top_layers.value); |
| 3973 | + cfg.support_floor_enable = m_config.support_interface_bottom_layers.value > 0; |
| 3974 | + cfg.support_floor_layers = static_cast<int32_t>(m_config.support_interface_bottom_layers.value); |
| 3975 | + cfg.minimum_roof_area = 0.0; // no minimum, generate roof for all contact areas |
| 3976 | + cfg.support_line_spacing = scaled<int64_t>(m_config.support_base_pattern_spacing.value); |
| 3977 | + cfg.support_bottom_offset = 0; // no offset for bottom support layers |
| 3978 | + cfg.support_wall_count = static_cast<int32_t>(m_config.tree_support_wall_count.value); |
| 3979 | + cfg.support_roof_line_distance = cfg.support_line_width; |
| 3980 | + cfg.minimum_support_area = 0; // no minimum, generate support for all detected overhangs |
| 3981 | + cfg.minimum_bottom_area = scaled<int64_t>(TREE_SUPPORT_MIN_BOTTOM_AREA_MM); |
| 3982 | + cfg.support_offset = 0; // no additional polygon offset |
| 3983 | + cfg.support_tree_angle = m_config.tree_support_branch_angle.value * M_PI / 180.0; |
| 3984 | + cfg.support_tree_angle_slow = m_config.tree_support_angle_slow.value * M_PI / 180.0; |
| 3985 | + cfg.support_tree_branch_diameter = scaled<int64_t>(m_config.tree_support_branch_diameter.value); |
| 3986 | + cfg.support_tree_branch_diameter_angle = m_config.tree_support_branch_diameter_angle.value * M_PI / 180.0; |
| 3987 | + cfg.support_tree_branch_distance = scaled<int64_t>(m_config.tree_support_branch_distance.value); |
| 3988 | + cfg.support_tree_bp_diameter = scaled<int64_t>(TREE_SUPPORT_BP_DIAMETER_MM); |
| 3989 | + cfg.support_tree_top_rate = m_config.tree_support_top_rate.value; |
| 3990 | + cfg.support_tree_tip_diameter = scaled<int64_t>(m_config.tree_support_tip_diameter.value); |
| 3991 | + cfg.support_tree_max_diameter_increase_by_merges_when_support_to_model = scaled<int64_t>(TREE_SUPPORT_MAX_DIAMETER_INCREASE_MM); |
| 3992 | + cfg.support_tree_min_height_to_model = scaled<int64_t>(TREE_SUPPORT_MIN_HEIGHT_TO_MODEL_MM); |
| 3993 | + cfg.support_rests_on_model = !m_config.support_on_build_plate_only.value; |
| 3994 | + |
| 3995 | + // Convert mesh to flat arrays for FFI |
| 3996 | + const indexed_triangle_set &its = m_model_object->volumes.front()->mesh().its; |
| 3997 | + std::vector<float> vertices; |
| 3998 | + vertices.reserve(its.vertices.size() * 3); |
| 3999 | + for (const auto &v : its.vertices) { |
| 4000 | + vertices.push_back(v.x()); |
| 4001 | + vertices.push_back(v.y()); |
| 4002 | + vertices.push_back(v.z()); |
| 4003 | + } |
| 4004 | + std::vector<uint32_t> indices; |
| 4005 | + indices.reserve(its.indices.size() * 3); |
| 4006 | + for (const auto &f : its.indices) { |
| 4007 | + indices.push_back(static_cast<uint32_t>(f[0])); |
| 4008 | + indices.push_back(static_cast<uint32_t>(f[1])); |
| 4009 | + indices.push_back(static_cast<uint32_t>(f[2])); |
| 4010 | + } |
| 4011 | + |
| 4012 | + MeshData mesh_data; |
| 4013 | + mesh_data.vertices = vertices.data(); |
| 4014 | + mesh_data.vertex_count = static_cast<uint32_t>(its.vertices.size()); |
| 4015 | + mesh_data.indices = indices.data(); |
| 4016 | + mesh_data.triangle_count = static_cast<uint32_t>(its.indices.size()); |
| 4017 | + |
| 4018 | + TreeSupportHandle *handle = orca_tree_support_create(&cfg, &mesh_data); |
| 4019 | + if (handle) { |
| 4020 | + SupportOutput *output = orca_tree_support_generate(handle); |
| 4021 | + if (output && output->success) { |
| 4022 | + // Convert Rust output to SupportLayer objects |
| 4023 | + // Note: layer.z is already in millimeters (not scaled) |
| 4024 | + for (uint32_t i = 0; i < output->layer_count; i++) { |
| 4025 | + const auto &layer = output->layers[i]; |
| 4026 | + coordf_t print_z = layer.z; |
| 4027 | + coordf_t height = (i > 0) ? print_z - output->layers[i - 1].z : print_z; |
| 4028 | + add_tree_support_layer(static_cast<int>(i), height, print_z, print_z - 0.5 * height); |
| 4029 | + } |
| 4030 | + } else if (output && !output->success) { |
| 4031 | + BOOST_LOG_TRIVIAL(error) << "Rust tree support generation failed"; |
| 4032 | + } else { |
| 4033 | + BOOST_LOG_TRIVIAL(error) << "Rust tree support generation returned null output"; |
| 4034 | + } |
| 4035 | + if (output) |
| 4036 | + orca_tree_support_destroy_output(output); |
| 4037 | + orca_tree_support_destroy_handle(handle); |
| 4038 | + } else { |
| 4039 | + BOOST_LOG_TRIVIAL(error) << "Failed to create Rust tree support handle"; |
| 4040 | + } |
| 4041 | +#else |
| 4042 | + // Rust tree supports not available — no tree support generation |
| 4043 | + BOOST_LOG_TRIVIAL(warning) << "Tree support generation requires Rust toolchain (HAS_RUST_TREE_SUPPORTS not defined)"; |
| 4044 | +#endif |
3950 | 4045 | } |
3951 | 4046 | else { |
3952 | 4047 | PrintObjectSupportMaterial support_material(this, m_slicing_params); |
@@ -4098,18 +4193,15 @@ template void PrintObject::remove_bridges_from_contacts<Polygons>( |
4098 | 4193 |
|
4099 | 4194 | SupportNecessaryType PrintObject::is_support_necessary() |
4100 | 4195 | { |
4101 | | - const double cantilevel_dist_thresh = scale_(6); |
4102 | | - |
4103 | | - TreeSupport tree_support(*this, m_slicing_params); |
4104 | | - tree_support.support_type = SupportType::stTreeAuto; // need to set support type to fully utilize the power of feature detection |
4105 | | - tree_support.detect_overhangs(true); |
4106 | | - this->clear_support_layers(); |
4107 | | - if (tree_support.has_sharp_tails) |
4108 | | - return SharpTail; |
4109 | | - else if (tree_support.has_cantilever && tree_support.max_cantilever_dist > cantilevel_dist_thresh) |
4110 | | - return Cantilever; |
4111 | | - |
| 4196 | +#ifdef HAS_RUST_TREE_SUPPORTS |
| 4197 | + // With Rust tree supports, use basic overhang detection to determine if support is needed. |
| 4198 | + // The full tree support algorithm handles sharp tails and cantilevers internally. |
| 4199 | + // For now, return NoNeedSupp and let the user explicitly enable supports. |
| 4200 | + // TODO: Implement overhang detection query through Rust FFI |
4112 | 4201 | return NoNeedSupp; |
| 4202 | +#else |
| 4203 | + return NoNeedSupp; |
| 4204 | +#endif |
4113 | 4205 | } |
4114 | 4206 |
|
4115 | 4207 | static void project_triangles_to_slabs(ConstLayerPtrsAdaptor layers, const indexed_triangle_set &custom_facets, const Transform3f &tr, bool seam, std::vector<Polygons> &out) |
|
0 commit comments