diff --git a/openvdb/openvdb/tools/LevelSetThickenedMesh.h b/openvdb/openvdb/tools/LevelSetThickenedMesh.h index a41c006341..1cef9d264b 100644 --- a/openvdb/openvdb/tools/LevelSetThickenedMesh.h +++ b/openvdb/openvdb/tools/LevelSetThickenedMesh.h @@ -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. @@ -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::Ptr +createLevelSetThickenedMesh( + const std::vector& vertices, const std::vector& 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::Ptr +createLevelSetThickenedMesh(const std::vector& vertices, + const std::vector& triangles, const std::vector& 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 @@ -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; @@ -1504,6 +1540,78 @@ createLevelSetThickenedMesh( return grid; } +template +typename GridType::Ptr +createLevelSetThickenedMesh( + const std::vector& vertices, const std::vector& quads, + float radius, float voxelSize, float halfWidth, InterruptT* interrupter) +{ + using ValueT = typename GridType::ValueType; + + static_assert(std::is_floating_point::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 triangles(2*n); + + tbb::parallel_for(tbb::blocked_range(0, n), + [&](const tbb::blocked_range& 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(vertices, triangles, radius, + voxelSize, halfWidth, interrupter); +} + +template +typename GridType::Ptr +createLevelSetThickenedMesh(const std::vector& vertices, + const std::vector& triangles, const std::vector& quads, + float radius, float voxelSize, float halfWidth, InterruptT* interrupter) +{ + using ValueT = typename GridType::ValueType; + + static_assert(std::is_floating_point::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(vertices, triangles, radius, + voxelSize, halfWidth, interrupter); + + const Index tn = triangles.size(), qn = quads.size(); + const Index qn2 = tn + qn; + std::vector tris(tn + 2*qn); + + tbb::parallel_for(tbb::blocked_range(0, tn), + [&](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + tris[i] = triangles[i]; + } + }); + + tbb::parallel_for(tbb::blocked_range(0, qn), + [&](const tbb::blocked_range& 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(vertices, tris, radius, + voxelSize, halfWidth, interrupter); +} + //////////////////////////////////////// @@ -1522,6 +1630,19 @@ createLevelSetThickenedMesh( OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) #undef _FUNCTION +#define _FUNCTION(TreeT) \ + Grid::Ptr createLevelSetThickenedMesh>(const std::vector&, \ + const std::vector&, float, float, float, util::NullInterrupter*) +OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) +#undef _FUNCTION + +#define _FUNCTION(TreeT) \ + Grid::Ptr createLevelSetThickenedMesh>(const std::vector&, \ + const std::vector&, const std::vector&, float, float, float, \ + util::NullInterrupter*) +OPENVDB_REAL_TREE_INSTANTIATE(_FUNCTION) +#undef _FUNCTION + #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION } // namespace tools diff --git a/openvdb/openvdb/tools/LevelSetTubes.h b/openvdb/openvdb/tools/LevelSetTubes.h index f2fe73cd12..af799b8d48 100644 --- a/openvdb/openvdb/tools/LevelSetTubes.h +++ b/openvdb/openvdb/tools/LevelSetTubes.h @@ -1381,7 +1381,6 @@ createLevelSetTubeComplex(const std::vector& 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;