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>
61 template<
typename T, Index Log2Dim>
67 typedef boost::shared_ptr<LeafNode>
Ptr;
74 NUM_VALUES = 1 << 3 * Log2Dim,
75 NUM_VOXELS = NUM_VALUES,
81 template<
typename OtherValueType>
104 while (n--) *target++ = val;
118 while (n--) *target++ = *source++;
149 ValueType& operator[](
Index i) { assert(i < SIZE);
return mData[i]; }
151 friend class ::TestLeaf;
167 const ValueType& value = zeroVal<ValueType>(),
168 bool active =
false);
174 template<
typename OtherValueType>
179 template<
typename OtherValueType>
215 bool isEmpty()
const {
return mValueMask.isOff(); }
217 bool isDense()
const {
return mValueMask.isOn(); }
223 void evalActiveVoxelBoundingBox(
CoordBBox&)
const;
240 static void offset2coord(
Index n,
Coord &xyz);
245 std::string str()
const;
249 template<
typename OtherType, Index OtherLog2Dim>
265 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
270 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
277 ValueT&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
278 ValueT&
getValue()
const {
return this->parent().getValue(this->pos()); }
283 this->parent().setValueOnly(pos, value);
288 this->parent().setValueOnly(this->pos(), value);
293 template<
typename MaskIterT,
typename NodeT,
typename TagT>
295 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
302 template<
typename NodeT,
typename ValueT,
typename TagT>
304 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
314 value = this->parent().getValue(pos);
325 this->parent().setValueOnly(pos, value);
400 void readTopology(std::istream& is,
bool fromHalf =
false);
404 void writeTopology(std::ostream& os,
bool toHalf =
false)
const;
409 void readBuffers(std::istream& is,
bool fromHalf =
false);
413 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
415 size_t streamingSize(
bool toHalf =
false)
const;
421 const ValueType& getValue(
const Coord& xyz)
const;
423 const ValueType& getValue(
Index offset)
const;
428 bool probeValue(
const Coord& xyz, ValueType& val)
const;
432 bool probeValue(
Index offset, ValueType& val)
const;
438 void setActiveState(
const Coord& xyz,
bool on);
446 void setValueOff(
const Coord& xyz,
const ValueType& val);
448 void setValueOff(
Index offset,
const ValueType& val);
456 this->setValueOn(LeafNode::coord2offset(xyz), val);
462 mBuffer[offset] = val;
463 mValueMask.setOn(offset);
469 this->setValueOnMin(LeafNode::coord2offset(xyz), val);
474 mBuffer[offset] =
std::min(val, mBuffer[offset]);
475 mValueMask.setOn(offset);
481 this->setValueOnMax(LeafNode::coord2offset(xyz), val);
486 mBuffer[offset] =
std::max(val, mBuffer[offset]);
487 mValueMask.setOn(offset);
493 this->setValueOnSum(LeafNode::coord2offset(xyz), val);
498 mBuffer[offset] += val;
499 mValueMask.setOn(offset);
505 this->setValueOnly(LeafNode::coord2offset(xyz), val);
512 assert(offset<SIZE); mBuffer[offset] = val;
535 void fill(
const CoordBBox& bbox,
const ValueType&,
bool active =
true);
538 void fill(
const ValueType& value);
541 void fill(
const ValueType& value,
bool active);
554 template<
typename DenseT>
573 template<
typename DenseT>
575 const ValueType& background,
const ValueType&
tolerance);
579 template<
typename AccessorT>
582 return this->getValue(xyz);
587 template<
typename AccessorT>
592 template<
typename AccessorT>
595 this->setValueOn(xyz, val);
601 template<
typename AccessorT>
604 this->setValueOnly(xyz, val);
611 template<
typename AccessorT>
614 this->setValueOnSum(xyz, val);
619 template<
typename AccessorT>
622 this->setValueOff(xyz, value);
628 template<
typename AccessorT>
631 this->setActiveState(xyz, on);
637 template<
typename AccessorT>
640 return this->probeValue(xyz, val);
646 template<
typename AccessorT>
649 const Index offset = this->coord2offset(xyz);
650 state = mValueMask.isOn(offset);
652 return mBuffer[offset];
657 template<
typename AccessorT>
669 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
680 void signedFloodFill(
const ValueType& background);
688 void signedFloodFill(
const ValueType& outside,
const ValueType& inside);
695 LeafNode::merge(other);
705 template<
typename OtherType>
719 template<
typename OtherType>
733 template<
typename OtherType>
736 template<
typename CombineOp>
738 template<
typename CombineOp>
739 void combine(
const ValueType& value,
bool valueIsActive, CombineOp& op);
741 template<
typename CombineOp>
742 void combine2(
const LeafNode& other,
const ValueType&,
bool valueIsActive, CombineOp&);
743 template<
typename CombineOp>
744 void combine2(
const ValueType&,
const LeafNode& other,
bool valueIsActive, CombineOp&);
745 template<
typename CombineOp>
753 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
755 template<
typename VisitorOp>
void visit(VisitorOp&);
756 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
758 template<
typename OtherLeafNodeType,
typename VisitorOp>
759 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
760 template<
typename OtherLeafNodeType,
typename VisitorOp>
761 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
762 template<
typename IterT,
typename VisitorOp>
763 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
764 template<
typename IterT,
typename VisitorOp>
765 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
768 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
773 template<
typename AccessorT>
775 template<
typename NodeT>
777 template<
typename NodeT>
779 template<
typename NodeT>
782 template<
typename AccessorT>
788 template<
typename AccessorT>
790 template<
typename NodeT,
typename AccessorT>
794 if (!(boost::is_same<NodeT,LeafNode>::value))
return NULL;
795 return reinterpret_cast<NodeT*
>(
this);
799 template<
typename AccessorT>
803 const LeafNode* probeConstLeaf(
const Coord&)
const {
return this; }
805 template<
typename AccessorT>
807 template<
typename AccessorT>
810 template<
typename NodeT,
typename AccessorT>
814 if (!(boost::is_same<NodeT,LeafNode>::value))
return NULL;
815 return reinterpret_cast<const NodeT*
>(
this);
821 template<
typename NodeT>
822 static bool hasNodeType() {
return (boost::is_same<NodeT,LeafNode>::value); }
827 bool isConstant(ValueType& constValue,
bool& state,
828 const ValueType&
tolerance = zeroVal<ValueType>())
const;
833 friend class ::TestLeaf;
834 template<
typename>
friend class ::TestLeafIO;
880 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
881 static inline void doVisit(NodeT&, VisitorOp&);
883 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
884 typename ChildAllIterT,
typename OtherChildAllIterT>
885 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
887 template<
typename NodeT,
typename VisitorOp,
888 typename ChildAllIterT,
typename OtherChildAllIterT>
889 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
901 template<
typename T, Index Log2Dim>
910 template<
typename T, Index Log2Dim>
915 mOrigin(xyz & (~(DIM - 1)))
919 template<
typename T, Index Log2Dim>
920 template<
typename OtherValueType>
925 mValueMask(other.mValueMask),
926 mOrigin(other.mOrigin)
930 template<
typename T, Index Log2Dim>
931 template<
typename OtherValueType>
935 mValueMask(other.mValueMask),
936 mOrigin(other.mOrigin)
943 template<
typename T, Index Log2Dim>
946 mBuffer(other.mBuffer),
947 mValueMask(other.mValueMask),
948 mOrigin(other.mOrigin)
953 template<
typename T, Index Log2Dim>
960 template<
typename T, Index Log2Dim>
964 std::ostringstream ostr;
965 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
973 template<
typename T, Index Log2Dim>
977 assert ((xyz[0]&DIM-1u)<DIM && (xyz[1]&DIM-1u)<DIM && (xyz[2]&DIM-1u)<DIM);
978 return ((xyz[0]&DIM-1u)<<2*Log2Dim)
979 + ((xyz[1]&DIM-1u)<< Log2Dim)
984 template<
typename T, Index Log2Dim>
988 assert(n<(1<< 3*Log2Dim));
989 xyz.
setX(n >> 2*Log2Dim);
990 n &= ((1<<2*Log2Dim)-1);
991 xyz.
setY(n >> Log2Dim);
992 xyz.
setZ(n & ((1<<Log2Dim)-1));
996 template<
typename T, Index Log2Dim>
1001 this->offset2coord(n, local);
1002 return Coord(local + this->getOrigin());
1009 template<
typename ValueT, Index Log2Dim>
1010 inline const ValueT&
1016 template<
typename ValueT, Index Log2Dim>
1017 inline const ValueT&
1020 assert(offset < SIZE);
1021 return mBuffer[offset];
1025 template<
typename T, Index Log2Dim>
1032 template<
typename T, Index Log2Dim>
1036 assert(offset < SIZE);
1037 val = mBuffer[offset];
1038 return mValueMask.isOn(offset);
1042 template<
typename T, Index Log2Dim>
1049 template<
typename T, Index Log2Dim>
1053 assert(offset < SIZE);
1054 mBuffer[offset] = val;
1055 mValueMask.setOff(offset);
1059 template<
typename T, Index Log2Dim>
1063 mValueMask.set(this->coord2offset(xyz), on);
1067 template<
typename T, Index Log2Dim>
1072 mBuffer[iter.pos()] += val;
1077 template<
typename T, Index Log2Dim>
1082 mBuffer[iter.pos()] *=
scale;
1090 template<
typename T, Index Log2Dim>
1095 const Index offsetX = (x&DIM-1u)<<2*Log2Dim;
1097 const Index offsetXY = offsetX + ((y&DIM-1u)<< Log2Dim);
1099 const Index offset = offsetXY + (z&DIM-1u);
1100 mBuffer[offset] = value;
1101 mValueMask.set(offset, active);
1107 template<
typename T, Index Log2Dim>
1111 mBuffer.fill(value);
1114 template<
typename T, Index Log2Dim>
1118 mBuffer.fill(value);
1119 mValueMask.set(active);
1124 template<
typename T, Index Log2Dim>
1125 template<
typename DenseT>
1129 const size_t xStride = dense.xStride(), yStride = dense.yStride();
1130 const Coord&
min = dense.bbox().min();
1131 T* t0 = dense.data() + bbox.
min()[2]-min[2];
1132 const T* s0 = &mBuffer[bbox.
min()[2]&DIM-1u];
1133 for (
Int32 x = bbox.
min()[0], ex=bbox.
max()[0]+1; x<ex; ++x) {
1134 T* t1 = t0 + xStride*(x-min[0]);
1135 const T* s1 = s0 + ((x&DIM-1u)<<2*Log2Dim);
1136 for (
Int32 y = bbox.
min()[1], ey=bbox.
max()[1]+1; y<ey; ++y) {
1137 T* t2 = t1 + yStride*(y-min[1]);
1138 const T* s2 = s1 + ((y&DIM-1u)<<Log2Dim);
1139 for (
Int32 z = bbox.
min()[2], ez=bbox.
max()[2]+1; z<ez ; ++z) *t2++ = *s2++;
1144 template<
typename T, Index Log2Dim>
1145 template<
typename DenseT>
1150 const size_t xStride = dense.xStride(), yStride = dense.yStride();
1151 const Coord&
min = dense.bbox().min();
1153 const ValueType* s0 = dense.data() + bbox.
min()[2]-min[2];
1154 const Int32 n0 = bbox.
min()[2]&DIM-1u;
1155 for (
Int32 x = bbox.
min()[0], ex=bbox.
max()[0]+1; x<ex; ++x) {
1156 const ValueType* s1 = s0 + xStride*(x-min[0]);
1157 const Int32 n1 = n0 + ((x&DIM-1u)<<2*LOG2DIM);
1158 for (
Int32 y = bbox.
min()[1], ey=bbox.
max()[1]+1; y<ey; ++y) {
1159 const ValueType* s2 = s1 + yStride*(y-min[1]);
1160 Int32 n2 = n1 + ((y&DIM-1u)<<LOG2DIM) ;
1161 for (
Int32 z = bbox.
min()[2], ez=bbox.
max()[2]+1; z<ez ; ++z, ++n2, ++s2) {
1163 mValueMask.setOff(n2);
1164 mBuffer[n2] = background;
1166 mValueMask.setOn(n2);
1177 template<
typename T, Index Log2Dim>
1181 mValueMask.load(is);
1185 template<
typename T, Index Log2Dim>
1189 mValueMask.save(os);
1196 template<
typename T, Index Log2Dim>
1201 mValueMask.load(is);
1203 int8_t numBuffers = 1;
1209 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1214 if (numBuffers > 1) {
1219 for (
int i = 1; i < numBuffers; ++i) {
1223 io::readData<T>(is, temp.mData, SIZE, zipped);
1230 template<
typename T, Index Log2Dim>
1235 mValueMask.save(os);
1245 template<
typename T, Index Log2Dim>
1249 return mOrigin == other.
mOrigin &&
1255 template<
typename T, Index Log2Dim>
1259 return mBuffer.memUsage() +
sizeof(mOrigin) + mValueMask.memUsage();
1263 template<
typename T, Index Log2Dim>
1267 const CoordBBox this_bbox = this->getNodeBoundingBox();
1270 }
else if (this->isDense()) {
1273 for (
ValueOnCIter iter=this->cbeginValueOn(); iter; ++iter) bbox.
expand(iter.getCoord());
1278 template<
typename T, Index Log2Dim>
1279 template<
typename OtherType, Index OtherLog2Dim>
1284 return (Log2Dim == OtherLog2Dim && mValueMask == other->
getValueMask());
1288 template<
typename T, Index Log2Dim>
1293 if (!mValueMask.isOn() && !mValueMask.isOff())
return false;
1295 state = mValueMask.isOn();
1297 bool allEqual =
true;
1298 const T value = mBuffer[0];
1299 for (
Index i = 1; allEqual && i < SIZE; ++i) {
1303 if (allEqual) constValue = value;
1307 template<
typename T, Index Log2Dim>
1311 this->signedFloodFill(background,
negative(background));
1314 template<
typename T, Index Log2Dim>
1319 const Index first = mValueMask.findFirstOn();
1321 bool xInside =
math::isNegative(mBuffer[first]), yInside = xInside, zInside = xInside;
1322 for (
Index x = 0; x != (1 << Log2Dim); ++x) {
1323 const Index x00 = x << (2 * Log2Dim);
1324 if (mValueMask.isOn(x00)) {
1328 for (
Index y = 0; y != (1 << Log2Dim); ++y) {
1329 const Index xy0 = x00 + (y << Log2Dim);
1330 if (mValueMask.isOn(xy0)) {
1334 for (
Index z = 0; z != (1 << Log2Dim); ++z) {
1335 const Index xyz = xy0 + z;
1336 if (mValueMask.isOn(xyz)) {
1339 mBuffer[xyz] = zInside ? insideValue : outsideValue;
1350 template<
typename T, Index Log2Dim>
1357 for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1360 inactiveValue = newBackground;
1362 inactiveValue =
negative(newBackground);
1368 template<
typename T, Index Log2Dim>
1373 for (; iter; ++iter) {
1375 if (mValueMask.isOn(n))
continue;
1376 mBuffer[n] = other.
mBuffer[n];
1377 mValueMask.setOn(n);
1382 template<
typename T, Index Log2Dim>
1383 template<
typename OtherType>
1390 template<
typename T, Index Log2Dim>
1391 template<
typename OtherType>
1399 template<
typename T, Index Log2Dim>
1400 template<
typename OtherType>
1408 template<
typename T, Index Log2Dim>
1412 for (
Index i = 0; i < SIZE; ++i) {
1413 mBuffer[i] = -mBuffer[i];
1421 template<
typename T, Index Log2Dim>
1422 template<
typename CombineOp>
1427 for (
Index i = 0; i < SIZE; ++i) {
1429 .setAIsActive(mValueMask.isOn(i))
1432 .setResultRef(mBuffer[i]));
1438 template<
typename T, Index Log2Dim>
1439 template<
typename CombineOp>
1444 args.
setBRef(value).setBIsActive(valueIsActive);
1445 for (
Index i = 0; i < SIZE; ++i) {
1447 .setAIsActive(mValueMask.isOn(i))
1448 .setResultRef(mBuffer[i]));
1457 template<
typename T, Index Log2Dim>
1458 template<
typename CombineOp>
1461 bool valueIsActive, CombineOp& op)
1464 args.
setBRef(value).setBIsActive(valueIsActive);
1465 for (
Index i = 0; i < SIZE; ++i) {
1468 .setResultRef(mBuffer[i]));
1474 template<
typename T, Index Log2Dim>
1475 template<
typename CombineOp>
1478 bool valueIsActive, CombineOp& op)
1481 args.
setARef(value).setAIsActive(valueIsActive);
1482 for (
Index i = 0; i < SIZE; ++i) {
1485 .setResultRef(mBuffer[i]));
1491 template<
typename T, Index Log2Dim>
1492 template<
typename CombineOp>
1497 for (
Index i = 0; i < SIZE; ++i) {
1503 .setResultRef(mBuffer[i]));
1512 template<
typename T, Index Log2Dim>
1513 template<
typename BBoxOp>
1517 if (op.template descent<LEVEL>()) {
1527 op.operator()<LEVEL>(this->getNodeBoundingBox());
1529 op.template operator()<LEVEL>(this->getNodeBoundingBox());
1535 template<
typename T, Index Log2Dim>
1536 template<
typename VisitorOp>
1540 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1544 template<
typename T, Index Log2Dim>
1545 template<
typename VisitorOp>
1549 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1553 template<
typename T, Index Log2Dim>
1554 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1558 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1567 template<
typename T, Index Log2Dim>
1568 template<
typename OtherLeafNodeType,
typename VisitorOp>
1573 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1577 template<
typename T, Index Log2Dim>
1578 template<
typename OtherLeafNodeType,
typename VisitorOp>
1583 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1587 template<
typename T, Index Log2Dim>
1590 typename OtherNodeT,
1592 typename ChildAllIterT,
1593 typename OtherChildAllIterT>
1598 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1599 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1601 ChildAllIterT iter =
self.beginChildAll();
1602 OtherChildAllIterT otherIter = other.beginChildAll();
1604 for ( ; iter && otherIter; ++iter, ++otherIter) {
1605 op(iter, otherIter);
1613 template<
typename T, Index Log2Dim>
1614 template<
typename IterT,
typename VisitorOp>
1618 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
1619 *
this, otherIter, op, otherIsLHS);
1623 template<
typename T, Index Log2Dim>
1624 template<
typename IterT,
typename VisitorOp>
1628 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
1629 *
this, otherIter, op, otherIsLHS);
1633 template<
typename T, Index Log2Dim>
1637 typename ChildAllIterT,
1638 typename OtherChildAllIterT>
1641 VisitorOp& op,
bool otherIsLHS)
1643 if (!otherIter)
return;
1646 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1647 op(otherIter, iter);
1650 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1651 op(iter, otherIter);
1660 template<
typename T, Index Log2Dim>
1661 inline std::ostream&
1662 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
1664 for (
Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] <<
", ";
1679 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED