31 #ifndef OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
37 #include <boost/shared_ptr.hpp>
38 #include <boost/static_assert.hpp>
39 #include <boost/bind.hpp>
40 #include <tbb/blocked_range.h>
41 #include <tbb/parallel_for.h>
42 #include <openvdb/Types.h>
43 #include <openvdb/util/NodeMasks.h>
44 #include <openvdb/io/Compression.h>
59 template<
typename T, Index Log2Dim>
65 typedef boost::shared_ptr<LeafNode>
Ptr;
72 NUM_VALUES = 1 << 3 * Log2Dim,
73 NUM_VOXELS = NUM_VALUES,
79 template<
typename OtherValueType>
96 while (size--) *target++ = val;
108 while (size--) *target++ = *source++;
134 ValueType& operator[](
Index i) { assert(i < SIZE);
return mData[i]; }
136 friend class ::TestLeaf;
152 const ValueType& value = zeroVal<ValueType>(),
153 bool active =
false);
159 template<
typename OtherValueType>
164 template<
typename OtherValueType>
194 bool isEmpty()
const {
return mValueMask.isOff(); }
196 bool isDense()
const {
return mValueMask.isOn(); }
202 void evalActiveVoxelBoundingBox(
CoordBBox&)
const;
216 static void offset2coord(
Index n,
Coord &xyz);
221 std::string str()
const;
225 template<
typename OtherType, Index OtherLog2Dim>
241 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
246 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
253 ValueT&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
254 ValueT&
getValue()
const {
return this->parent().getValue(this->pos()); }
257 void setItem(
Index pos,
const ValueT& value)
const
259 this->parent().setValueOnly(pos, value);
262 void setValue(
const ValueT& value)
const
264 this->parent().setValueOnly(this->pos(), value);
269 template<
typename MaskIterT,
typename NodeT,
typename TagT>
271 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
278 template<
typename NodeT,
typename ValueT,
typename TagT>
280 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
290 value = this->parent().getValue(pos);
299 void unsetItem(
Index pos,
const ValueT& value)
const
301 this->parent().setValueOnly(pos, value);
377 void readTopology(std::istream&,
bool fromHalf =
false);
380 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
384 void readBuffers(std::istream&,
bool fromHalf =
false);
387 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
389 size_t streamingSize(
bool toHalf =
false)
const;
395 const ValueType& getValue(
const Coord& xyz)
const;
397 const ValueType& getValue(
Index offset)
const;
402 bool probeValue(
const Coord& xyz, ValueType& val)
const;
406 bool probeValue(
Index offset, ValueType& val)
const;
412 void setActiveState(
const Coord& xyz,
bool on);
420 void setValueOff(
const Coord& xyz,
const ValueType& val);
422 void setValueOff(
Index offset,
const ValueType& val);
430 this->setValueOn(LeafNode::coord2offset(xyz), val);
436 mBuffer[offset] = val;
437 mValueMask.setOn(offset);
443 this->setValueOnMin(LeafNode::coord2offset(xyz), val);
448 mBuffer[offset] =
std::min(val, mBuffer[offset]);
449 mValueMask.setOn(offset);
455 this->setValueOnMax(LeafNode::coord2offset(xyz), val);
460 mBuffer[offset] =
std::max(val, mBuffer[offset]);
461 mValueMask.setOn(offset);
467 this->setValueOnSum(LeafNode::coord2offset(xyz), val);
472 mBuffer[offset] += val;
473 mValueMask.setOn(offset);
477 this->resetValue(LeafNode::coord2offset(xyz), val);
482 this->setValueOnly(LeafNode::coord2offset(xyz), val);
489 assert(offset<SIZE); mBuffer[offset] = val;
493 mBuffer[offset] = val;
497 void addValue(
const ValueType& val);
499 void scaleValue(
const ValueType&
scale);
523 void fill(
const CoordBBox& bbox,
const ValueType&,
bool active =
true);
526 void fill(
const ValueType& value);
529 void fill(
const ValueType& value,
bool active);
533 template<
typename AccessorT>
536 return this->getValue(xyz);
541 template<
typename AccessorT>
546 template<
typename AccessorT>
549 this->setValueOn(xyz, val);
555 template<
typename AccessorT>
558 this->setValueOnly(xyz, val);
565 template<
typename AccessorT>
568 this->setValueOnSum(xyz, val);
573 template<
typename AccessorT>
576 this->setValueOff(xyz, value);
582 template<
typename AccessorT>
583 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&)
585 this->setActiveState(xyz, on);
591 template<
typename AccessorT>
594 return this->probeValue(xyz, val);
600 template<
typename AccessorT>
601 const ValueType& getValue(
const Coord& xyz,
bool& state,
int& level, AccessorT&)
const
603 const Index offset = this->coord2offset(xyz);
604 state = mValueMask.isOn(offset);
606 return mBuffer[offset];
608 template<
typename ProbeType,
typename AccessorT>
611 const Index offset = this->coord2offset(xyz);
612 p.setState(mValueMask.isOn(offset));
614 return mBuffer[offset];
616 template<
bool State,
bool Level,
typename AccessorT>
619 const Index offset = this->coord2offset(xyz);
620 if (State) state = mValueMask.isOn(offset);
621 if (Level) level = LEVEL;
622 return mBuffer[offset];
627 template<
typename AccessorT>
631 template<
typename AccessorT>
643 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
645 void signedFloodFill(
const ValueType& background);
652 LeafNode::merge(other);
660 template<
typename OtherType>
671 template<
typename OtherType>
674 template<
typename CombineOp>
676 template<
typename CombineOp>
677 void combine(
const ValueType& value,
bool valueIsActive, CombineOp& op);
679 template<
typename CombineOp>
680 void combine2(
const LeafNode& other,
const ValueType&,
bool valueIsActive, CombineOp&);
681 template<
typename CombineOp>
682 void combine2(
const ValueType&,
const LeafNode& other,
bool valueIsActive, CombineOp&);
683 template<
typename CombineOp>
691 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
693 template<
typename VisitorOp>
void visit(VisitorOp&);
694 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
696 template<
typename OtherLeafNodeType,
typename VisitorOp>
697 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
698 template<
typename OtherLeafNodeType,
typename VisitorOp>
699 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
700 template<
typename IterT,
typename VisitorOp>
701 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
702 template<
typename IterT,
typename VisitorOp>
703 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
707 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
714 template<
typename AccessorT>
717 template<
typename AccessorT>
723 template<
typename AccessorT>
730 bool isConstant(ValueType& constValue,
bool& state,
731 const ValueType& tolerance = zeroVal<ValueType>())
const;
736 friend class ::TestLeaf;
737 template<
typename>
friend class ::TestLeafIO;
782 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
783 static inline void doVisit(NodeT&, VisitorOp&);
785 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
786 typename ChildAllIterT,
typename OtherChildAllIterT>
787 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
789 template<
typename NodeT,
typename VisitorOp,
790 typename ChildAllIterT,
typename OtherChildAllIterT>
791 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
803 template<
typename T, Index Log2Dim>
812 template<
typename T, Index Log2Dim>
817 mOrigin(xyz & (~(DIM - 1)))
821 template<
typename T, Index Log2Dim>
822 template<
typename OtherValueType>
827 mValueMask(other.mValueMask),
828 mOrigin(other.mOrigin)
832 template<
typename T, Index Log2Dim>
833 template<
typename OtherValueType>
837 mValueMask(other.mValueMask),
838 mOrigin(other.mOrigin)
845 template<
typename T, Index Log2Dim>
848 mBuffer(other.mBuffer),
849 mValueMask(other.mValueMask),
850 mOrigin(other.mOrigin)
855 template<
typename T, Index Log2Dim>
862 template<
typename T, Index Log2Dim>
866 std::ostringstream ostr;
867 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
875 template<
typename T, Index Log2Dim>
879 assert ((xyz[0]&DIM-1u)<DIM && (xyz[1]&DIM-1u)<DIM && (xyz[2]&DIM-1u)<DIM);
880 return ((xyz[0]&DIM-1u)<<2*Log2Dim)
881 + ((xyz[1]&DIM-1u)<< Log2Dim)
886 template<
typename T, Index Log2Dim>
890 assert(n<(1<< 3*Log2Dim));
891 xyz.
setX(n >> 2*Log2Dim);
892 n &= ((1<<2*Log2Dim)-1);
893 xyz.
setY(n >> Log2Dim);
894 xyz.
setZ(n & ((1<<Log2Dim)-1));
898 template<
typename T, Index Log2Dim>
903 this->offset2coord(n, local);
904 return Coord(local + this->getOrigin());
911 template<
typename ValueT, Index Log2Dim>
918 template<
typename ValueT, Index Log2Dim>
922 assert(offset < SIZE);
923 return mBuffer[offset];
927 template<
typename T, Index Log2Dim>
934 template<
typename T, Index Log2Dim>
938 assert(offset < SIZE);
939 val = mBuffer[offset];
940 return mValueMask.isOn(offset);
944 template<
typename T, Index Log2Dim>
951 template<
typename T, Index Log2Dim>
955 assert(offset < SIZE);
956 mBuffer[offset] = val;
957 mValueMask.setOff(offset);
961 template<
typename T, Index Log2Dim>
965 mValueMask.set(this->coord2offset(xyz), on);
969 template<
typename T, Index Log2Dim>
974 mBuffer[iter.pos()] += val;
979 template<
typename T, Index Log2Dim>
984 mBuffer[iter.pos()] *=
scale;
992 template<
typename T, Index Log2Dim>
997 const Index offsetX = (x&DIM-1u)<<2*Log2Dim;
999 const Index offsetXY = offsetX + ((y&DIM-1u)<< Log2Dim);
1001 const Index offset = offsetXY + (z&DIM-1u);
1002 mBuffer[offset] = value;
1003 mValueMask.set(offset, active);
1009 template<
typename T, Index Log2Dim>
1013 mBuffer.fill(value);
1016 template<
typename T, Index Log2Dim>
1020 mBuffer.fill(value);
1021 mValueMask.set(active);
1028 template<
typename T, Index Log2Dim>
1032 mValueMask.load(is);
1036 template<
typename T, Index Log2Dim>
1040 mValueMask.save(os);
1047 template<
typename T, Index Log2Dim>
1052 mValueMask.load(is);
1054 int8_t numBuffers = 1;
1060 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1065 if (numBuffers > 1) {
1070 for (
int i = 1; i < numBuffers; ++i) {
1074 io::readData<T>(is, temp.mData, SIZE, zipped);
1081 template<
typename T, Index Log2Dim>
1086 mValueMask.save(os);
1096 template<
typename T, Index Log2Dim>
1100 return mOrigin == other.
mOrigin &&
1106 template<
typename T, Index Log2Dim>
1110 return mBuffer.memUsage() +
sizeof(mOrigin) + mValueMask.memUsage();
1114 template<
typename T, Index Log2Dim>
1118 const CoordBBox this_bbox = this->getNodeBoundingBox();
1121 }
else if (this->isDense()) {
1124 for (
ValueOnCIter iter=this->cbeginValueOn(); iter; ++iter) bbox.
expand(iter.getCoord());
1129 template<
typename T, Index Log2Dim>
1130 template<
typename OtherType, Index OtherLog2Dim>
1135 return (Log2Dim == OtherLog2Dim && mValueMask == other->
getValueMask());
1139 template<
typename T, Index Log2Dim>
1143 if (!mValueMask.isOn() && !mValueMask.isOff())
return false;
1145 state = mValueMask.isOn();
1147 bool allEqual =
true;
1148 const T value = mBuffer[0];
1149 for (
Index i = 1; allEqual && i < SIZE; ++i) {
1153 if (allEqual) constValue = value;
1161 template<
typename T, Index Log2Dim>
1166 const Index first = mValueMask.findFirstOn();
1168 if (first == SIZE)
return;
1170 const T zero = zeroVal<T>();
1171 bool inside = (mBuffer[first] < zero), xInside = inside, yInside = inside;
1172 for (
Index i = 0; i != (1 << Log2Dim); ++i) {
1173 const Index x = i << (2 * Log2Dim);
1174 if (mValueMask.isOn(x)) {
1175 xInside = (mBuffer[x] < zero);
1178 for (
Index j = 0; j != (1 << Log2Dim); ++j) {
1179 const Index xy = x + (j << Log2Dim);
1180 if (mValueMask.isOn(xy)) {
1181 yInside = (mBuffer[xy] < zero);
1184 for (
Index k = 0; k != (1 << Log2Dim); ++k) {
1185 const Index xyz = xy + k;
1186 if (mValueMask.isOn(xyz)) {
1187 inside = (mBuffer[xyz] < zero);
1188 }
else if (inside) {
1189 mBuffer[xyz] =
negative(background);
1191 mBuffer[xyz] = background;
1199 template<
typename T, Index Log2Dim>
1206 for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1209 inactiveValue = newBackground;
1211 inactiveValue =
negative(newBackground);
1217 template<
typename T, Index Log2Dim>
1222 for (; iter; ++iter) {
1224 if (mValueMask.isOn(n))
continue;
1225 mBuffer[n] = other.
mBuffer[n];
1226 mValueMask.setOn(n);
1231 template<
typename T, Index Log2Dim>
1232 template<
typename OtherType>
1239 template<
typename T, Index Log2Dim>
1240 template<
typename OtherType>
1248 template<
typename T, Index Log2Dim>
1252 for (
Index i = 0; i < SIZE; ++i) {
1253 mBuffer[i] = -mBuffer[i];
1261 template<
typename T, Index Log2Dim>
1262 template<
typename CombineOp>
1267 for (
Index i = 0; i < SIZE; ++i) {
1269 .setAIsActive(mValueMask.isOn(i))
1272 .setResultRef(mBuffer[i]));
1278 template<
typename T, Index Log2Dim>
1279 template<
typename CombineOp>
1284 args.
setBRef(value).setBIsActive(valueIsActive);
1285 for (
Index i = 0; i < SIZE; ++i) {
1287 .setAIsActive(mValueMask.isOn(i))
1288 .setResultRef(mBuffer[i]));
1297 template<
typename T, Index Log2Dim>
1298 template<
typename CombineOp>
1301 bool valueIsActive, CombineOp& op)
1304 args.
setBRef(value).setBIsActive(valueIsActive);
1305 for (
Index i = 0; i < SIZE; ++i) {
1308 .setResultRef(mBuffer[i]));
1314 template<
typename T, Index Log2Dim>
1315 template<
typename CombineOp>
1318 bool valueIsActive, CombineOp& op)
1321 args.
setARef(value).setAIsActive(valueIsActive);
1322 for (
Index i = 0; i < SIZE; ++i) {
1325 .setResultRef(mBuffer[i]));
1331 template<
typename T, Index Log2Dim>
1332 template<
typename CombineOp>
1337 for (
Index i = 0; i < SIZE; ++i) {
1343 .setResultRef(mBuffer[i]));
1352 template<
typename T, Index Log2Dim>
1353 template<
typename BBoxOp>
1357 if (op.template descent<LEVEL>()) {
1367 op.operator()<LEVEL>(this->getNodeBoundingBox());
1369 op.template operator()<LEVEL>(this->getNodeBoundingBox());
1375 template<
typename T, Index Log2Dim>
1376 template<
typename VisitorOp>
1380 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1384 template<
typename T, Index Log2Dim>
1385 template<
typename VisitorOp>
1389 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1393 template<
typename T, Index Log2Dim>
1394 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1398 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1407 template<
typename T, Index Log2Dim>
1408 template<
typename OtherLeafNodeType,
typename VisitorOp>
1413 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1417 template<
typename T, Index Log2Dim>
1418 template<
typename OtherLeafNodeType,
typename VisitorOp>
1423 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1427 template<
typename T, Index Log2Dim>
1430 typename OtherNodeT,
1432 typename ChildAllIterT,
1433 typename OtherChildAllIterT>
1438 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1439 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1441 ChildAllIterT iter =
self.beginChildAll();
1442 OtherChildAllIterT otherIter = other.beginChildAll();
1444 for ( ; iter && otherIter; ++iter, ++otherIter) {
1445 op(iter, otherIter);
1453 template<
typename T, Index Log2Dim>
1454 template<
typename IterT,
typename VisitorOp>
1458 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
1459 *
this, otherIter, op, otherIsLHS);
1463 template<
typename T, Index Log2Dim>
1464 template<
typename IterT,
typename VisitorOp>
1468 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
1469 *
this, otherIter, op, otherIsLHS);
1473 template<
typename T, Index Log2Dim>
1477 typename ChildAllIterT,
1478 typename OtherChildAllIterT>
1481 VisitorOp& op,
bool otherIsLHS)
1483 if (!otherIter)
return;
1486 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1487 op(otherIter, iter);
1490 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1491 op(iter, otherIter);
1500 template<
typename T, Index Log2Dim>
1501 inline std::ostream&
1502 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
1504 for (
Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] <<
", ";
1519 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED