31 #ifndef OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
34 #include <openvdb/Types.h>
35 #include <openvdb/tree/TreeIterator.h>
36 #include <openvdb/tree/ValueAccessor.h>
37 #include <openvdb/tree/LeafManager.h>
64 template<Index Log2Dim>
struct DimToWord {
typedef uint8_t Type[0]; };
74 #undef OPENVDB_TOOLS_MORPHOLOGY_USE_WORKAROUND_FOR_BROKEN_ICC12_COMPILER
76 #if __ICC >= 1210 && __ICC < 1300
79 #define OPENVDB_TOOLS_MORPHOLOGY_USE_WORKAROUND_FOR_BROKEN_ICC12_COMPILER
84 #ifndef OPENVDB_TOOLS_MORPHOLOGY_USE_WORKAROUND_FOR_BROKEN_ICC12_COMPILER
86 template<
typename TreeType>
90 typedef typename TreeType::LeafNodeType LeafType;
91 typedef typename LeafType::NodeMaskType MaskType;
94 static const Index LEAF_DIM = LeafType::DIM;
95 static const Index LEAF_LOG2DIM = LeafType::LOG2DIM;
99 Accessor acc(manager.
tree());
104 std::vector<MaskType> savedMasks;
105 savedMasks.resize(leafCount);
106 for (
Index i = 0; i < leafCount; ++i) {
107 savedMasks[i] = manager.
leaf(i).getValueMask();
114 Neighbor(Accessor& acc,
const Coord& xyz):
115 leaf(acc.probeLeaf(xyz)), isOn(
false), orig(xyz)
117 if (leaf == NULL) isOn = acc.isValueOn(xyz);
119 void createLeaf(Accessor& acc) {
if (leaf == NULL) leaf = acc.touchLeaf(orig); }
123 for (
Index i = 0; i < leafCount; ++i) {
125 const MaskType& oldMask = savedMasks[i];
126 LeafType& leaf = manager.
leaf(i);
127 leaf.getOrigin(origin);
131 Neighbor MX(acc, origin.
offsetBy(-LEAF_DIM, 0, 0));
132 Neighbor PX(acc, origin.
offsetBy( LEAF_DIM, 0, 0));
133 Neighbor MY(acc, origin.
offsetBy( 0, -LEAF_DIM, 0));
134 Neighbor PY(acc, origin.
offsetBy( 0, LEAF_DIM, 0));
135 Neighbor MZ(acc, origin.
offsetBy( 0, 0,-LEAF_DIM));
136 Neighbor PZ(acc, origin.
offsetBy( 0, 0, LEAF_DIM));
138 for (
Index x = 0; x < LEAF_DIM; ++x) {
139 for (
Index y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
141 const Word oldWord = oldMask.template getWord<Word>(n);
142 if (oldWord == 0)
continue;
146 leaf.getValueMask().template getWord<Word>(n) |= (oldWord >> 1) | (oldWord << 1);
148 if (!MZ.isOn && Word(oldWord<<(LEAF_DIM-1))) {
150 MZ.leaf->getValueMask().template getWord<Word>(n)
151 |= Word(oldWord<<(LEAF_DIM-1));
153 if (!PZ.isOn && Word(oldWord>>(LEAF_DIM-1))) {
155 PZ.leaf->getValueMask().template getWord<Word>(n)
156 |= Word(oldWord>>(LEAF_DIM-1));
162 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM) |= oldWord;
163 }
else if (!MX.isOn) {
169 MX.leaf->getValueMask().template getWord<Word>(n+LEAF_DIM*(LEAF_DIM-1))
173 if (x < LEAF_DIM - 1) {
176 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM) |= oldWord;
177 }
else if (!PX.isOn) {
180 PX.leaf->getValueMask().template getWord<Word>(n-LEAF_DIM*(LEAF_DIM-1))
187 leaf.getValueMask().template getWord<Word>(n-1) |= oldWord;
188 }
else if (!MY.isOn) {
191 MY.leaf->getValueMask().template getWord<Word>(n+LEAF_DIM-1) |= oldWord;
194 if (y < LEAF_DIM - 1) {
197 leaf.getValueMask().template getWord<Word>(n+1) |= oldWord;
198 }
else if (!PY.isOn) {
201 PY.leaf->getValueMask().template getWord<Word>(n-LEAF_DIM+1) |= oldWord;
208 #else // ifdef OPENVDB_TOOLS_MORPHOLOGY_USE_WORKAROUND_FOR_BROKEN_ICC12_COMPILER
216 template<
typename TreeType>
219 typedef typename TreeType::LeafNodeType LeafType;
224 const boost::shared_ptr<LeafType> onTile, offTile;
226 LeafLookup(TreeType& tree):
227 cache(tree), onTile(new LeafType), offTile(new LeafType) {}
229 bool isActiveTile(
const LeafType* leaf)
const {
return leaf == onTile.get(); }
230 bool isInactiveTile(
const LeafType* leaf)
const {
return leaf == offTile.get(); }
234 LeafType* operator()(
const Coord& xyz)
237 cache.template eraseNode<LeafType>();
239 bool on = cache.isValueOn(xyz);
240 LeafType* leaf = cache.template getNode<LeafType>();
243 return leaf != NULL ? leaf : (on ? onTile.get() : offTile.get());
247 LeafType* createLeaf(
const Coord& xyz)
249 cache.template eraseNode<LeafType>();
251 cache.setValueOn(xyz);
252 LeafType* leaf = cache.template getNode<LeafType>();
254 leaf->setValuesOff();
260 template<
typename TreeType>
264 typedef typename TreeType::LeafNodeType LeafType;
265 typedef typename LeafType::NodeMaskType MaskType;
267 static const Index LEAF_DIM = LeafType::DIM;
268 static const Index LEAF_LOG2DIM = LeafType::LOG2DIM;
270 typedef typename DimToWord<LEAF_LOG2DIM>::Type Word;
273 const Index leafCount = manager.leafCount();
276 std::vector<MaskType> savedMasks;
277 savedMasks.resize(leafCount);
278 for (
Index i = 0; i < leafCount; ++i) {
279 savedMasks[i] = manager.leaf(i).getValueMask();
282 LeafLookup<TreeType> leafLookup(manager.tree());
285 for (
Index i = 0; i < leafCount; ++i) {
286 const MaskType& oldMask = savedMasks[i];
289 manager.leaf(i).getOrigin(origin);
293 LeafType* nbhd[5] = {
295 leafLookup(origin.offsetBy(-LEAF_DIM, 0, 0)),
296 leafLookup(origin.offsetBy( LEAF_DIM, 0, 0)),
297 leafLookup(origin.offsetBy( 0, -LEAF_DIM, 0)),
298 leafLookup(origin.offsetBy( 0, LEAF_DIM, 0))
301 for (
Index x = 0; x < LEAF_DIM; ++x) {
302 for (
Index y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
304 const Word oldWord = oldMask.template getWord<Word>(n);
305 if (oldWord == 0)
continue;
309 nbhd[0]->getValueMask().template getWord<Word>(n) |=
310 (oldWord >> 1) | (oldWord << 1);
315 leafLookup.cache.setValueOn(origin.offsetBy(x, y, -1));
317 if (Word(oldWord >> (LEAF_DIM - 1))) {
320 leafLookup.cache.setValueOn(origin.offsetBy(x, y, LEAF_DIM));
326 nbhd[0]->getValueMask().template getWord<Word>(n - LEAF_DIM) |= oldWord;
327 }
else if (!leafLookup.isActiveTile(nbhd[1])) {
330 if (leafLookup.isInactiveTile(nbhd[1])) {
332 nbhd[1] = leafLookup.createLeaf(origin.offsetBy(-LEAF_DIM, 0, 0));
336 nbhd[1]->getValueMask().template getWord<Word>(
337 n + LEAF_DIM * (LEAF_DIM - 1)) |= oldWord;
340 if (x < LEAF_DIM - 1) {
343 nbhd[0]->getValueMask().template getWord<Word>(n + LEAF_DIM) |= oldWord;
344 }
else if (!leafLookup.isActiveTile(nbhd[2])) {
346 if (leafLookup.isInactiveTile(nbhd[2])) {
348 nbhd[2] = leafLookup.createLeaf(origin.offsetBy(LEAF_DIM, 0, 0));
350 nbhd[2]->getValueMask().template getWord<Word>(
351 n - LEAF_DIM * (LEAF_DIM - 1)) |= oldWord;
357 nbhd[0]->getValueMask().template getWord<Word>(n - 1) |= oldWord;
358 }
else if (!leafLookup.isActiveTile(nbhd[3])) {
360 if (leafLookup.isInactiveTile(nbhd[3])) {
362 nbhd[3] = leafLookup.createLeaf(origin.offsetBy(0, -LEAF_DIM, 0));
364 nbhd[3]->getValueMask().template getWord<Word>(n+LEAF_DIM-1) |= oldWord;
367 if (y < LEAF_DIM - 1) {
370 nbhd[0]->getValueMask().template getWord<Word>(n + 1) |= oldWord;
371 }
else if (!leafLookup.isActiveTile(nbhd[4])) {
373 if (leafLookup.isInactiveTile(nbhd[4])) {
375 nbhd[4] = leafLookup.createLeaf(origin.offsetBy(0, LEAF_DIM, 0));
377 nbhd[4]->getValueMask().template getWord<Word>(n-LEAF_DIM+1) |= oldWord;
384 #endif // defined(OPENVDB_TOOLS_MORPHOLOGY_USE_WORKAROUND_FOR_BROKEN_ICC12_COMPILER)
387 template<
typename TreeType>
392 dilateVoxels<TreeType>(manager);
399 #endif // OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED