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>
50 template<
typename>
class TestLeafIO;
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 (size--) *target++ = val;
118 while (size--) *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;
237 static void offset2coord(
Index n,
Coord &xyz);
242 std::string str()
const;
246 template<
typename OtherType, Index OtherLog2Dim>
262 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
267 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
274 ValueT&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
275 ValueT&
getValue()
const {
return this->parent().getValue(this->pos()); }
278 void setItem(
Index pos,
const ValueT& value)
const
280 this->parent().setValueOnly(pos, value);
283 void setValue(
const ValueT& value)
const
285 this->parent().setValueOnly(this->pos(), value);
290 template<
typename MaskIterT,
typename NodeT,
typename TagT>
292 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
299 template<
typename NodeT,
typename ValueT,
typename TagT>
301 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
311 value = this->parent().getValue(pos);
320 void unsetItem(
Index pos,
const ValueT& value)
const
322 this->parent().setValueOnly(pos, value);
397 void readTopology(std::istream& is,
bool fromHalf =
false);
401 void writeTopology(std::ostream& os,
bool toHalf =
false)
const;
406 void readBuffers(std::istream& is,
bool fromHalf =
false);
410 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
412 size_t streamingSize(
bool toHalf =
false)
const;
418 const ValueType& getValue(
const Coord& xyz)
const;
420 const ValueType& getValue(
Index offset)
const;
425 bool probeValue(
const Coord& xyz, ValueType& val)
const;
429 bool probeValue(
Index offset, ValueType& val)
const;
435 void setActiveState(
const Coord& xyz,
bool on);
443 void setValueOff(
const Coord& xyz,
const ValueType& val);
445 void setValueOff(
Index offset,
const ValueType& val);
453 this->setValueOn(LeafNode::coord2offset(xyz), val);
459 mBuffer[offset] = val;
460 mValueMask.setOn(offset);
466 this->setValueOnMin(LeafNode::coord2offset(xyz), val);
471 mBuffer[offset] =
std::min(val, mBuffer[offset]);
472 mValueMask.setOn(offset);
478 this->setValueOnMax(LeafNode::coord2offset(xyz), val);
483 mBuffer[offset] =
std::max(val, mBuffer[offset]);
484 mValueMask.setOn(offset);
490 this->setValueOnSum(LeafNode::coord2offset(xyz), val);
495 mBuffer[offset] += val;
496 mValueMask.setOn(offset);
502 this->setValueOnly(LeafNode::coord2offset(xyz), val);
509 assert(offset<SIZE); mBuffer[offset] = val;
513 void addValue(
const ValueType& val);
515 void scaleValue(
const ValueType&
scale);
532 void fill(
const CoordBBox& bbox,
const ValueType&,
bool active =
true);
535 void fill(
const ValueType& value);
538 void fill(
const ValueType& value,
bool active);
542 template<
typename AccessorT>
545 return this->getValue(xyz);
550 template<
typename AccessorT>
555 template<
typename AccessorT>
558 this->setValueOn(xyz, val);
564 template<
typename AccessorT>
567 this->setValueOnly(xyz, val);
574 template<
typename AccessorT>
577 this->setValueOnSum(xyz, val);
582 template<
typename AccessorT>
585 this->setValueOff(xyz, value);
591 template<
typename AccessorT>
592 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&)
594 this->setActiveState(xyz, on);
600 template<
typename AccessorT>
603 return this->probeValue(xyz, val);
609 template<
typename AccessorT>
610 const ValueType& getValue(
const Coord& xyz,
bool& state,
int& level, AccessorT&)
const
612 const Index offset = this->coord2offset(xyz);
613 state = mValueMask.isOn(offset);
615 return mBuffer[offset];
620 template<
typename AccessorT>
632 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
643 void signedFloodFill(
const ValueType& background);
651 void signedFloodFill(
const ValueType& outside,
const ValueType& inside);
658 LeafNode::merge(other);
666 template<
typename OtherType>
677 template<
typename OtherType>
680 template<
typename CombineOp>
682 template<
typename CombineOp>
683 void combine(
const ValueType& value,
bool valueIsActive, CombineOp& op);
685 template<
typename CombineOp>
686 void combine2(
const LeafNode& other,
const ValueType&,
bool valueIsActive, CombineOp&);
687 template<
typename CombineOp>
688 void combine2(
const ValueType&,
const LeafNode& other,
bool valueIsActive, CombineOp&);
689 template<
typename CombineOp>
697 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
699 template<
typename VisitorOp>
void visit(VisitorOp&);
700 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
702 template<
typename OtherLeafNodeType,
typename VisitorOp>
703 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
704 template<
typename OtherLeafNodeType,
typename VisitorOp>
705 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
706 template<
typename IterT,
typename VisitorOp>
707 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
708 template<
typename IterT,
typename VisitorOp>
709 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
713 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
720 template<
typename AccessorT>
723 template<
typename AccessorT>
729 template<
typename AccessorT>
736 bool isConstant(ValueType& constValue,
bool& state,
737 const ValueType& tolerance = zeroVal<ValueType>())
const;
742 friend class ::TestLeaf;
743 template<
typename>
friend class ::TestLeafIO;
789 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
790 static inline void doVisit(NodeT&, VisitorOp&);
792 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
793 typename ChildAllIterT,
typename OtherChildAllIterT>
794 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
796 template<
typename NodeT,
typename VisitorOp,
797 typename ChildAllIterT,
typename OtherChildAllIterT>
798 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
810 template<
typename T, Index Log2Dim>
812 LeafNode<T, Log2Dim>::LeafNode():
819 template<
typename T, Index Log2Dim>
824 mOrigin(xyz & (~(DIM - 1)))
828 template<
typename T, Index Log2Dim>
829 template<
typename OtherValueType>
834 mValueMask(other.mValueMask),
835 mOrigin(other.mOrigin)
839 template<
typename T, Index Log2Dim>
840 template<
typename OtherValueType>
844 mValueMask(other.mValueMask),
845 mOrigin(other.mOrigin)
852 template<
typename T, Index Log2Dim>
855 mBuffer(other.mBuffer),
856 mValueMask(other.mValueMask),
857 mOrigin(other.mOrigin)
862 template<
typename T, Index Log2Dim>
869 template<
typename T, Index Log2Dim>
873 std::ostringstream ostr;
874 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
882 template<
typename T, Index Log2Dim>
886 assert ((xyz[0]&DIM-1u)<DIM && (xyz[1]&DIM-1u)<DIM && (xyz[2]&DIM-1u)<DIM);
887 return ((xyz[0]&DIM-1u)<<2*Log2Dim)
888 + ((xyz[1]&DIM-1u)<< Log2Dim)
893 template<
typename T, Index Log2Dim>
897 assert(n<(1<< 3*Log2Dim));
898 xyz.
setX(n >> 2*Log2Dim);
899 n &= ((1<<2*Log2Dim)-1);
900 xyz.
setY(n >> Log2Dim);
901 xyz.
setZ(n & ((1<<Log2Dim)-1));
905 template<
typename T, Index Log2Dim>
910 this->offset2coord(n, local);
911 return Coord(local + this->getOrigin());
918 template<
typename ValueT, Index Log2Dim>
925 template<
typename ValueT, Index Log2Dim>
929 assert(offset < SIZE);
930 return mBuffer[offset];
934 template<
typename T, Index Log2Dim>
941 template<
typename T, Index Log2Dim>
945 assert(offset < SIZE);
946 val = mBuffer[offset];
947 return mValueMask.isOn(offset);
951 template<
typename T, Index Log2Dim>
958 template<
typename T, Index Log2Dim>
962 assert(offset < SIZE);
963 mBuffer[offset] = val;
964 mValueMask.setOff(offset);
968 template<
typename T, Index Log2Dim>
972 mValueMask.set(this->coord2offset(xyz), on);
976 template<
typename T, Index Log2Dim>
981 mBuffer[iter.pos()] += val;
986 template<
typename T, Index Log2Dim>
991 mBuffer[iter.pos()] *=
scale;
999 template<
typename T, Index Log2Dim>
1004 const Index offsetX = (x&DIM-1u)<<2*Log2Dim;
1006 const Index offsetXY = offsetX + ((y&DIM-1u)<< Log2Dim);
1008 const Index offset = offsetXY + (z&DIM-1u);
1009 mBuffer[offset] = value;
1010 mValueMask.set(offset, active);
1016 template<
typename T, Index Log2Dim>
1020 mBuffer.fill(value);
1023 template<
typename T, Index Log2Dim>
1027 mBuffer.fill(value);
1028 mValueMask.set(active);
1035 template<
typename T, Index Log2Dim>
1039 mValueMask.load(is);
1043 template<
typename T, Index Log2Dim>
1047 mValueMask.save(os);
1054 template<
typename T, Index Log2Dim>
1059 mValueMask.load(is);
1061 int8_t numBuffers = 1;
1067 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1072 if (numBuffers > 1) {
1077 for (
int i = 1; i < numBuffers; ++i) {
1079 io::HalfReader<io::RealToHalf<T>::isReal, T>::read(is, temp.mData, SIZE, zipped);
1081 io::readData<T>(is, temp.mData, SIZE, zipped);
1088 template<
typename T, Index Log2Dim>
1093 mValueMask.save(os);
1103 template<
typename T, Index Log2Dim>
1107 return mOrigin == other.
mOrigin &&
1113 template<
typename T, Index Log2Dim>
1117 return mBuffer.memUsage() +
sizeof(mOrigin) + mValueMask.memUsage();
1121 template<
typename T, Index Log2Dim>
1125 const CoordBBox this_bbox = this->getNodeBoundingBox();
1128 }
else if (this->isDense()) {
1131 for (
ValueOnCIter iter=this->cbeginValueOn(); iter; ++iter) bbox.
expand(iter.getCoord());
1136 template<
typename T, Index Log2Dim>
1137 template<
typename OtherType, Index OtherLog2Dim>
1142 return (Log2Dim == OtherLog2Dim && mValueMask == other->
getValueMask());
1146 template<
typename T, Index Log2Dim>
1149 bool& state,
const ValueType& tolerance)
const
1151 if (!mValueMask.isOn() && !mValueMask.isOff())
return false;
1153 state = mValueMask.isOn();
1155 bool allEqual =
true;
1156 const T value = mBuffer[0];
1157 for (
Index i = 1; allEqual && i < SIZE; ++i) {
1161 if (allEqual) constValue = value;
1165 template<
typename T, Index Log2Dim>
1169 this->signedFloodFill(background,
negative(background));
1172 template<
typename T, Index Log2Dim>
1177 const Index first = mValueMask.findFirstOn();
1179 bool xInside =
math::isNegative(mBuffer[first]), yInside = xInside, zInside = xInside;
1180 for (
Index x = 0; x != (1 << Log2Dim); ++x) {
1181 const Index x00 = x << (2 * Log2Dim);
1182 if (mValueMask.isOn(x00)) {
1186 for (
Index y = 0; y != (1 << Log2Dim); ++y) {
1187 const Index xy0 = x00 + (y << Log2Dim);
1188 if (mValueMask.isOn(xy0)) {
1192 for (
Index z = 0; z != (1 << Log2Dim); ++z) {
1193 const Index xyz = xy0 + z;
1194 if (mValueMask.isOn(xyz)) {
1197 mBuffer[xyz] = zInside ? insideValue : outsideValue;
1208 template<
typename T, Index Log2Dim>
1215 for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1218 inactiveValue = newBackground;
1220 inactiveValue =
negative(newBackground);
1226 template<
typename T, Index Log2Dim>
1231 for (; iter; ++iter) {
1233 if (mValueMask.isOn(n))
continue;
1234 mBuffer[n] = other.
mBuffer[n];
1235 mValueMask.setOn(n);
1240 template<
typename T, Index Log2Dim>
1241 template<
typename OtherType>
1248 template<
typename T, Index Log2Dim>
1249 template<
typename OtherType>
1257 template<
typename T, Index Log2Dim>
1261 for (
Index i = 0; i < SIZE; ++i) {
1262 mBuffer[i] = -mBuffer[i];
1270 template<
typename T, Index Log2Dim>
1271 template<
typename CombineOp>
1276 for (
Index i = 0; i < SIZE; ++i) {
1278 .setAIsActive(mValueMask.isOn(i))
1281 .setResultRef(mBuffer[i]));
1287 template<
typename T, Index Log2Dim>
1288 template<
typename CombineOp>
1293 args.
setBRef(value).setBIsActive(valueIsActive);
1294 for (
Index i = 0; i < SIZE; ++i) {
1296 .setAIsActive(mValueMask.isOn(i))
1297 .setResultRef(mBuffer[i]));
1306 template<
typename T, Index Log2Dim>
1307 template<
typename CombineOp>
1310 bool valueIsActive, CombineOp& op)
1313 args.
setBRef(value).setBIsActive(valueIsActive);
1314 for (
Index i = 0; i < SIZE; ++i) {
1317 .setResultRef(mBuffer[i]));
1323 template<
typename T, Index Log2Dim>
1324 template<
typename CombineOp>
1327 bool valueIsActive, CombineOp& op)
1330 args.
setARef(value).setAIsActive(valueIsActive);
1331 for (
Index i = 0; i < SIZE; ++i) {
1334 .setResultRef(mBuffer[i]));
1340 template<
typename T, Index Log2Dim>
1341 template<
typename CombineOp>
1346 for (
Index i = 0; i < SIZE; ++i) {
1352 .setResultRef(mBuffer[i]));
1361 template<
typename T, Index Log2Dim>
1362 template<
typename BBoxOp>
1366 if (op.template descent<LEVEL>()) {
1376 op.operator()<LEVEL>(this->getNodeBoundingBox());
1378 op.template operator()<LEVEL>(this->getNodeBoundingBox());
1384 template<
typename T, Index Log2Dim>
1385 template<
typename VisitorOp>
1389 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1393 template<
typename T, Index Log2Dim>
1394 template<
typename VisitorOp>
1398 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1402 template<
typename T, Index Log2Dim>
1403 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1407 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1416 template<
typename T, Index Log2Dim>
1417 template<
typename OtherLeafNodeType,
typename VisitorOp>
1422 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1426 template<
typename T, Index Log2Dim>
1427 template<
typename OtherLeafNodeType,
typename VisitorOp>
1432 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1436 template<
typename T, Index Log2Dim>
1439 typename OtherNodeT,
1441 typename ChildAllIterT,
1442 typename OtherChildAllIterT>
1447 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1448 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1450 ChildAllIterT iter =
self.beginChildAll();
1451 OtherChildAllIterT otherIter = other.beginChildAll();
1453 for ( ; iter && otherIter; ++iter, ++otherIter) {
1454 op(iter, otherIter);
1462 template<
typename T, Index Log2Dim>
1463 template<
typename IterT,
typename VisitorOp>
1467 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
1468 *
this, otherIter, op, otherIsLHS);
1472 template<
typename T, Index Log2Dim>
1473 template<
typename IterT,
typename VisitorOp>
1477 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
1478 *
this, otherIter, op, otherIsLHS);
1482 template<
typename T, Index Log2Dim>
1486 typename ChildAllIterT,
1487 typename OtherChildAllIterT>
1490 VisitorOp& op,
bool otherIsLHS)
1492 if (!otherIter)
return;
1495 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1496 op(otherIter, iter);
1499 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1500 op(iter, otherIter);
1509 template<
typename T, Index Log2Dim>
1510 inline std::ostream&
1511 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
1513 for (
Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] <<
", ";
1528 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED