From e57eca0289e2f5e3e6bb2f6d6fa53e0fc48987c3 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 17 Dec 2020 13:38:09 +0100 Subject: [PATCH] Add voxel scale to openvdb metadata. To be able to retrieve that information from a generated grid alone. To avoid the copying of input mesh (for scaling) when doing the hollowing Also remove some unused stuff from OpenVDBUtils --- src/libslic3r/OpenVDBUtils.cpp | 110 +++++++++++++------------------- src/libslic3r/OpenVDBUtils.hpp | 14 ++-- src/libslic3r/SLA/Hollowing.cpp | 36 +++++------ 3 files changed, 70 insertions(+), 90 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 0f5bfa157..259cd1cbd 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -22,74 +22,52 @@ namespace Slic3r { class TriangleMeshDataAdapter { public: const TriangleMesh &mesh; - + float voxel_scale; + size_t polygonCount() const { return mesh.its.indices.size(); } size_t pointCount() const { return mesh.its.vertices.size(); } size_t vertexCount(size_t) const { return 3; } - + // Return position pos in local grid index space for polygon n and vertex v - void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const; + // The actual mesh will appear to openvdb as scaled uniformly by voxel_size + // And the voxel count per unit volume can be affected this way. + void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const + { + auto vidx = size_t(mesh.its.indices[n](Eigen::Index(v))); + Slic3r::Vec3d p = mesh.its.vertices[vidx].cast() * voxel_scale; + pos = {p.x(), p.y(), p.z()}; + } + + TriangleMeshDataAdapter(const TriangleMesh &m, float voxel_sc = 1.f) + : mesh{m}, voxel_scale{voxel_sc} {}; }; -class Contour3DDataAdapter { -public: - const sla::Contour3D &mesh; - - size_t polygonCount() const { return mesh.faces3.size() + mesh.faces4.size(); } - size_t pointCount() const { return mesh.points.size(); } - size_t vertexCount(size_t n) const { return n < mesh.faces3.size() ? 3 : 4; } - - // Return position pos in local grid index space for polygon n and vertex v - void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const; -}; - -void TriangleMeshDataAdapter::getIndexSpacePoint(size_t n, - size_t v, - openvdb::Vec3d &pos) const -{ - auto vidx = size_t(mesh.its.indices[n](Eigen::Index(v))); - Slic3r::Vec3d p = mesh.its.vertices[vidx].cast(); - pos = {p.x(), p.y(), p.z()}; -} - -void Contour3DDataAdapter::getIndexSpacePoint(size_t n, - size_t v, - openvdb::Vec3d &pos) const -{ - size_t vidx = 0; - if (n < mesh.faces3.size()) vidx = size_t(mesh.faces3[n](Eigen::Index(v))); - else vidx = size_t(mesh.faces4[n - mesh.faces3.size()](Eigen::Index(v))); - - Slic3r::Vec3d p = mesh.points[vidx]; - pos = {p.x(), p.y(), p.z()}; -} - - // 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 TriangleMesh &mesh, +openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh & mesh, const openvdb::math::Transform &tr, - float exteriorBandWidth, - float interiorBandWidth, - int flags) + float voxel_scale, + float exteriorBandWidth, + float interiorBandWidth, + int flags) { openvdb::initialize(); TriangleMeshPtrs meshparts = mesh.split(); auto it = std::remove_if(meshparts.begin(), meshparts.end(), - [](TriangleMesh *m){ - m->require_shared_vertices(); - return !m->is_manifold() || m->volume() < EPSILON; - }); + [](TriangleMesh *m){ + m->require_shared_vertices(); + return !m->is_manifold() || m->volume() < EPSILON; + }); meshparts.erase(it, meshparts.end()); openvdb::FloatGrid::Ptr grid; for (TriangleMesh *m : meshparts) { auto subgrid = openvdb::tools::meshToVolume( - TriangleMeshDataAdapter{*m}, tr, exteriorBandWidth, + TriangleMeshDataAdapter{*m, voxel_scale}, tr, exteriorBandWidth, interiorBandWidth, flags); if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid); @@ -106,19 +84,9 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh &mesh, interiorBandWidth, flags); } - return grid; -} + grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale)); -openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D &mesh, - const openvdb::math::Transform &tr, - float exteriorBandWidth, - float interiorBandWidth, - int flags) -{ - openvdb::initialize(); - return openvdb::tools::meshToVolume( - Contour3DDataAdapter{mesh}, tr, exteriorBandWidth, interiorBandWidth, - flags); + return grid; } template @@ -128,20 +96,25 @@ sla::Contour3D _volumeToMesh(const Grid &grid, bool relaxDisorientedTriangles) { openvdb::initialize(); - + std::vector points; std::vector triangles; std::vector quads; - + openvdb::tools::volumeToMesh(grid, points, triangles, quads, isovalue, adaptivity, relaxDisorientedTriangles); - + + float scale = 1.; + try { + scale = grid.template metaValue("voxel_scale"); + } catch (...) { } + sla::Contour3D ret; ret.points.reserve(points.size()); ret.faces3.reserve(triangles.size()); ret.faces4.reserve(quads.size()); - for (auto &v : points) ret.points.emplace_back(to_vec3d(v)); + for (auto &v : points) ret.points.emplace_back(to_vec3d(v) / scale); for (auto &v : triangles) ret.faces3.emplace_back(to_vec3i(v)); for (auto &v : quads) ret.faces4.emplace_back(to_vec4i(v)); @@ -166,9 +139,18 @@ sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid, relaxDisorientedTriangles); } -openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, double iso, double er, double ir) +openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, + double iso, + double er, + double ir) { - return openvdb::tools::levelSetRebuild(grid, float(iso), float(er), float(ir)); + auto new_grid = openvdb::tools::levelSetRebuild(grid, float(iso), + float(er), float(ir)); + + // Copies voxel_scale metadata, if it exists. + new_grid->insertMeta(*grid.deepCopyMeta()); + + return new_grid; } } // namespace Slic3r diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index aa4b5154a..5df816abb 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -21,14 +21,16 @@ inline Vec3d to_vec3d(const openvdb::Vec3s &v) { return to_vec3f(v).cast inline Vec3i to_vec3i(const openvdb::Vec3I &v) { return Vec3i{int(v[0]), int(v[1]), int(v[2])}; } inline Vec4i to_vec4i(const openvdb::Vec4I &v) { return Vec4i{int(v[0]), int(v[1]), int(v[2]), int(v[3])}; } +// Here voxel_scale defines the scaling of voxels which affects the voxel count. +// 1.0 value means a voxel for every unit cube. 2 means the model is scaled to +// be 2x larger and the voxel count is increased by the increment in the scaled +// volume, thus 4 times. This kind a sampling accuracy selection is not +// achievable through the Transform parameter. (TODO: or is it?) +// The resulting grid will contain the voxel_scale in its metadata under the +// "voxel_scale" key to be used in grid_to_mesh function. openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh & mesh, const openvdb::math::Transform &tr = {}, - float exteriorBandWidth = 3.0f, - float interiorBandWidth = 3.0f, - int flags = 0); - -openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D & mesh, - const openvdb::math::Transform &tr = {}, + float voxel_scale = 1.f, float exteriorBandWidth = 3.0f, float interiorBandWidth = 3.0f, int flags = 0); diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 6df752fd3..61e1e122b 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -32,48 +32,44 @@ static TriangleMesh _generate_interior(const TriangleMesh &mesh, double voxel_scale, double closing_dist) { - TriangleMesh imesh{mesh}; - - _scale(voxel_scale, imesh); - double offset = voxel_scale * min_thickness; double D = voxel_scale * closing_dist; float out_range = 0.1f * float(offset); float in_range = 1.1f * float(offset + D); - + if (ctl.stopcondition()) return {}; else ctl.statuscb(0, L("Hollowing")); - - auto gridptr = mesh_to_grid(imesh, {}, out_range, in_range); - + + auto gridptr = mesh_to_grid(mesh, {}, voxel_scale, out_range, in_range); + assert(gridptr); - + if (!gridptr) { BOOST_LOG_TRIVIAL(error) << "Returned OpenVDB grid is NULL"; return {}; } - + if (ctl.stopcondition()) return {}; else ctl.statuscb(30, L("Hollowing")); - + + double iso_surface = D; + auto narrowb = double(in_range); if (closing_dist > .0) { - gridptr = redistance_grid(*gridptr, -(offset + D), double(in_range)); + gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb); } else { - D = -offset; + iso_surface = -offset; } - + if (ctl.stopcondition()) return {}; else ctl.statuscb(70, L("Hollowing")); - - double iso_surface = D; + double adaptivity = 0.; + auto omesh = grid_to_mesh(*gridptr, iso_surface, adaptivity); - - _scale(1. / voxel_scale, omesh); - + if (ctl.stopcondition()) return {}; else ctl.statuscb(100, L("Hollowing")); - + return omesh; }