11 #ifndef OPENVDB_TOOLS_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED
12 #define OPENVDB_TOOLS_SIGNEDFLOODFILL_HAS_BEEN_INCLUDED
20 #include <type_traits>
43 template<
typename TreeOrLeafManagerT>
46 size_t grainSize = 1, Index minLevel = 0);
67 template<
typename TreeOrLeafManagerT>
70 TreeOrLeafManagerT& tree,
81 template<
typename TreeOrLeafManagerT>
86 using RootT =
typename TreeOrLeafManagerT::RootNodeType;
87 using LeafT =
typename TreeOrLeafManagerT::LeafNodeType;
89 "signed flood fill is supported only for signed value grids");
92 : mOutside(
ValueT(math::
Abs(tree.background())))
99 : mOutside(
ValueT(math::
Abs(outsideValue)))
101 , mMinLevel(minLevel)
108 if (LeafT::LEVEL < mMinLevel)
return;
110 if (!leaf.allocate())
return;
112 const typename LeafT::NodeMaskType& valueMask = leaf.getValueMask();
119 bool xInside = buffer[
first]<0, yInside = xInside, zInside = xInside;
120 for (
Index x = 0;
x != (1 << LeafT::LOG2DIM); ++
x) {
121 const Index x00 =
x << (2 * LeafT::LOG2DIM);
122 if (valueMask.isOn(x00)) xInside = buffer[x00] < 0;
124 for (
Index y = 0;
y != (1 << LeafT::LOG2DIM); ++
y) {
125 const Index xy0 = x00 + (
y << LeafT::LOG2DIM);
126 if (valueMask.isOn(xy0)) yInside = buffer[xy0] < 0;
128 for (
Index z = 0;
z != (1 << LeafT::LOG2DIM); ++
z) {
129 const Index xyz = xy0 +
z;
130 if (valueMask.isOn(xyz)) {
131 zInside = buffer[xyz] < 0;
133 buffer[xyz] = zInside ? mInside : mOutside;
139 leaf.fill(buffer[0] < 0 ? mInside : mOutside);
144 template<
typename NodeT>
147 if (NodeT::LEVEL < mMinLevel)
return;
149 const typename NodeT::NodeMaskType& childMask = node.getChildMask();
151 typename NodeT::UnionType*
table =
const_cast<typename NodeT::UnionType*
>(node.getTable());
154 if (first < NodeT::NUM_VALUES) {
155 bool xInside = table[
first].getChild()->getFirstValue()<0;
156 bool yInside = xInside, zInside = xInside;
157 for (
Index x = 0;
x != (1 << NodeT::LOG2DIM); ++
x) {
158 const int x00 =
x << (2 * NodeT::LOG2DIM);
159 if (childMask.isOn(x00)) xInside = table[x00].getChild()->getLastValue()<0;
161 for (
Index y = 0;
y != (1 << NodeT::LOG2DIM); ++
y) {
162 const Index xy0 = x00 + (
y << NodeT::LOG2DIM);
163 if (childMask.isOn(xy0)) yInside = table[xy0].getChild()->getLastValue()<0;
165 for (
Index z = 0;
z != (1 << NodeT::LOG2DIM); ++
z) {
166 const Index xyz = xy0 +
z;
167 if (childMask.isOn(xyz)) {
168 zInside = table[xyz].getChild()->getLastValue()<0;
170 table[xyz].setValue(zInside ? mInside : mOutside);
176 const ValueT v = table[0].getValue()<0 ? mInside : mOutside;
177 for (
Index i = 0; i < NodeT::NUM_VALUES; ++i) table[i].
setValue(v);
184 if (RootT::LEVEL < mMinLevel)
return;
185 using ChildT =
typename RootT::ChildNodeType;
187 std::map<Coord, ChildT*> nodeKeys;
188 typename RootT::ChildOnIter it = root.beginChildOn();
189 for (; it; ++it) nodeKeys.insert(std::pair<Coord, ChildT*>(it.getCoord(), &(*it)));
190 static const Index DIM = RootT::ChildNodeType::DIM;
194 typename std::map<Coord, ChildT*>::const_iterator
b = nodeKeys.begin(), e = nodeKeys.end();
195 if ( b == e )
return;
196 for (
typename std::map<Coord, ChildT*>::const_iterator
a = b++; b != e; ++
a, ++
b) {
197 Coord d = b->first -
a->first;
198 if (d[0]!=0 || d[1]!=0 || d[2]==
Int32(DIM))
continue;
199 const ValueT fill[] = {
a->second->getLastValue(), b->second->getFirstValue() };
200 if (!(fill[0] < 0) || !(fill[1] < 0))
continue;
201 Coord
c =
a->first + Coord(0u, 0u, DIM);
202 for (; c[2] != b->first[2]; c[2] += DIM) root.addTile(c, mInside,
false);
204 root.setBackground(mOutside,
false);
208 const ValueT mOutside, mInside;
209 const Index mMinLevel;
216 template<
typename TreeOrLeafManagerT>
219 doSignedFloodFill(TreeOrLeafManagerT& tree,
227 SignedFloodFillOp<TreeOrLeafManagerT> op(outsideValue, insideValue, minLevel);
228 nodes.foreachBottomUp(op, threaded, grainSize);
232 template <
typename TreeOrLeafManagerT>
235 doSignedFloodFill(TreeOrLeafManagerT&,
243 "signedFloodFill is supported only for signed value grids");
251 template <
typename TreeOrLeafManagerT>
254 TreeOrLeafManagerT& tree,
261 doSignedFloodFill(tree, outsideValue, insideValue, threaded, grainSize, minLevel);
265 template <
typename TreeOrLeafManagerT>
273 doSignedFloodFill(tree, v,
math::negative(v), threaded, grainSize, minLevel);
282 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
284 #ifdef OPENVDB_INSTANTIATE_SIGNEDFLOODFILL
288 #define _FUNCTION(TreeT) \
289 void signedFloodFill(TreeT&, bool, size_t, Index)
293 #define _FUNCTION(TreeT) \
294 void signedFloodFill(tree::LeafManager<TreeT>&, bool, size_t, Index)
298 #define _FUNCTION(TreeT) \
299 void signedFloodFillWithValues(TreeT&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t, Index)
303 #define _FUNCTION(TreeT) \
304 void signedFloodFillWithValues(tree::LeafManager<TreeT>&, const TreeT::ValueType&, const TreeT::ValueType&, bool, size_t, Index)
308 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
315 #endif // OPENVDB_TOOLS_RESETBACKGROUND_HAS_BEEN_INCLUDED
T negative(const T &val)
Return the unary negation of the given value.
GLsizei const GLfloat * value
GLdouble GLdouble GLdouble z
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
__hostdev__ void setValue(uint32_t offset, bool v)
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.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
GLboolean GLboolean GLboolean b
GLenum GLenum GLsizei void * table
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
#define OPENVDB_THROW(exception, message)