OpenVDB: TopologyToLevelSet.h Source File

OpenVDB 3.2.0

TopologyToLevelSet.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
38
39 #ifndef OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
40 #define OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
41
42 #include "LevelSetFilter.h"
43 #include "Morphology.h" // for erodeVoxels and dilateActiveValues
44 #include "SignedFloodFill.h"
45
46 #include <openvdb/Grid.h>
47 #include <openvdb/Types.h>
48 #include <openvdb/math/FiniteDifference.h> // for math::BiasedGradientScheme
49 #include <openvdb/util/NullInterrupter.h>
50
51 #include <tbb/task_group.h>
52
53
54 namespace openvdb {
55 OPENVDB_USE_VERSION_NAMESPACE
56 namespace OPENVDB_VERSION_NAME {
57 namespace tools {
58
59
72 template<typename GridT>
73 inline typename GridT::template ValueConverter<float>::Type::Ptr
74 topologyToLevelSet(const GridT& grid, int halfWidth = 3, int closingSteps = 1, int dilation = 0,
75 int smoothingSteps = 0);
76
77
91 template<typename GridT, typename InterrupterT>
92 inline typename GridT::template ValueConverter<float>::Type::Ptr
93 topologyToLevelSet(const GridT& grid, int halfWidth = 3, int closingSteps = 1, int dilation = 0,
94 int smoothingSteps = 0, InterrupterT* interrupt = NULL);
95
96
98
99
100 namespace ttls_internal {
101
102
103 template<typename TreeT>
104 struct DilateOp
105 {
106 DilateOp(TreeT& t, int n) : tree(&t), size(n) {}
107 void operator()() const {
108 dilateActiveValues( *tree, size, tools::NN_FACE, tools::IGNORE_TILES);
109 }
110 TreeT* tree;
111 const int size;
112 };
113
114
115 template<typename TreeT>
116 struct ErodeOp
117 {
118 ErodeOp(TreeT& t, int n) : tree(&t), size(n) {}
119 void operator()() const { erodeVoxels( *tree, size); }
120 TreeT* tree;
121 const int size;
122 };
123
124
125 template<typename TreeType>
126 struct OffsetAndMinComp
127 {
128 typedef typename TreeType::LeafNodeType LeafNodeType;
129 typedef typename TreeType::ValueType ValueType;
130
131 OffsetAndMinComp(std::vector<LeafNodeType*>& lhsNodes, const TreeType& rhsTree, ValueType offset)
132 : mLhsNodes(lhsNodes.empty() ? NULL : &lhsNodes[0]), mRhsTree(&rhsTree), mOffset(offset)
133 {
134 }
135
136 void operator()(const tbb::blocked_range<size_t>& range) const
137 {
138 typedef typename LeafNodeType::ValueOnIter Iterator;
139
140 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
141 const ValueType offset = mOffset;
142
143 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
144
145 LeafNodeType& lhsNode = *mLhsNodes[n];
146 const LeafNodeType * rhsNodePt = rhsAcc.probeConstLeaf(lhsNode.origin());
147 if (!rhsNodePt) continue;
148
149 for (Iterator it = lhsNode.beginValueOn(); it; ++it) {
150 ValueType& val = const_cast<ValueType&>(it.getValue());
151 val = std::min(val, offset + rhsNodePt->getValue(it.pos()));
152 }
153 }
154 }
155
156 private:
157 LeafNodeType * * const mLhsNodes;
158 TreeType const * const mRhsTree;
159 ValueType const mOffset;
160 }; // struct OffsetAndMinComp
161
162
163 template<typename GridType, typename InterrupterType>
164 inline void
165 normalizeLevelSet(GridType& grid, const int halfWidthInVoxels, InterrupterType* interrupt = NULL)
166 {
167 LevelSetFilter<GridType, GridType, InterrupterType> filter(grid, interrupt);
168 filter.setSpatialScheme(math::FIRST_BIAS);
169 filter.setNormCount(halfWidthInVoxels);
170 filter.normalize();
171 filter.prune();
172 }
173
174
175 template<typename GridType, typename InterrupterType>
176 inline void
177 smoothLevelSet(GridType& grid, int iterations, int halfBandWidthInVoxels, InterrupterType* interrupt = NULL)
178 {
179 typedef typename GridType::ValueType ValueType;
180 typedef typename GridType::TreeType TreeType;
181 typedef typename TreeType::LeafNodeType LeafNodeType;
182
183 GridType filterGrid(grid);
184
185 LevelSetFilter<GridType, GridType, InterrupterType> filter(filterGrid, interrupt);
186 filter.setSpatialScheme(math::FIRST_BIAS);
187
188 for (int n = 0; n < iterations; ++n) {
189 if (interrupt && interrupt->wasInterrupted()) break;
190 filter.mean(1);
191 }
192
193 std::vector<LeafNodeType*> nodes;
194 grid.tree().getNodes(nodes);
195
196 const ValueType offset = ValueType(double(0.5) * grid.transform().voxelSize()[0]);
197
198 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
199 OffsetAndMinComp<TreeType>(nodes, filterGrid.tree(), -offset));
200
201 // Clean up any damanage that was done by the min operation
202 normalizeLevelSet(grid, halfBandWidthInVoxels, interrupt);
203 }
204
205
206 } // namespace ttls_internal
207
208
209
210 template<typename GridT, typename InterrupterT>
211 inline typename GridT::template ValueConverter<float>::Type::Ptr
212 topologyToLevelSet(const GridT& grid, int halfWidth, int closingSteps, int dilation,
213 int smoothingSteps, InterrupterT* interrupt)
214 {
215 typedef typename GridT::TreeType::template ValueConverter<ValueMask>::Type MaskTreeT;
216 typedef typename GridT::TreeType::template ValueConverter<float>::Type FloatTreeT;
217 typedef Grid<FloatTreeT> FloatGridT;
218
219 // Check inputs
220
221 halfWidth = std::max(halfWidth, 1);
222 closingSteps = std::max(closingSteps, 0);
223 dilation = std::max(dilation, 0);
224
225 if ( !grid.hasUniformVoxels() ) {
226 OPENVDB_THROW(ValueError, "Non-uniform voxels are not supported!");
227 }
228
229 // Copy the topology into a MaskGrid.
230 MaskTreeT maskTree( grid.tree(), false/*background*/, openvdb::TopologyCopy() );
231
232 // Morphological closing operation.
233 dilateActiveValues( maskTree, closingSteps + dilation, tools::NN_FACE, tools::IGNORE_TILES );
234 erodeVoxels( maskTree, closingSteps );
235
236 // Generate a volume with an implicit zero crossing at the boundary
237 // between active and inactive values in the input grid.
238 const float background = float(grid.voxelSize()[0]) * float(halfWidth);
239 typename FloatTreeT::Ptr lsTree(
240 new FloatTreeT( maskTree, /*out=*/background, /*in=*/-background, openvdb::TopologyCopy() ) );
241
242 tbb::task_group pool;
243 pool.run( ttls_internal::ErodeOp< MaskTreeT >( maskTree, halfWidth ) );
244 pool.run( ttls_internal::DilateOp<FloatTreeT>( *lsTree , halfWidth ) );
245 pool.wait();// wait for both tasks to complete
246
247 lsTree->topologyDifference( maskTree );
248 tools::pruneLevelSet( *lsTree, /*threading=*/true);
249
250 // Create a level set grid from the tree
251 typename FloatGridT::Ptr lsGrid = FloatGridT::create( lsTree );
252 lsGrid->setTransform( grid.transform().copy() );
253 lsGrid->setGridClass( openvdb::GRID_LEVEL_SET );
254
255 // Use a PDE based scheme to propagate distance values from the
256 // implicit zero crossing.
257 ttls_internal::normalizeLevelSet(*lsGrid, 3*halfWidth, interrupt);
258
259 // Additional filtering
260 if (smoothingSteps > 0) {
261 ttls_internal::smoothLevelSet(*lsGrid, smoothingSteps, halfWidth, interrupt);
262 }
263
264 return lsGrid;
265 }
266
267
268 template<typename GridT>
269 inline typename GridT::template ValueConverter<float>::Type::Ptr
270 topologyToLevelSet(const GridT& grid, int halfWidth, int closingSteps, int dilation, int smoothingSteps)
271 {
272 util::NullInterrupter interrupt;
273 return topologyToLevelSet(grid, halfWidth, closingSteps, dilation, smoothingSteps, &interrupt);
274 }
275
276
277 } // namespace tools
278 } // namespace OPENVDB_VERSION_NAME
279 } // namespace openvdb
280
281 #endif // OPENVDB_TOOLS_TOPOLOGY_TO_LEVELSET_HAS_BEEN_INCLUDED
282
283
284 // Copyright (c) 2012-2016 DreamWorks Animation LLC
285 // All rights reserved. This software is distributed under the
286 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v3_2_0::tools::NN_FACE
Definition: Morphology.h:87
FiniteDifference.h
openvdb::v3_2_0::tools::ttls_internal::DilateOp
Definition: TopologyToLevelSet.h:104
openvdb::v3_2_0::tools::ttls_internal::smoothLevelSet
void smoothLevelSet(GridType &grid, int iterations, int halfBandWidthInVoxels, InterrupterType *interrupt=NULL)
Definition: TopologyToLevelSet.h:177
openvdb::v3_2_0::tools::ttls_internal::ErodeOp::ErodeOp
ErodeOp(TreeT &t, int n)
Definition: TopologyToLevelSet.h:118
Types.h
openvdb::v3_2_0::tools::LevelSetTracker::setSpatialScheme
void setSpatialScheme(math::BiasedGradientScheme scheme)
Set the spatial finite difference scheme.
Definition: LevelSetTracker.h:151
NullInterrupter.h
openvdb::v3_2_0::tools::ttls_internal::OffsetAndMinComp::OffsetAndMinComp
OffsetAndMinComp(std::vector< LeafNodeType *> &lhsNodes, const TreeType &rhsTree, ValueType offset)
Definition: TopologyToLevelSet.h:131
openvdb::v3_2_0::tools::ttls_internal::DilateOp::operator()
void operator()() const
Definition: TopologyToLevelSet.h:107
openvdb::v3_2_0::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v3_2_0::tools::erodeVoxels
OPENVDB_STATIC_SPECIALIZATION void erodeVoxels(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically erode all leaf-level active voxels in the given tree.
Definition: Morphology.h:872
openvdb::v3_2_0::tools::ttls_internal::ErodeOp::operator()
void operator()() const
Definition: TopologyToLevelSet.h:119
openvdb::v3_2_0::TopologyCopy
Definition: Types.h:442
openvdb::v3_2_0::tools::topologyToLevelSet
GridT::template ValueConverter< float >::Type::Ptr topologyToLevelSet(const GridT &grid, int halfWidth=3, int closingSteps=1, int dilation=0, int smoothingSteps=0, InterrupterT *interrupt=NULL)
Compute the narrow-band signed distance to the interface between active and inactive voxels in the in...
Definition: TopologyToLevelSet.h:212
openvdb::v3_2_0::tools::ttls_internal::normalizeLevelSet
void normalizeLevelSet(GridType &grid, const int halfWidthInVoxels, InterrupterType *interrupt=NULL)
Definition: TopologyToLevelSet.h:165
openvdb::v3_2_0::tools::ttls_internal::OffsetAndMinComp
Definition: TopologyToLevelSet.h:126
openvdb::v3_2_0::tools::ttls_internal::ErodeOp::tree
TreeT * tree
Definition: TopologyToLevelSet.h:120
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
openvdb::v3_2_0::math::FIRST_BIAS
Definition: FiniteDifference.h:194
openvdb::v3_2_0::tools::ttls_internal::OffsetAndMinComp::operator()
void operator()(const tbb::blocked_range< size_t > &range) const
Definition: TopologyToLevelSet.h:136
openvdb::v3_2_0::tools::ttls_internal::ErodeOp::size
const int size
Definition: TopologyToLevelSet.h:121
openvdb::v3_2_0::tools::composite::max
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
openvdb::v3_2_0::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:429
openvdb::v3_2_0::tree::ValueAccessor< const TreeType >
openvdb::v3_2_0::tools::ttls_internal::OffsetAndMinComp::ValueType
TreeType::ValueType ValueType
Definition: TopologyToLevelSet.h:129
LevelSetFilter.h
Performs various types of level set deformations with interface tracking. These unrestricted deformat...
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::tools::LevelSetTracker::setNormCount
void setNormCount(int n)
Set the number of normalizations performed per track or normalize call.
Definition: LevelSetTracker.h:165
SignedFloodFill.h
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v3_2_0::tools::ttls_internal::ErodeOp
Definition: TopologyToLevelSet.h:116
openvdb::v3_2_0::tools::ttls_internal::OffsetAndMinComp::LeafNodeType
TreeType::LeafNodeType LeafNodeType
Definition: TopologyToLevelSet.h:128
Morphology.h
Implementation of morphological dilation and erosion.
openvdb::v3_2_0::tools::LevelSetFilter
Filtering (e.g. diffusion) of narrow-band level sets. An optional scalar field can be used to produce...
Definition: LevelSetFilter.h:64
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::tools::ttls_internal::DilateOp::DilateOp
DilateOp(TreeT &t, int n)
Definition: TopologyToLevelSet.h:106
openvdb::v3_2_0::tools::ttls_internal::DilateOp::tree
TreeT * tree
Definition: TopologyToLevelSet.h:110
openvdb::v3_2_0::tools::dilateActiveValues
OPENVDB_STATIC_SPECIALIZATION void dilateActiveValues(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE, TilePolicy mode=PRESERVE_TILES)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1071
openvdb::v3_2_0::tools::LevelSetTracker::normalize
void normalize(const MaskType *mask)
Iterative normalization, i.e. solving the Eikonal equation.
Grid.h
openvdb::v3_2_0::ValueError
Definition: Exceptions.h:88
openvdb::v3_2_0::tools::LevelSetFilter::mean
void mean(int width=1, const MaskType *mask=NULL)
One iteration of mean-value flow of the level set.
Definition: LevelSetFilter.h:164
openvdb::v3_2_0::GRID_LEVEL_SET
Definition: Types.h:213
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tools::ttls_internal::DilateOp::size
const int size
Definition: TopologyToLevelSet.h:111
openvdb::v3_2_0::tree::ValueAccessor::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:429
openvdb::v3_2_0::tools::IGNORE_TILES
Definition: Morphology.h:102
openvdb::v3_2_0::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
openvdb::v3_2_0::tools::LevelSetTracker::prune
void prune()
Remove voxels that are outside the narrow band. (substep of track)
Definition: LevelSetTracker.h:276
openvdb::v3_2_0::tools::composite::min
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128