1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /// @file Mask.h
5 ///
6 /// @brief Construct boolean mask grids from grids of arbitrary type
7 
8 #ifndef OPENVDB_TOOLS_MASK_HAS_BEEN_INCLUDED
9 #define OPENVDB_TOOLS_MASK_HAS_BEEN_INCLUDED
10 
11 #include <openvdb/Grid.h>
12 #include <openvdb/openvdb.h>
13 #include "LevelSetUtil.h" // for tools::sdfInteriorMask()
14 #include <type_traits> // for std::enable_if, std::is_floating_point
15 
16 
17 namespace openvdb {
18 OPENVDB_USE_VERSION_NAMESPACE
19 namespace OPENVDB_VERSION_NAME {
20 namespace tools {
21 
22 /// @brief Given an input grid of any type, return a new, boolean grid
23 /// whose active voxel topology matches the input grid's or,
24 /// if the input grid is a level set, matches the input grid's interior.
25 /// @param grid      the grid from which to construct a mask
26 /// @param isovalue  for a level set grid, the isovalue that defines the grid's interior
27 /// @sa tools::sdfInteriorMask()
28 template<typename GridType>
29 typename GridType::template ValueConverter<bool>::Type::Ptr
30 interiorMask(const GridType& grid, const double isovalue = 0.0);
31 
32 
33 ////////////////////////////////////////
34 
35 /// @cond OPENVDB_DOCS_INTERNAL
36 
37 namespace mask_internal {
38 template<typename GridType>
39 struct Traits {
40     static const bool isBool = std::is_same<typename GridType::ValueType, bool>::value;
41     using BoolGridType = typename GridType::template ValueConverter<bool>::Type;
42     using BoolGridPtrType = typename BoolGridType::Ptr;
43 };
44 
45 template<typename GridType>
46 inline typename std::enable_if<std::is_floating_point<typename GridType::ValueType>::value,
47     typename mask_internal::Traits<GridType>::BoolGridPtrType>::type
doLevelSetInteriorMask(const GridType & grid,const double isovalue)48 doLevelSetInteriorMask(const GridType& grid, const double isovalue)
49 {
50     using GridValueT = typename GridType::ValueType;
51     using MaskGridPtrT = typename mask_internal::Traits<GridType>::BoolGridPtrType;
52 
53     // If the input grid is a level set (and floating-point), return a mask of its interior.
54     if (grid.getGridClass() == GRID_LEVEL_SET) {
55         return tools::sdfInteriorMask(grid, static_cast<GridValueT>(isovalue));
56     }
57     return MaskGridPtrT{};
58 }
59 
60 // No-op specialization for non-floating-point grids
61 template<typename GridType>
62 inline typename std::enable_if<!std::is_floating_point<typename GridType::ValueType>::value,
63     typename mask_internal::Traits<GridType>::BoolGridPtrType>::type
doLevelSetInteriorMask(const GridType &,const double)64 doLevelSetInteriorMask(const GridType&, const double /*isovalue*/)
65 {
66     using MaskGridPtrT = typename mask_internal::Traits<GridType>::BoolGridPtrType;
67     return MaskGridPtrT{};
68 }
69 
70 template<typename GridType>
71 inline typename std::enable_if<mask_internal::Traits<GridType>::isBool,
72     typename mask_internal::Traits<GridType>::BoolGridPtrType>::type
doInteriorMask(const GridType & grid,const double)73 doInteriorMask(const GridType& grid, const double /*isovalue*/)
74 {
75     // If the input grid is already boolean, return a copy of it.
76     return grid.deepCopy();
77 }
78 
79 template<typename GridType>
80 inline typename std::enable_if<!(mask_internal::Traits<GridType>::isBool),
81     typename mask_internal::Traits<GridType>::BoolGridPtrType>::type
doInteriorMask(const GridType & grid,const double isovalue)82 doInteriorMask(const GridType& grid, const double isovalue)
83 {
84     using MaskGridT = typename mask_internal::Traits<GridType>::BoolGridType;
85 
86     // If the input grid is a level set, return a mask of its interior.
87     if (auto maskGridPtr = doLevelSetInteriorMask(grid, isovalue)) {
88         return maskGridPtr;
89     }
90 
91     // For any other grid type, return a mask of its active voxels.
92     auto maskGridPtr = MaskGridT::create(/*background=*/false);
93     maskGridPtr->setTransform(grid.transform().copy());
94     maskGridPtr->topologyUnion(grid);
95     return maskGridPtr;
96 }
97 
98 } // namespace mask_internal
99 
100 /// @endcond
101 
102 
103 template<typename GridType>
104 typename GridType::template ValueConverter<bool>::Type::Ptr
interiorMask(const GridType & grid,const double isovalue)105 interiorMask(const GridType& grid, const double isovalue)
106 {
107     return mask_internal::doInteriorMask(grid, isovalue);
108 }
109 
110 
111 ////////////////////////////////////////
112 
113 
114 // Explicit Template Instantiation
115 
116 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
117 
118 #ifdef OPENVDB_INSTANTIATE_MASK
119 #include <openvdb/util/ExplicitInstantiation.h>
120 #endif
121 
122 #define _FUNCTION(TreeT) \
123     Grid<TreeT>::ValueConverter<bool>::Type::Ptr interiorMask(const Grid<TreeT>&, const double)
124 OPENVDB_VOLUME_TREE_INSTANTIATE(_FUNCTION)
125 #undef _FUNCTION
126 
127 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
128 
129 
130 } // namespace tools
131 } // namespace OPENVDB_VERSION_NAME
132 } // namespace openvdb
133 
134 #endif // OPENVDB_TOOLS_MASK_HAS_BEEN_INCLUDED
135