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
This commit is contained in:
parent
7cb3e729ee
commit
e57eca0289
@ -22,74 +22,52 @@ namespace Slic3r {
|
|||||||
class TriangleMeshDataAdapter {
|
class TriangleMeshDataAdapter {
|
||||||
public:
|
public:
|
||||||
const TriangleMesh &mesh;
|
const TriangleMesh &mesh;
|
||||||
|
float voxel_scale;
|
||||||
|
|
||||||
size_t polygonCount() const { return mesh.its.indices.size(); }
|
size_t polygonCount() const { return mesh.its.indices.size(); }
|
||||||
size_t pointCount() const { return mesh.its.vertices.size(); }
|
size_t pointCount() const { return mesh.its.vertices.size(); }
|
||||||
size_t vertexCount(size_t) const { return 3; }
|
size_t vertexCount(size_t) const { return 3; }
|
||||||
|
|
||||||
// Return position pos in local grid index space for polygon n and vertex v
|
// 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<double>() * 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<double>();
|
|
||||||
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
|
// 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
|
// docs say it should be called ones. It does a mutex lock-unlock sequence all
|
||||||
// even if was called previously.
|
// 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,
|
const openvdb::math::Transform &tr,
|
||||||
float exteriorBandWidth,
|
float voxel_scale,
|
||||||
float interiorBandWidth,
|
float exteriorBandWidth,
|
||||||
int flags)
|
float interiorBandWidth,
|
||||||
|
int flags)
|
||||||
{
|
{
|
||||||
openvdb::initialize();
|
openvdb::initialize();
|
||||||
|
|
||||||
TriangleMeshPtrs meshparts = mesh.split();
|
TriangleMeshPtrs meshparts = mesh.split();
|
||||||
|
|
||||||
auto it = std::remove_if(meshparts.begin(), meshparts.end(),
|
auto it = std::remove_if(meshparts.begin(), meshparts.end(),
|
||||||
[](TriangleMesh *m){
|
[](TriangleMesh *m){
|
||||||
m->require_shared_vertices();
|
m->require_shared_vertices();
|
||||||
return !m->is_manifold() || m->volume() < EPSILON;
|
return !m->is_manifold() || m->volume() < EPSILON;
|
||||||
});
|
});
|
||||||
|
|
||||||
meshparts.erase(it, meshparts.end());
|
meshparts.erase(it, meshparts.end());
|
||||||
|
|
||||||
openvdb::FloatGrid::Ptr grid;
|
openvdb::FloatGrid::Ptr grid;
|
||||||
for (TriangleMesh *m : meshparts) {
|
for (TriangleMesh *m : meshparts) {
|
||||||
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||||
TriangleMeshDataAdapter{*m}, tr, exteriorBandWidth,
|
TriangleMeshDataAdapter{*m, voxel_scale}, tr, exteriorBandWidth,
|
||||||
interiorBandWidth, flags);
|
interiorBandWidth, flags);
|
||||||
|
|
||||||
if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
|
if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
|
||||||
@ -106,19 +84,9 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh &mesh,
|
|||||||
interiorBandWidth, flags);
|
interiorBandWidth, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return grid;
|
grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale));
|
||||||
}
|
|
||||||
|
|
||||||
openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D &mesh,
|
return grid;
|
||||||
const openvdb::math::Transform &tr,
|
|
||||||
float exteriorBandWidth,
|
|
||||||
float interiorBandWidth,
|
|
||||||
int flags)
|
|
||||||
{
|
|
||||||
openvdb::initialize();
|
|
||||||
return openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
|
||||||
Contour3DDataAdapter{mesh}, tr, exteriorBandWidth, interiorBandWidth,
|
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Grid>
|
template<class Grid>
|
||||||
@ -128,20 +96,25 @@ sla::Contour3D _volumeToMesh(const Grid &grid,
|
|||||||
bool relaxDisorientedTriangles)
|
bool relaxDisorientedTriangles)
|
||||||
{
|
{
|
||||||
openvdb::initialize();
|
openvdb::initialize();
|
||||||
|
|
||||||
std::vector<openvdb::Vec3s> points;
|
std::vector<openvdb::Vec3s> points;
|
||||||
std::vector<openvdb::Vec3I> triangles;
|
std::vector<openvdb::Vec3I> triangles;
|
||||||
std::vector<openvdb::Vec4I> quads;
|
std::vector<openvdb::Vec4I> quads;
|
||||||
|
|
||||||
openvdb::tools::volumeToMesh(grid, points, triangles, quads, isovalue,
|
openvdb::tools::volumeToMesh(grid, points, triangles, quads, isovalue,
|
||||||
adaptivity, relaxDisorientedTriangles);
|
adaptivity, relaxDisorientedTriangles);
|
||||||
|
|
||||||
|
float scale = 1.;
|
||||||
|
try {
|
||||||
|
scale = grid.template metaValue<float>("voxel_scale");
|
||||||
|
} catch (...) { }
|
||||||
|
|
||||||
sla::Contour3D ret;
|
sla::Contour3D ret;
|
||||||
ret.points.reserve(points.size());
|
ret.points.reserve(points.size());
|
||||||
ret.faces3.reserve(triangles.size());
|
ret.faces3.reserve(triangles.size());
|
||||||
ret.faces4.reserve(quads.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 : triangles) ret.faces3.emplace_back(to_vec3i(v));
|
||||||
for (auto &v : quads) ret.faces4.emplace_back(to_vec4i(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);
|
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
|
} // namespace Slic3r
|
||||||
|
@ -21,14 +21,16 @@ inline Vec3d to_vec3d(const openvdb::Vec3s &v) { return to_vec3f(v).cast<double>
|
|||||||
inline Vec3i to_vec3i(const openvdb::Vec3I &v) { return Vec3i{int(v[0]), int(v[1]), int(v[2])}; }
|
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])}; }
|
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,
|
openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh & mesh,
|
||||||
const openvdb::math::Transform &tr = {},
|
const openvdb::math::Transform &tr = {},
|
||||||
float exteriorBandWidth = 3.0f,
|
float voxel_scale = 1.f,
|
||||||
float interiorBandWidth = 3.0f,
|
|
||||||
int flags = 0);
|
|
||||||
|
|
||||||
openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D & mesh,
|
|
||||||
const openvdb::math::Transform &tr = {},
|
|
||||||
float exteriorBandWidth = 3.0f,
|
float exteriorBandWidth = 3.0f,
|
||||||
float interiorBandWidth = 3.0f,
|
float interiorBandWidth = 3.0f,
|
||||||
int flags = 0);
|
int flags = 0);
|
||||||
|
@ -32,48 +32,44 @@ static TriangleMesh _generate_interior(const TriangleMesh &mesh,
|
|||||||
double voxel_scale,
|
double voxel_scale,
|
||||||
double closing_dist)
|
double closing_dist)
|
||||||
{
|
{
|
||||||
TriangleMesh imesh{mesh};
|
|
||||||
|
|
||||||
_scale(voxel_scale, imesh);
|
|
||||||
|
|
||||||
double offset = voxel_scale * min_thickness;
|
double offset = voxel_scale * min_thickness;
|
||||||
double D = voxel_scale * closing_dist;
|
double D = voxel_scale * closing_dist;
|
||||||
float out_range = 0.1f * float(offset);
|
float out_range = 0.1f * float(offset);
|
||||||
float in_range = 1.1f * float(offset + D);
|
float in_range = 1.1f * float(offset + D);
|
||||||
|
|
||||||
if (ctl.stopcondition()) return {};
|
if (ctl.stopcondition()) return {};
|
||||||
else ctl.statuscb(0, L("Hollowing"));
|
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);
|
assert(gridptr);
|
||||||
|
|
||||||
if (!gridptr) {
|
if (!gridptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Returned OpenVDB grid is NULL";
|
BOOST_LOG_TRIVIAL(error) << "Returned OpenVDB grid is NULL";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctl.stopcondition()) return {};
|
if (ctl.stopcondition()) return {};
|
||||||
else ctl.statuscb(30, L("Hollowing"));
|
else ctl.statuscb(30, L("Hollowing"));
|
||||||
|
|
||||||
|
double iso_surface = D;
|
||||||
|
auto narrowb = double(in_range);
|
||||||
if (closing_dist > .0) {
|
if (closing_dist > .0) {
|
||||||
gridptr = redistance_grid(*gridptr, -(offset + D), double(in_range));
|
gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb);
|
||||||
} else {
|
} else {
|
||||||
D = -offset;
|
iso_surface = -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctl.stopcondition()) return {};
|
if (ctl.stopcondition()) return {};
|
||||||
else ctl.statuscb(70, L("Hollowing"));
|
else ctl.statuscb(70, L("Hollowing"));
|
||||||
|
|
||||||
double iso_surface = D;
|
|
||||||
double adaptivity = 0.;
|
double adaptivity = 0.;
|
||||||
|
|
||||||
auto omesh = grid_to_mesh(*gridptr, iso_surface, adaptivity);
|
auto omesh = grid_to_mesh(*gridptr, iso_surface, adaptivity);
|
||||||
|
|
||||||
_scale(1. / voxel_scale, omesh);
|
|
||||||
|
|
||||||
if (ctl.stopcondition()) return {};
|
if (ctl.stopcondition()) return {};
|
||||||
else ctl.statuscb(100, L("Hollowing"));
|
else ctl.statuscb(100, L("Hollowing"));
|
||||||
|
|
||||||
return omesh;
|
return omesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user