mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-13 19:25:59 +08:00
Merge branch 'tm_hollowing_optimization_stable' into dev_250
This commit is contained in:
commit
374cb237ed
@ -8,22 +8,16 @@ if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||
set(_q QUIET)
|
||||
endif()
|
||||
|
||||
# Only consider the config scripts if not building with the static dependencies
|
||||
# and this call is not made from a static dependency build (e.g. dep_OpenVDB will use this module)
|
||||
# BUILD_SHARED_LIBS will always be defined for dependency projects and will be OFF.
|
||||
# Newer versions of TBB also discourage from using TBB as a static library
|
||||
if (NOT SLIC3R_STATIC AND (NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS))
|
||||
find_package(${CMAKE_FIND_PACKAGE_NAME} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} CONFIG ${_q})
|
||||
|
||||
if(NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FOUND)
|
||||
message(STATUS "Falling back to MODULE search for ${CMAKE_FIND_PACKAGE_NAME}...")
|
||||
else()
|
||||
message(STATUS "${CMAKE_FIND_PACKAGE_NAME} found in ${${CMAKE_FIND_PACKAGE_NAME}_DIR}")
|
||||
endif()
|
||||
find_package(${CMAKE_FIND_PACKAGE_NAME} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} CONFIG ${_q})
|
||||
|
||||
if(NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FOUND)
|
||||
message(STATUS "Falling back to MODULE search for ${CMAKE_FIND_PACKAGE_NAME}...")
|
||||
else()
|
||||
message(STATUS "${CMAKE_FIND_PACKAGE_NAME} found in ${${CMAKE_FIND_PACKAGE_NAME}_DIR}")
|
||||
endif()
|
||||
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FOUND)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindTBB.cmake.in)
|
||||
|
14
deps/OpenVDB/OpenVDB.cmake
vendored
14
deps/OpenVDB/OpenVDB.cmake
vendored
@ -6,9 +6,17 @@ else()
|
||||
set(_build_static ON)
|
||||
endif()
|
||||
|
||||
set (_openvdb_vdbprint ON)
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
|
||||
# Build fails on raspberry pi due to missing link directive to latomic
|
||||
# Let's hope it will be fixed soon.
|
||||
set (_openvdb_vdbprint OFF)
|
||||
endif ()
|
||||
|
||||
prusaslicer_add_cmake_project(OpenVDB
|
||||
URL https://github.com/tamasmeszaros/openvdb/archive/refs/tags/v6.2.1-prusa3d.zip #v6.2.1 patched
|
||||
URL_HASH SHA256=caf9f0c91976722883ff9cb32420ef142af22f7e625fc643b91c23d6e4172f62
|
||||
# 8.2 patched
|
||||
URL https://github.com/tamasmeszaros/openvdb/archive/a68fd58d0e2b85f01adeb8b13d7555183ab10aa5.zip
|
||||
URL_HASH SHA256=f353e7b99bd0cbfc27ac9082de51acf32a8bc0b3e21ff9661ecca6f205ec1d81
|
||||
DEPENDS dep_TBB dep_Blosc dep_OpenEXR dep_Boost
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
@ -18,7 +26,7 @@ prusaslicer_add_cmake_project(OpenVDB
|
||||
-DOPENVDB_CORE_STATIC=${_build_static}
|
||||
-DOPENVDB_ENABLE_RPATH:BOOL=OFF
|
||||
-DTBB_STATIC=${_build_static}
|
||||
-DOPENVDB_BUILD_VDB_PRINT=ON
|
||||
-DOPENVDB_BUILD_VDB_PRINT=${_openvdb_vdbprint}
|
||||
-DDISABLE_DEPENDENCY_VERSION_CHECKS=ON # Centos6 has old zlib
|
||||
)
|
||||
|
||||
|
7
deps/TBB/TBB.cmake
vendored
7
deps/TBB/TBB.cmake
vendored
@ -1,11 +1,10 @@
|
||||
prusaslicer_add_cmake_project(
|
||||
TBB
|
||||
URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz"
|
||||
URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe
|
||||
URL "https://github.com/oneapi-src/oneTBB/archive/refs/tags/v2021.5.0.zip"
|
||||
URL_HASH SHA256=83ea786c964a384dd72534f9854b419716f412f9d43c0be88d41874763e7bb47
|
||||
CMAKE_ARGS
|
||||
-DTBB_BUILD_SHARED=OFF
|
||||
-DTBB_BUILD_TESTS=OFF
|
||||
-DTBB_BUILD_TESTS=OFF
|
||||
-DTBB_TEST=OFF
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
-DCMAKE_DEBUG_POSTFIX=_debug
|
||||
)
|
||||
|
@ -407,6 +407,12 @@ if(SLIC3R_PROFILE)
|
||||
target_link_libraries(libslic3r Shiny)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# This flag prevents the need for minimum SDK version 10.14
|
||||
# currently, PS targets v10.12
|
||||
target_compile_options(libslic3r PUBLIC "-fno-aligned-allocation")
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||
add_precompiled_header(libslic3r pchheader.hpp FORCEINCLUDE)
|
||||
endif ()
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <openvdb/tools/VolumeToMesh.h>
|
||||
#include <openvdb/tools/Composite.h>
|
||||
#include <openvdb/tools/LevelSetRebuild.h>
|
||||
#include <openvdb/tools/FastSweeping.h>
|
||||
|
||||
//#include "MTUtils.hpp"
|
||||
|
||||
@ -42,16 +43,13 @@ public:
|
||||
: its{m}, voxel_scale{voxel_sc} {};
|
||||
};
|
||||
|
||||
// TODO: Do I need to call initialize? Seems to work without it as well but the
|
||||
// docs say it should be called ones. It does a mutex lock-unlock sequence all
|
||||
// even if was called previously.
|
||||
openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
const openvdb::math::Transform &tr,
|
||||
float voxel_scale,
|
||||
float exteriorBandWidth,
|
||||
float interiorBandWidth,
|
||||
int flags)
|
||||
float interiorBandWidth)
|
||||
{
|
||||
// Might not be needed but this is now proven to be working
|
||||
openvdb::initialize();
|
||||
|
||||
std::vector<indexed_triangle_set> meshparts = its_split(mesh);
|
||||
@ -64,23 +62,35 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
openvdb::FloatGrid::Ptr grid;
|
||||
for (auto &m : meshparts) {
|
||||
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||
TriangleMeshDataAdapter{m, voxel_scale}, tr, exteriorBandWidth,
|
||||
interiorBandWidth, flags);
|
||||
TriangleMeshDataAdapter{m, voxel_scale}, tr, 1.f, 1.f);
|
||||
|
||||
if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
|
||||
else if (subgrid) grid = std::move(subgrid);
|
||||
}
|
||||
|
||||
if (grid) {
|
||||
grid = openvdb::tools::levelSetRebuild(*grid, 0., exteriorBandWidth,
|
||||
interiorBandWidth);
|
||||
} else if(meshparts.empty()) {
|
||||
if (meshparts.size() > 1) {
|
||||
// This is needed to avoid various artefacts on multipart meshes.
|
||||
// TODO: replace with something faster
|
||||
grid = openvdb::tools::levelSetRebuild(*grid, 0., 1.f, 1.f);
|
||||
}
|
||||
if(meshparts.empty()) {
|
||||
// Splitting failed, fall back to hollow the original mesh
|
||||
grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||
TriangleMeshDataAdapter{mesh}, tr, exteriorBandWidth,
|
||||
interiorBandWidth, flags);
|
||||
TriangleMeshDataAdapter{mesh}, tr, 1.f, 1.f);
|
||||
}
|
||||
|
||||
constexpr int DilateIterations = 1;
|
||||
|
||||
grid = openvdb::tools::dilateSdf(
|
||||
*grid, interiorBandWidth, openvdb::tools::NN_FACE_EDGE,
|
||||
DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_LESS_THAN_ISOVALUE);
|
||||
|
||||
grid = openvdb::tools::dilateSdf(
|
||||
*grid, exteriorBandWidth, openvdb::tools::NN_FACE_EDGE,
|
||||
DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE);
|
||||
|
||||
grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale));
|
||||
|
||||
return grid;
|
||||
@ -133,4 +143,15 @@ openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso)
|
||||
{
|
||||
auto new_grid = openvdb::tools::levelSetRebuild(grid, float(iso));
|
||||
|
||||
// Copies voxel_scale metadata, if it exists.
|
||||
new_grid->insertMeta(*grid.deepCopyMeta());
|
||||
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -30,18 +30,20 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh,
|
||||
const openvdb::math::Transform &tr = {},
|
||||
float voxel_scale = 1.f,
|
||||
float exteriorBandWidth = 3.0f,
|
||||
float interiorBandWidth = 3.0f,
|
||||
int flags = 0);
|
||||
float interiorBandWidth = 3.0f);
|
||||
|
||||
indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid,
|
||||
double isovalue = 0.0,
|
||||
double adaptivity = 0.0,
|
||||
bool relaxDisorientedTriangles = true);
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso);
|
||||
|
||||
openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
|
||||
double iso,
|
||||
double ext_range = 3.,
|
||||
double int_range = 3.);
|
||||
double ext_range,
|
||||
double int_range);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <openvdb/tools/FastSweeping.h>
|
||||
|
||||
#include <libslic3r/MTUtils.hpp>
|
||||
#include <libslic3r/I18N.hpp>
|
||||
|
||||
@ -27,12 +29,10 @@ struct Interior {
|
||||
openvdb::FloatGrid::Ptr gridptr;
|
||||
mutable std::optional<openvdb::FloatGrid::ConstAccessor> accessor;
|
||||
|
||||
double closing_distance = 0.;
|
||||
double iso_surface = 0.;
|
||||
double thickness = 0.;
|
||||
double voxel_scale = 1.;
|
||||
double nb_in = 3.; // narrow band width inwards
|
||||
double nb_out = 3.; // narrow band width outwards
|
||||
// Full narrow band is the sum of the two above values.
|
||||
double full_narrowb = 2.;
|
||||
|
||||
void reset_accessor() const // This resets the accessor and its cache
|
||||
// Not a thread safe call!
|
||||
@ -63,10 +63,11 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
double voxel_scale,
|
||||
double closing_dist)
|
||||
{
|
||||
double offset = voxel_scale * min_thickness;
|
||||
double D = voxel_scale * closing_dist;
|
||||
float out_range = 0.1f * float(offset);
|
||||
double offset = voxel_scale * min_thickness;
|
||||
double D = voxel_scale * closing_dist;
|
||||
float in_range = 1.1f * float(offset + D);
|
||||
auto narrowb = 1.;
|
||||
float out_range = narrowb;
|
||||
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(0, L("Hollowing"));
|
||||
@ -84,8 +85,21 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
else ctl.statuscb(30, L("Hollowing"));
|
||||
|
||||
double iso_surface = D;
|
||||
auto narrowb = double(in_range);
|
||||
gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb);
|
||||
if (D > EPSILON) {
|
||||
in_range = narrowb;
|
||||
gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, in_range);
|
||||
|
||||
constexpr int DilateIterations = 1;
|
||||
|
||||
gridptr = openvdb::tools::dilateSdf(
|
||||
*gridptr, std::ceil(iso_surface),
|
||||
openvdb::tools::NN_FACE_EDGE_VERTEX, DilateIterations,
|
||||
openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE);
|
||||
|
||||
out_range = iso_surface;
|
||||
} else {
|
||||
iso_surface = -offset;
|
||||
}
|
||||
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(70, L("Hollowing"));
|
||||
@ -99,11 +113,10 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
|
||||
if (ctl.stopcondition()) return {};
|
||||
else ctl.statuscb(100, L("Hollowing"));
|
||||
|
||||
interior->closing_distance = D;
|
||||
interior->thickness = offset;
|
||||
interior->iso_surface = iso_surface;
|
||||
interior->thickness = offset;
|
||||
interior->voxel_scale = voxel_scale;
|
||||
interior->nb_in = narrowb;
|
||||
interior->nb_out = narrowb;
|
||||
interior->full_narrowb = out_range + in_range;
|
||||
|
||||
return interior;
|
||||
}
|
||||
@ -112,8 +125,9 @@ InteriorPtr generate_interior(const TriangleMesh & mesh,
|
||||
const HollowingConfig &hc,
|
||||
const JobController & ctl)
|
||||
{
|
||||
static const double MIN_OVERSAMPL = 3.5;
|
||||
static const double MAX_OVERSAMPL = 8.;
|
||||
static constexpr double MIN_SAMPLES_IN_WALL = 3.5;
|
||||
static constexpr double MAX_OVERSAMPL = 8.;
|
||||
static constexpr double UNIT_VOLUME = 500000; // empiric
|
||||
|
||||
// I can't figure out how to increase the grid resolution through openvdb
|
||||
// API so the model will be scaled up before conversion and the result
|
||||
@ -121,12 +135,25 @@ InteriorPtr generate_interior(const TriangleMesh & mesh,
|
||||
// scales the whole geometry down, and doesn't increase the number of
|
||||
// voxels.
|
||||
//
|
||||
// max 8x upscale, min is native voxel size
|
||||
auto voxel_scale = MIN_OVERSAMPL + (MAX_OVERSAMPL - MIN_OVERSAMPL) * hc.quality;
|
||||
// First an allowed range for voxel scale is determined from an initial
|
||||
// range of <MIN_SAMPLES_IN_WALL, MAX_OVERSAMPL>. The final voxel scale is
|
||||
// then chosen from this range using the 'quality:<0, 1>' parameter.
|
||||
// The minimum can be lowered if the wall thickness is great enough and
|
||||
// the maximum is lowered if the model volume very big.
|
||||
double mesh_vol = its_volume(mesh.its);
|
||||
double sc_divider = std::max(1.0, (mesh_vol / UNIT_VOLUME));
|
||||
double min_oversampl = std::max(MIN_SAMPLES_IN_WALL / hc.min_thickness, 1.);
|
||||
double max_oversampl_scaled = std::max(min_oversampl, MAX_OVERSAMPL / sc_divider);
|
||||
auto voxel_scale = min_oversampl + (max_oversampl_scaled - min_oversampl) * hc.quality;
|
||||
|
||||
InteriorPtr interior =
|
||||
generate_interior_verbose(mesh, ctl, hc.min_thickness, voxel_scale,
|
||||
hc.closing_distance);
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: max oversampl will be: " << max_oversampl_scaled;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: voxel scale will be: " << voxel_scale;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Hollowing: mesh volume is: " << mesh_vol;
|
||||
|
||||
InteriorPtr interior = generate_interior_verbose(mesh, ctl,
|
||||
hc.min_thickness,
|
||||
voxel_scale,
|
||||
hc.closing_distance);
|
||||
|
||||
if (interior && !interior->mesh.empty()) {
|
||||
|
||||
@ -342,22 +369,18 @@ struct TriangleBubble { Vec3f center; double R; };
|
||||
static double get_distance(const TriangleBubble &b, const Interior &interior)
|
||||
{
|
||||
double R = b.R * interior.voxel_scale;
|
||||
double D = get_distance_raw(b.center, interior);
|
||||
double D = 2. * R;
|
||||
double Dst = get_distance_raw(b.center, interior);
|
||||
|
||||
return (D > 0. && R >= interior.nb_out) ||
|
||||
(D < 0. && R >= interior.nb_in) ||
|
||||
((D - R) < 0. && 2 * R > interior.thickness) ?
|
||||
return D > interior.full_narrowb ||
|
||||
((Dst - R) < 0. && 2 * R > interior.thickness) ?
|
||||
std::nan("") :
|
||||
// FIXME: Adding interior.voxel_scale is a compromise supposed
|
||||
// to prevent the deletion of the triangles forming the interior
|
||||
// itself. This has a side effect that a small portion of the
|
||||
// bad triangles will still be visible.
|
||||
D - interior.closing_distance /*+ 2 * interior.voxel_scale*/;
|
||||
Dst - interior.iso_surface;
|
||||
}
|
||||
|
||||
double get_distance(const Vec3f &p, const Interior &interior)
|
||||
{
|
||||
double d = get_distance_raw(p, interior) - interior.closing_distance;
|
||||
double d = get_distance_raw(p, interior) - interior.iso_surface;
|
||||
return d / interior.voxel_scale;
|
||||
}
|
||||
|
||||
@ -494,7 +517,7 @@ void remove_inside_triangles(TriangleMesh &mesh, const Interior &interior,
|
||||
if (f.parent != NEW_FACE) // Top parent needs to be removed as well
|
||||
mesh_mods.to_remove[f.parent] = true;
|
||||
|
||||
// If the outside part is between the interior end the exterior
|
||||
// If the outside part is between the interior and the exterior
|
||||
// (inside the wall being invisible), no further division is needed.
|
||||
if ((R + D) < interior.thickness)
|
||||
return false;
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include <libnest2d/tools/benchmark.h>
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) Slic3r::I18N::translate(s)
|
||||
@ -215,6 +217,22 @@ struct FaceHash {
|
||||
}
|
||||
};
|
||||
|
||||
static void exclude_neighbors(const Vec3i &face,
|
||||
std::vector<bool> &mask,
|
||||
const indexed_triangle_set &its,
|
||||
const VertexFaceIndex &index,
|
||||
size_t recursions)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const auto &neighbors_range = index[face(i)];
|
||||
for (size_t fi_n : neighbors_range) {
|
||||
mask[fi_n] = true;
|
||||
if (recursions > 0)
|
||||
exclude_neighbors(its.indices[fi_n], mask, its, index, recursions - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create exclude mask for triangle removal inside hollowed interiors.
|
||||
// This is necessary when the interior is already part of the mesh which was
|
||||
// drilled using CGAL mesh boolean operation. Excluded will be the triangles
|
||||
@ -231,15 +249,6 @@ static std::vector<bool> create_exclude_mask(
|
||||
|
||||
VertexFaceIndex neighbor_index{its};
|
||||
|
||||
auto exclude_neighbors = [&neighbor_index, &exclude_mask](const Vec3i &face)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const auto &neighbors_range = neighbor_index[face(i)];
|
||||
for (size_t fi_n : neighbors_range)
|
||||
exclude_mask[fi_n] = true;
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t fi = 0; fi < its.indices.size(); ++fi) {
|
||||
auto &face = its.indices[fi];
|
||||
|
||||
@ -249,7 +258,7 @@ static std::vector<bool> create_exclude_mask(
|
||||
}
|
||||
|
||||
if (exclude_mask[fi]) {
|
||||
exclude_neighbors(face);
|
||||
exclude_neighbors(face, exclude_mask, its, neighbor_index, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -294,7 +303,7 @@ static std::vector<bool> create_exclude_mask(
|
||||
|
||||
if (D_hole < D_tol && std::abs(dot) < normal_angle_tol) {
|
||||
exclude_mask[fi] = true;
|
||||
exclude_neighbors(face);
|
||||
exclude_neighbors(face, exclude_mask, its, neighbor_index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user