Skip to content

Commit

Permalink
quad mesh
Browse files Browse the repository at this point in the history
Adds support for quad meshes and mixed triangle & quad meshes in createLevelSetThickenedMesh.

Signed-off-by: ghurstunither <[email protected]>
  • Loading branch information
ghurstunither committed Oct 11, 2024
1 parent 862333d commit 10fecd4
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 3 deletions.
125 changes: 123 additions & 2 deletions openvdb/openvdb/tools/LevelSetThickenedMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace OPENVDB_VERSION_NAME {
namespace tools {

/// @brief Return a grid of type @c GridType containing a narrow-band level set
/// representation of a thickened mesh (surface mesh thickened by a radius in all directions).
/// representation of a thickened triangle mesh (thickened by a radius in all directions).
///
/// @param vertices Vertices of the mesh in world units.
/// @param triangles Triangle indices of the mesh.
Expand All @@ -51,6 +51,43 @@ createLevelSetThickenedMesh(
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);

/// @brief Return a grid of type @c GridType containing a narrow-band level set
/// representation of a thickened quad mesh (thickened by a radius in all directions).
///
/// @param vertices Vertices of the mesh in world units.
/// @param quads Quad indices of the mesh.
/// @param radius Radius of the sphere in world units.
/// @param voxelSize Voxel size in world units.
/// @param halfWidth Half the width of the narrow band, in voxel units.
/// @param interrupter Interrupter adhering to the util::NullInterrupter interface.
///
/// @note @c GridType::ValueType must be a floating-point scalar.
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(
const std::vector<Vec3s>& vertices, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);

/// @brief Return a grid of type @c GridType containing a narrow-band level set
/// representation of a thickened triangle & quad mesh (thickened by a radius in all directions).
///
/// @param vertices Vertices of the mesh in world units.
/// @param triangles Triangle indices of the mesh.
/// @param quads Quad indices of the mesh.
/// @param radius Radius of the sphere in world units.
/// @param voxelSize Voxel size in world units.
/// @param halfWidth Half the width of the narrow band, in voxel units.
/// @param interrupter Interrupter adhering to the util::NullInterrupter interface.
///
/// @note @c GridType::ValueType must be a floating-point scalar.
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(const std::vector<Vec3s>& vertices,
const std::vector<Vec3I>& triangles, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);

namespace lvlset {

/// @brief Class used to generate a grid of type @c GridType containing a narrow-band level set
Expand Down Expand Up @@ -1482,7 +1519,6 @@ createLevelSetThickenedMesh(
float radius, float voxelSize, float halfWidth, InterruptT* interrupter)
{
using GridPtr = typename GridType::Ptr;
using TreeT = typename GridType::TreeType;
using ValueT = typename GridType::ValueType;

using Voxelizer = typename lvlset::ThickenedMeshVoxelizer<GridType, InterruptT>;
Expand All @@ -1504,6 +1540,78 @@ createLevelSetThickenedMesh(
return grid;
}

template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetThickenedMesh(
const std::vector<Vec3s>& vertices, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth, InterruptT* interrupter)
{
using ValueT = typename GridType::ValueType;

static_assert(std::is_floating_point<ValueT>::value,
"createLevelSetThickenedMesh must return a scalar grid");

if (voxelSize <= 0) OPENVDB_THROW(ValueError, "voxel size must be positive");
if (halfWidth <= 0) OPENVDB_THROW(ValueError, "half-width must be positive");

const Index n = quads.size();
std::vector<Vec3I> triangles(2*n);

tbb::parallel_for(tbb::blocked_range<size_t>(0, n),
[&](const tbb::blocked_range<size_t>& r) {
for (size_t i = r.begin(); i != r.end(); ++i) {
const Vec4I& q = quads[i];
triangles[i] = Vec3I(q.x(), q.y(), q.z());
triangles[i + n] = Vec3I(q.x(), q.z(), q.w());
}
});

return createLevelSetThickenedMesh<GridType, InterruptT>(vertices, triangles, radius,
voxelSize, halfWidth, interrupter);
}

template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetThickenedMesh(const std::vector<Vec3s>& vertices,
const std::vector<Vec3I>& triangles, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth, InterruptT* interrupter)
{
using ValueT = typename GridType::ValueType;

static_assert(std::is_floating_point<ValueT>::value,
"createLevelSetThickenedMesh must return a scalar grid");

if (voxelSize <= 0) OPENVDB_THROW(ValueError, "voxel size must be positive");
if (halfWidth <= 0) OPENVDB_THROW(ValueError, "half-width must be positive");

if (quads.empty())
return createLevelSetThickenedMesh<GridType, InterruptT>(vertices, triangles, radius,
voxelSize, halfWidth, interrupter);

const Index tn = triangles.size(), qn = quads.size();
const Index qn2 = tn + qn;
std::vector<Vec3I> tris(tn + 2*qn);

tbb::parallel_for(tbb::blocked_range<size_t>(0, tn),
[&](const tbb::blocked_range<size_t>& r) {
for (size_t i = r.begin(); i != r.end(); ++i) {
tris[i] = triangles[i];
}
});

tbb::parallel_for(tbb::blocked_range<size_t>(0, qn),
[&](const tbb::blocked_range<size_t>& r) {
for (size_t i = r.begin(); i != r.end(); ++i) {
const Vec4I& q = quads[i];
tris[i + tn] = Vec3I(q.x(), q.y(), q.z());
tris[i + qn2] = Vec3I(q.x(), q.z(), q.w());
}
});

return createLevelSetThickenedMesh<GridType, InterruptT>(vertices, tris, radius,
voxelSize, halfWidth, interrupter);
}


////////////////////////////////////////

Expand All @@ -1522,6 +1630,19 @@ createLevelSetThickenedMesh(
OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
#undef _FUNCTION

#define _FUNCTION(TreeT) \
Grid<TreeT>::Ptr createLevelSetThickenedMesh<Grid<TreeT>>(const std::vector<Vec3s>&, \
const std::vector<Vec4I>&, float, float, float, util::NullInterrupter*)
OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
#undef _FUNCTION

#define _FUNCTION(TreeT) \
Grid<TreeT>::Ptr createLevelSetThickenedMesh<Grid<TreeT>>(const std::vector<Vec3s>&, \
const std::vector<Vec3I>&, const std::vector<Vec4I>&, float, float, float, \
util::NullInterrupter*)
OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION)
#undef _FUNCTION

#endif // OPENVDB_USE_EXPLICIT_INSTANTIATION

} // namespace tools
Expand Down
1 change: 0 additions & 1 deletion openvdb/openvdb/tools/LevelSetTubes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,6 @@ createLevelSetTubeComplex(const std::vector<Vec3s>& vertices, const std::vector<
TubeRadiiPolicy radii_policy, InterruptT* interrupter)
{
using GridPtr = typename GridType::Ptr;
using TreeT = typename GridType::TreeType;
using ValueT = typename GridType::ValueType;

using CapsuleComplexVoxelizer = typename lvlset::TubeComplexVoxelizer<GridType, InterruptT, true>;
Expand Down

0 comments on commit 10fecd4

Please sign in to comment.