openvdb icon indicating copy to clipboard operation
openvdb copied to clipboard

Tube and Thickened Mesh Level Set Constructors

Open ghurstunither opened this issue 1 year ago • 0 comments

Summary

This PR introduces level set constructors for

  • capsules
  • tapered capsules (different radius at the endpoints)
  • tube complex with constant or varying radius
  • thickened triangle, quad, or mixed mesh (thickens in all directions)

A base class ConvexVoxelizer, which provides the infrastructure for convex level set construction, is also introduced.

class tools::ConvexVoxelizer

tools/ConvexVoxelizer.h

This base class requires the derived class implement methods such as

A simple example that creates a level set sphere can be found in the doxygen here.

tools::createLevelSetCapsule

Implemented in tools/LevelSetTubes.h via class CapsuleVoxelizer:

template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius, float voxelSize,
    float halfWidth = float(LEVEL_SET_HALF_WIDTH),
    InterruptT* interrupter = nullptr, bool threaded = true);

and

template <typename GridType>
typename GridType::Ptr
createLevelSetCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius, float voxelSize,
    float halfWidth = float(LEVEL_SET_HALF_WIDTH), bool threaded = true);

Example:

const Vec3s p1(15.8f, 13.2f, 16.7f), p2(4.3f, 7.9f, -4.8f);
const float r1 = 4.3f, voxelSize = 0.1f;

FloatGrid::Ptr grid = tools::createLevelSetCapsule<FloatGrid>(p1, p2, r1, voxelSize);

yielding

Screenshot 2024-10-12 at 11 14 06 PM

tools::createLevelSetTaperedCapsule

Implemented in tools/LevelSetTubes.h via class TaperedCapsuleVoxelizer:

template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetTaperedCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius1, float radius2,
    float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
    InterruptT* interrupter = nullptr, bool threaded = true);

and

template <typename GridType>
typename GridType::Ptr
createLevelSetTaperedCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius1, float radius2,
    float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH), bool threaded = true);

Example:

const Vec3s p1(15.8f, 13.2f, 16.7f), p2(4.3f, 7.9f, -4.8f);
const float r1 = 4.3f, r2 = 1.2f, voxelSize = 0.1f;

FloatGrid::Ptr grid = tools::createLevelSetTaperedCapsule<FloatGrid>(p1, p2, r1, r2, voxelSize);

yielding

Screenshot 2024-10-12 at 11 16 30 PM

tools::createLevelSetTubeComplex

Implemented in tools/LevelSetTubes.h via class TubeComplexVoxelizer:

template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetTubeComplex(const std::vector<Vec3s>& vertices, const std::vector<Vec2I>& segments,
    float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
    InterruptT* interrupter = nullptr);

and

template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetTubeComplex(const std::vector<Vec3s>& vertices, const std::vector<Vec2I>& segments,
    const std::vector<float>& radii, float voxelSize,
    float halfWidth = float(LEVEL_SET_HALF_WIDTH), TubeRadiiPolicy radii_policy = TUBE_AUTOMATIC,
    InterruptT* interrupter = nullptr);

The different TubeRadiiPolicy are described here.

Example of constant radius:

const Vec3s p0(0.0f, 0.0f, 0.0f), p1(0.0f, 0.0f, 1.0f),
            p2(-0.471405f, -0.816497f, -0.333333f), p3(-0.471405f, 0.816497f, -0.333333f),
            p4(0.942809f, 0.0f, -0.333333f);
const float r = 0.2f, voxelSize = 0.0125f;

const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4});
const std::vector<Vec2I> segments({Vec2I(0, 1), Vec2I(0, 2), Vec2I(0, 3), Vec2I(0, 4)});

FloatGrid::Ptr grid = tools::createLevelSetTubeComplex<FloatGrid>(vertices, segments, radii, voxelSize);

yielding

Screenshot 2024-10-12 at 11 26 10 PM

Example of varying radius:

const Vec3s p0(0.0f, 0.0f, 0.0f), p1(0.0f, 0.0f, 1.0f),
            p2(-0.471405f, -0.816497f, -0.333333f), p3(-0.471405f, 0.816497f, -0.333333f),
            p4(0.942809f, 0.0f, -0.333333f);
const std::vector<float> radii({0.15f, 0.15f, 0.1f, 0.05f, 0.0f});
const float voxelSize = 0.0125f;

const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4});
const std::vector<Vec2I> segments({Vec2I(0, 1), Vec2I(0, 2), Vec2I(0, 3), Vec2I(0, 4)});

FloatGrid::Ptr grid = tools::createLevelSetTubeComplex<FloatGrid>(vertices, segments, r, voxelSize);

yielding

Screenshot 2024-10-12 at 11 32 50 PM

tools::createLevelSetThickenedMesh

Implemented in tools/LevelSetThickenedMesh.h via class TubeComplexVoxelizer:

template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(
    const std::vector<Vec3s>& vertices, const std::vector<Vec3I>& triangles,
    float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
    InterruptT* interrupter = nullptr);

and

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);

and

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);

Initialize mesh data:

const float r = 2.9f;
const Vec3s p0(15.8f, 13.2f, 16.7f),  p1(4.3f, 7.9f, -4.8f);
const Vec3s p2(-3.0f, -7.4f, 8.9f),   p3(-2.7f, 8.9f, 30.4f);
const Vec3s p4(23.0f, 17.4f, -10.9f), p5(5.2f, -5.7f, 29.0f);
const Vec3s p6(-14.6f, 3.7f, 10.9f),  p7(35.8f, 23.4f, 5.8f);

const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4, p5, p6, p7});
const std::vector<Vec3I> triangles1({Vec3I(0, 1, 2), Vec3I(0, 1, 3), Vec3I(0, 1, 4)});
const std::vector<Vec3I> triangles2({Vec3I(0, 1, 4)});
const std::vector<Vec4I> quads1({Vec4I(0, 1, 2, 5), Vec4I(0, 1, 6, 3), Vec4I(0, 1, 4, 7)});
const std::vector<Vec4I> quads2({Vec4I(0, 1, 2, 5), Vec4I(0, 1, 6, 3)});

Example of triangle mesh:

FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, triangles1, r, voxelSize);

yielding

Screenshot 2024-10-12 at 11 41 43 PM

Example of quad mesh:

FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, quads1, r, voxelSize);

yielding

Screenshot 2024-10-12 at 11 42 28 PM

Example of mixed mesh:

FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, triangles2, quads2, r, voxelSize);

yielding

Screenshot 2024-10-12 at 11 43 42 PM

ghurstunither avatar Oct 13 '24 03:10 ghurstunither