33 #ifndef OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED
36 #include <openvdb/Types.h>
37 #include <openvdb/tree/TreeIterator.h>
38 #include <openvdb/tree/ValueAccessor.h>
39 #include <openvdb/tree/LeafManager.h>
57 inline void dilateVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
67 inline void erodeVoxels(TreeType& tree,
int count=1);
70 inline void erodeVoxels(tree::LeafManager<TreeType>& manager,
int count = 1);
76 template<Index Log2Dim>
struct DimToWord {
typedef uint8_t Type[0]; };
83 template<
typename TreeType>
99 typedef typename TreeType::LeafNodeType LeafType;
100 typedef typename LeafType::NodeMaskType MaskType;
103 const bool mOwnsManager;
104 ManagerType* mManager;
107 static const int LEAF_DIM = LeafType::DIM;
108 static const int LEAF_LOG2DIM = LeafType::LOG2DIM;
115 static const Word OFF = Word(0), ON = ~OFF;
116 Neighbor() : leaf(NULL), init(true) {}
117 inline void clear() { init =
true; }
118 template<
int DX,
int DY,
int DZ>
119 void scatter(AccessorType& acc,
const Coord &xyz,
int indx, Word oldWord)
123 Coord orig = xyz.
offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
124 leaf = acc.probeLeaf(orig);
125 if (leaf==NULL && !acc.isValueOn(orig)) leaf = acc.touchLeaf(orig);
127 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
128 if (leaf) leaf->getValueMask().template getWord<Word>(indx-N) |= oldWord;
130 template<
int DX,
int DY,
int DZ>
131 Word gather(AccessorType& acc,
const Coord &xyz,
int indx)
135 Coord orig = xyz.
offsetBy(DX*LEAF_DIM, DY*LEAF_DIM, DZ*LEAF_DIM);
136 leaf = acc.probeLeaf(orig);
137 isOn = leaf ?
false : acc.isValueOn(orig);
139 static const int N = (LEAF_DIM -1 )*(DY + DX*LEAF_DIM);
140 return leaf ? leaf->getValueMask().template getWord<Word>(indx-N) : isOn ? ON : OFF;
145 template <
typename TreeType>
149 const int leafCount = mManager->leafCount();
152 std::vector<MaskType> savedMasks;
153 savedMasks.resize(leafCount);
154 for (
int i = 0; i < leafCount; ++i) savedMasks[i] = mManager->leaf(i).getValueMask();
158 for (
int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
159 const MaskType& oldMask = savedMasks[leafIdx];
160 LeafType& leaf = mManager->leaf(leafIdx);
161 leaf.getOrigin(origin);
162 for (
int x = 0; x < LEAF_DIM; ++x ) {
163 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
165 const Word oldWord = oldMask.template getWord<Word>(n);
166 if (oldWord == 0)
continue;
170 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM) |= oldWord;
172 NN[0].template scatter<-1, 0, 0>(
mAcc, origin, n, oldWord);
175 if (x < LEAF_DIM - 1) {
176 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM) |= oldWord;
178 NN[1].template scatter< 1, 0, 0>(
mAcc, origin, n, oldWord);
182 leaf.getValueMask().template getWord<Word>(n-1) |= oldWord;
184 NN[2].template scatter< 0,-1, 0>(
mAcc, origin, n, oldWord);
187 if (y < LEAF_DIM - 1) {
188 leaf.getValueMask().template getWord<Word>(n+1) |= oldWord;
190 NN[3].template scatter< 0, 1, 0>(
mAcc, origin, n, oldWord);
194 leaf.getValueMask().template getWord<Word>(n) |= (oldWord >> 1) | (oldWord << 1);
196 if (Word w = oldWord<<(LEAF_DIM-1)) {
197 NN[4].template scatter< 0, 0,-1>(
mAcc, origin, n, w);
200 if (Word w = oldWord>>(LEAF_DIM-1)) {
201 NN[5].template scatter< 0, 0, 1>(
mAcc, origin, n, w);
205 for (
int i=0; i<6; ++i) NN[i].clear();
208 mManager->rebuildLeafArray();
211 template <
typename TreeType>
215 const int leafCount = mManager->leafCount();
218 std::vector<MaskType> savedMasks;
219 savedMasks.resize(leafCount);
220 for (
int i = 0; i < leafCount; ++i) savedMasks[i] = mManager->leaf(i).getValueMask();
224 for (
int leafIdx = 0; leafIdx < leafCount; ++leafIdx) {
225 MaskType& newMask = savedMasks[leafIdx];
226 LeafType& leaf = mManager->leaf(leafIdx);
227 leaf.getOrigin(origin);
228 for (
int x = 0; x < LEAF_DIM; ++x ) {
229 for (
int y = 0, n = (x << LEAF_LOG2DIM); y < LEAF_DIM; ++y, ++n) {
231 Word& w = newMask.template getWord<Word>(n);
232 if (w == 0)
continue;
235 w &= (w<<1 | (NN[4].template gather<0,0,-1>(
mAcc, origin, n)>>(LEAF_DIM-1))) &
236 (w>>1 | (NN[5].template gather<0,0, 1>(
mAcc, origin, n)<<(LEAF_DIM-1)));
239 w &= (x == 0) ? NN[0].
template gather<-1, 0, 0>(mAcc, origin, n) :
240 leaf.getValueMask().template getWord<Word>(n-LEAF_DIM);
243 w &= (x == LEAF_DIM-1) ? NN[1].
template gather< 1, 0, 0>(mAcc, origin, n) :
244 leaf.getValueMask().template getWord<Word>(n+LEAF_DIM);
247 w &= (y == 0) ? NN[2].
template gather< 0,-1, 0>(mAcc, origin, n) :
248 leaf.getValueMask().template getWord<Word>(n-1);
251 w &= (y == LEAF_DIM-1) ? NN[3].
template gather< 0, 1, 0>(mAcc, origin, n) :
252 leaf.getValueMask().template getWord<Word>(n+1);
255 for (
int i=0; i<6; ++i) NN[i].clear();
258 for (
int i = 0; i < leafCount; ++i) mManager->leaf(i).setValueMask(savedMasks[i]);
260 mManager->tree().pruneLevelSet();
262 mManager->rebuildLeafArray();
269 template<
typename TreeType>
277 template<
typename TreeType>
285 template<
typename TreeType>
293 template<
typename TreeType>
305 #endif // OPENVDB_TOOLS_MORPHOLOGY_HAS_BEEN_INCLUDED