Skip to content

Commit

Permalink
Add voxel scale to openvdb metadata.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tamasmeszaros committed Mar 8, 2021
1 parent 7cb3e72 commit e57eca0
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 89 deletions.
108 changes: 45 additions & 63 deletions src/libslic3r/OpenVDBUtils.cpp
Expand Up @@ -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;
};

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()};
}
// 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} {};
};

// 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<openvdb::FloatGrid>(
TriangleMeshDataAdapter{*m}, tr, exteriorBandWidth,
TriangleMeshDataAdapter{*m, voxel_scale}, tr, exteriorBandWidth,
interiorBandWidth, flags);

if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
Expand All @@ -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<openvdb::FloatGrid>(
Contour3DDataAdapter{mesh}, tr, exteriorBandWidth, interiorBandWidth,
flags);
return grid;
}

template<class Grid>
Expand All @@ -128,20 +96,25 @@ sla::Contour3D _volumeToMesh(const Grid &grid,
bool relaxDisorientedTriangles)
{
openvdb::initialize();

std::vector<openvdb::Vec3s> points;
std::vector<openvdb::Vec3I> triangles;
std::vector<openvdb::Vec4I> quads;

openvdb::tools::volumeToMesh(grid, points, triangles, quads, isovalue,
adaptivity, relaxDisorientedTriangles);


float scale = 1.;
try {
scale = grid.template metaValue<float>("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));

Expand All @@ -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
14 changes: 8 additions & 6 deletions src/libslic3r/OpenVDBUtils.hpp
Expand Up @@ -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 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);
Expand Down
36 changes: 16 additions & 20 deletions src/libslic3r/SLA/Hollowing.cpp
Expand Up @@ -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;
}

Expand Down

0 comments on commit e57eca0

Please sign in to comment.