OpenVDB  4.0.2
SignedFloodFill.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2017 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_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED
40 #define OPENVDB_TOOLS_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED
41 
42 #include <openvdb/math/Math.h> // for math::negative
43 #include <openvdb/Types.h> // for Index typedef
45 #include <type_traits>
46 
47 
48 namespace openvdb {
50 namespace OPENVDB_VERSION_NAME {
51 namespace tools {
52 
68 template<typename TreeOrLeafManagerT>
69 inline void
70 signedFloodFill(TreeOrLeafManagerT& tree, bool threaded = true,
71  size_t grainSize = 1, Index minLevel = 0);
72 
73 
92 template<typename TreeOrLeafManagerT>
93 inline void
95  TreeOrLeafManagerT& tree,
96  const typename TreeOrLeafManagerT::ValueType& outsideWidth,
97  const typename TreeOrLeafManagerT::ValueType& insideWidth,
98  bool threaded = true,
99  size_t grainSize = 1,
100  Index minLevel = 0);
101 
102 
104 
105 
106 template<typename TreeOrLeafManagerT>
108 {
109 public:
110  using ValueT = typename TreeOrLeafManagerT::ValueType;
111  using RootT = typename TreeOrLeafManagerT::RootNodeType;
112  using LeafT = typename TreeOrLeafManagerT::LeafNodeType;
113  static_assert(std::is_signed<ValueT>::value,
114  "signed flood fill is supported only for signed value grids");
115 
116  SignedFloodFillOp(const TreeOrLeafManagerT& tree, Index minLevel = 0)
117  : mOutside(ValueT(math::Abs(tree.background())))
118  , mInside(ValueT(math::negative(mOutside)))
119  , mMinLevel(minLevel)
120  {
121  }
122 
123  SignedFloodFillOp(ValueT outsideValue, ValueT insideValue, Index minLevel = 0)
124  : mOutside(ValueT(math::Abs(outsideValue)))
125  , mInside(ValueT(math::negative(math::Abs(insideValue))))
126  , mMinLevel(minLevel)
127  {
128  }
129 
130  // Nothing to do at the leaf node level
131  void operator()(LeafT& leaf) const
132  {
133  if (LeafT::LEVEL < mMinLevel) return;
134 
135 #ifndef OPENVDB_2_ABI_COMPATIBLE
136  if (!leaf.allocate()) return;//this assures that the buffer is allocated and in-memory
137 #endif
138  const typename LeafT::NodeMaskType& valueMask = leaf.getValueMask();
139  // WARNING: "Never do what you're about to see at home, we're what you call experts!"
140  typename LeafT::ValueType* buffer =
141  const_cast<typename LeafT::ValueType*>(&(leaf.getFirstValue()));
142 
143  const Index first = valueMask.findFirstOn();
144  if (first < LeafT::SIZE) {
145  bool xInside = buffer[first]<0, yInside = xInside, zInside = xInside;
146  for (Index x = 0; x != (1 << LeafT::LOG2DIM); ++x) {
147  const Index x00 = x << (2 * LeafT::LOG2DIM);
148  if (valueMask.isOn(x00)) xInside = buffer[x00] < 0; // element(x, 0, 0)
149  yInside = xInside;
150  for (Index y = 0; y != (1 << LeafT::LOG2DIM); ++y) {
151  const Index xy0 = x00 + (y << LeafT::LOG2DIM);
152  if (valueMask.isOn(xy0)) yInside = buffer[xy0] < 0; // element(x, y, 0)
153  zInside = yInside;
154  for (Index z = 0; z != (1 << LeafT::LOG2DIM); ++z) {
155  const Index xyz = xy0 + z; // element(x, y, z)
156  if (valueMask.isOn(xyz)) {
157  zInside = buffer[xyz] < 0;
158  } else {
159  buffer[xyz] = zInside ? mInside : mOutside;
160  }
161  }
162  }
163  }
164  } else {// if no active voxels exist simply use the sign of the first value
165  leaf.fill(buffer[0] < 0 ? mInside : mOutside);
166  }
167  }
168 
169  // Prune the child nodes of the internal nodes
170  template<typename NodeT>
171  void operator()(NodeT& node) const
172  {
173  if (NodeT::LEVEL < mMinLevel) return;
174  // We assume the child nodes have already been flood filled!
175  const typename NodeT::NodeMaskType& childMask = node.getChildMask();
176  // WARNING: "Never do what you're about to see at home, we're what you call experts!"
177  typename NodeT::UnionType* table = const_cast<typename NodeT::UnionType*>(node.getTable());
178 
179  const Index first = childMask.findFirstOn();
180  if (first < NodeT::NUM_VALUES) {
181  bool xInside = table[first].getChild()->getFirstValue()<0;
182  bool yInside = xInside, zInside = xInside;
183  for (Index x = 0; x != (1 << NodeT::LOG2DIM); ++x) {
184  const int x00 = x << (2 * NodeT::LOG2DIM); // offset for block(x, 0, 0)
185  if (childMask.isOn(x00)) xInside = table[x00].getChild()->getLastValue()<0;
186  yInside = xInside;
187  for (Index y = 0; y != (1 << NodeT::LOG2DIM); ++y) {
188  const Index xy0 = x00 + (y << NodeT::LOG2DIM); // offset for block(x, y, 0)
189  if (childMask.isOn(xy0)) yInside = table[xy0].getChild()->getLastValue()<0;
190  zInside = yInside;
191  for (Index z = 0; z != (1 << NodeT::LOG2DIM); ++z) {
192  const Index xyz = xy0 + z; // offset for block(x, y, z)
193  if (childMask.isOn(xyz)) {
194  zInside = table[xyz].getChild()->getLastValue()<0;
195  } else {
196  table[xyz].setValue(zInside ? mInside : mOutside);
197  }
198  }
199  }
200  }
201  } else {//no child nodes exist simply use the sign of the first tile value.
202  const ValueT v = table[0].getValue()<0 ? mInside : mOutside;
203  for (Index i = 0; i < NodeT::NUM_VALUES; ++i) table[i].setValue(v);
204  }
205  }
206 
207  // Prune the child nodes of the root node
208  void operator()(RootT& root) const
209  {
210  if (RootT::LEVEL < mMinLevel) return;
211  using ChildT = typename RootT::ChildNodeType;
212  // Insert the child nodes into a map sorted according to their origin
213  std::map<Coord, ChildT*> nodeKeys;
214  typename RootT::ChildOnIter it = root.beginChildOn();
215  for (; it; ++it) nodeKeys.insert(std::pair<Coord, ChildT*>(it.getCoord(), &(*it)));
216  static const Index DIM = RootT::ChildNodeType::DIM;
217 
218  // We employ a simple z-scanline algorithm that inserts inactive tiles with
219  // the inside value if they are sandwiched between inside child nodes only!
220  typename std::map<Coord, ChildT*>::const_iterator b = nodeKeys.begin(), e = nodeKeys.end();
221  if ( b == e ) return;
222  for (typename std::map<Coord, ChildT*>::const_iterator a = b++; b != e; ++a, ++b) {
223  Coord d = b->first - a->first; // delta of neighboring coordinates
224  if (d[0]!=0 || d[1]!=0 || d[2]==Int32(DIM)) continue;// not same z-scanline or neighbors
225  const ValueT fill[] = { a->second->getLastValue(), b->second->getFirstValue() };
226  if (!(fill[0] < 0) || !(fill[1] < 0)) continue; // scanline isn't inside
227  Coord c = a->first + Coord(0u, 0u, DIM);
228  for (; c[2] != b->first[2]; c[2] += DIM) root.addTile(c, mInside, false);
229  }
230  root.setBackground(mOutside, /*updateChildNodes=*/false);
231  }
232 
233 private:
234  const ValueT mOutside, mInside;
235  const Index mMinLevel;
236 };// SignedFloodFillOp
237 
238 
239 //{
241 
242 template<typename TreeOrLeafManagerT>
243 inline
244 typename std::enable_if<std::is_signed<typename TreeOrLeafManagerT::ValueType>::value, void>::type
245 doSignedFloodFill(TreeOrLeafManagerT& tree,
246  typename TreeOrLeafManagerT::ValueType outsideValue,
247  typename TreeOrLeafManagerT::ValueType insideValue,
248  bool threaded,
249  size_t grainSize,
250  Index minLevel)
251 {
253  SignedFloodFillOp<TreeOrLeafManagerT> op(outsideValue, insideValue, minLevel);
254  nodes.foreachBottomUp(op, threaded, grainSize);
255 }
256 
257 // Dummy (no-op) implementation for unsigned types
258 template <typename TreeOrLeafManagerT>
259 inline
260 typename std::enable_if<!std::is_signed<typename TreeOrLeafManagerT::ValueType>::value, void>::type
261 doSignedFloodFill(TreeOrLeafManagerT&,
262  const typename TreeOrLeafManagerT::ValueType&,
263  const typename TreeOrLeafManagerT::ValueType&,
264  bool,
265  size_t,
266  Index)
267 {
269  "signedFloodFill is supported only for signed value grids");
270 }
271 
273 //}
274 
275 
276 // If the narrow-band is symmetric and unchanged
277 template <typename TreeOrLeafManagerT>
278 inline void
280  TreeOrLeafManagerT& tree,
281  const typename TreeOrLeafManagerT::ValueType& outsideValue,
282  const typename TreeOrLeafManagerT::ValueType& insideValue,
283  bool threaded,
284  size_t grainSize,
285  Index minLevel)
286 {
287  doSignedFloodFill(tree, outsideValue, insideValue, threaded, grainSize, minLevel);
288 }
289 
290 
291 template <typename TreeOrLeafManagerT>
292 inline void
293 signedFloodFill(TreeOrLeafManagerT& tree,
294  bool threaded,
295  size_t grainSize,
296  Index minLevel)
297 {
298  const typename TreeOrLeafManagerT::ValueType v = tree.root().background();
299  doSignedFloodFill(tree, v, math::negative(v), threaded, grainSize, minLevel);
300 }
301 
302 } // namespace tools
303 } // namespace OPENVDB_VERSION_NAME
304 } // namespace openvdb
305 
306 #endif // OPENVDB_TOOLS_RESETBACKGROUND_HAS_BEEN_INCLUDED
307 
308 // Copyright (c) 2012-2017 DreamWorks Animation LLC
309 // All rights reserved. This software is distributed under the
310 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
void signedFloodFillWithValues(TreeOrLeafManagerT &tree, const typename TreeOrLeafManagerT::ValueType &outsideWidth, const typename TreeOrLeafManagerT::ValueType &insideWidth, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:279
void operator()(LeafT &leaf) const
Definition: SignedFloodFill.h:131
typename TreeOrLeafManagerT::LeafNodeType LeafT
Definition: SignedFloodFill.h:112
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:293
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
void operator()(RootT &root) const
Definition: SignedFloodFill.h:208
typename TreeOrLeafManagerT::ValueType ValueT
Definition: SignedFloodFill.h:110
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays, one for each level of the tree.
Definition: NodeManager.h:57
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
Index32 Index
Definition: Types.h:57
SignedFloodFillOp(const TreeOrLeafManagerT &tree, Index minLevel=0)
Definition: SignedFloodFill.h:116
#define OPENVDB_VERSION_NAME
Definition: version.h:43
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:108
Coord Abs(const Coord &xyz)
Definition: Coord.h:509
Definition: Exceptions.h:39
SignedFloodFillOp(ValueT outsideValue, ValueT insideValue, Index minLevel=0)
Definition: SignedFloodFill.h:123
void operator()(NodeT &node) const
Definition: SignedFloodFill.h:171
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
int32_t Int32
Definition: Types.h:59
Definition: Exceptions.h:91
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
typename TreeOrLeafManagerT::RootNodeType RootT
Definition: SignedFloodFill.h:111
Definition: SignedFloodFill.h:107