31 #ifndef OPENVDB_TREE_LEAFNODEBOOL_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_LEAFNODEBOOL_HAS_BEEN_INCLUDED
35 #include <boost/shared_ptr.hpp>
36 #include <boost/shared_array.hpp>
37 #include <boost/static_assert.hpp>
38 #include <openvdb/Types.h>
39 #include <openvdb/io/Compression.h>
40 #include <openvdb/util/NodeMasks.h>
53 template<Index Log2Dim>
58 typedef boost::shared_ptr<LeafNodeType>
Ptr;
63 static const Index LOG2DIM = Log2Dim;
64 static const Index TOTAL = Log2Dim;
65 static const Index DIM = 1 << TOTAL;
66 static const Index NUM_VALUES = 1 << 3 * Log2Dim;
67 static const Index NUM_VOXELS = NUM_VALUES;
68 static const Index SIZE = NUM_VALUES;
73 template<
typename ValueType>
82 Buffer(
const Buffer& other): mData(other.mData) {}
84 void fill(
bool val) { mData.set(val); }
85 Buffer&
operator=(
const Buffer& b) {
if (&b !=
this) { mData = b.mData; }
return *
this; }
87 const bool& getValue(
Index i)
const
90 return mData.isOn(i) ? LeafNode::sOn : LeafNode::sOff;
94 bool operator==(
const Buffer& other)
const {
return mData == other.mData; }
95 bool operator!=(
const Buffer& other)
const {
return mData != other.mData; }
97 void setValue(
Index i,
bool val) { assert(i < SIZE); mData.set(i, val); }
99 void swap(Buffer& other) {
if (&other !=
this) std::swap(mData, other.mData); }
105 friend class ::TestLeaf;
120 explicit LeafNode(
const Coord& xyz,
bool value =
false,
bool active =
false);
126 template<
typename ValueType>
131 template<
typename ValueType>
134 template<
typename ValueType>
165 bool isEmpty()
const {
return mValueMask.isOff(); }
167 bool isDense()
const {
return mValueMask.isOn(); }
174 void evalActiveVoxelBoundingBox(
CoordBBox& bbox)
const;
194 std::string str()
const;
198 template<
typename OtherType, Index OtherLog2Dim>
210 void swap(Buffer& other) { mBuffer.swap(other); }
211 const Buffer&
buffer()
const {
return mBuffer; }
218 void readTopology(std::istream&,
bool fromHalf =
false);
220 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
223 void readBuffers(std::istream&,
bool fromHalf =
false);
225 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
231 const bool& getValue(
const Coord& xyz)
const;
233 const bool& getValue(
Index offset)
const;
238 bool probeValue(
const Coord& xyz,
bool& val)
const;
244 void setActiveState(
const Coord& xyz,
bool on);
251 void setValueOff(
const Coord& xyz,
bool val);
258 void setValueOn(
const Coord& xyz,
bool val);
264 void setValueOnMin(
const Coord& xyz,
bool val);
267 void setValueOnMax(
const Coord& xyz,
bool val);
270 void setValueOnSum(
const Coord& xyz,
bool val);
275 this->setValueOnly(LeafNode::coord2offset(xyz), val);
279 void setValueOnly(
Index offset,
bool val) { assert(offset<SIZE); mBuffer.setValue(offset,val); }
282 void addValue(
bool val);
284 void scaleValue(
bool scale);
292 bool isValueOn(
const Coord& xyz)
const {
return mValueMask.isOn(this->coord2offset(xyz)); }
294 bool isValueOn(
Index offset)
const { assert(offset < SIZE);
return mValueMask.isOn(offset); }
301 void fill(
const CoordBBox& bbox,
bool value,
bool active =
true);
304 void fill(
const bool& value);
307 void fill(
const bool& value,
bool active);
311 template<
typename AccessorT>
316 template<
typename AccessorT>
321 template<
typename AccessorT>
327 template<
typename AccessorT>
332 template<
typename AccessorT>
333 void setValueOffAndCache(
const Coord& xyz,
bool value, AccessorT&)
335 this->setValueOff(xyz, value);
341 template<
typename AccessorT>
342 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&)
344 this->setActiveState(xyz, on);
350 template<
typename AccessorT>
351 bool probeValueAndCache(
const Coord& xyz,
bool& val, AccessorT&)
const
353 return this->probeValue(xyz, val);
358 template<
typename AccessorT>
364 const bool&
getFirstValue()
const {
if (mValueMask.isOn(0))
return sOn;
else return sOff; }
368 const bool&
getLastValue()
const {
if (mValueMask.isOn(SIZE-1))
return sOn;
else return sOff; }
373 bool isConstant(
bool& constValue,
bool& state,
bool tolerance = 0)
const;
377 void resetBackground(
bool oldBackground,
bool newBackground);
379 void negate() { mBuffer.mData.toggle(); }
389 template<
typename OtherType>
400 template<
typename OtherType>
403 template<
typename CombineOp>
405 template<
typename CombineOp>
406 void combine(
bool,
bool valueIsActive, CombineOp& op);
408 template<
typename CombineOp>
409 void combine2(
const LeafNode& other,
bool,
bool valueIsActive, CombineOp&);
410 template<
typename CombineOp>
411 void combine2(
bool,
const LeafNode& other,
bool valueIsActive, CombineOp&);
412 template<
typename CombineOp>
419 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
421 template<
typename VisitorOp>
void visit(VisitorOp&);
422 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
424 template<
typename OtherLeafNodeType,
typename VisitorOp>
425 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
426 template<
typename OtherLeafNodeType,
typename VisitorOp>
427 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
428 template<
typename IterT,
typename VisitorOp>
429 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
430 template<
typename IterT,
typename VisitorOp>
431 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
438 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
446 template<
typename AccessorT>
449 template<
typename AccessorT>
455 template<
typename AccessorT>
469 template<
typename MaskIterT,
typename NodeT,
typename ValueT>
473 public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
480 const bool&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
481 const bool&
getValue()
const {
return this->getItem(this->pos()); }
484 void setItem(
Index pos,
bool value)
const { this->parent().setValueOnly(pos, value); }
486 void setValue(
bool value)
const { this->setItem(this->pos(), value); }
490 template<
typename MaskIterT,
typename NodeT>
496 MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
499 template<
typename NodeT,
typename ValueT>
501 MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, void, ValueT>
511 value = this->parent().getValue(pos);
520 void unsetItem(
Index pos,
const ValueT& val)
const {this->parent().setValueOnly(pos, val);}
525 typedef ValueIter<MaskOnIter, const LeafNode, const bool>
ValueOnCIter;
600 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
601 static inline void doVisit(NodeT&, VisitorOp&);
603 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
604 typename ChildAllIterT,
typename OtherChildAllIterT>
605 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
607 template<
typename NodeT,
typename VisitorOp,
608 typename ChildAllIterT,
typename OtherChildAllIterT>
609 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
660 template<Index Log2Dim>
667 template<Index Log2Dim>
672 mOrigin(xyz & (~(DIM - 1)))
677 template<Index Log2Dim>
678 template<
typename ValueT>
681 mValueMask(other.getValueMask()),
682 mBuffer(other.getValueMask()),
683 mOrigin(other.getOrigin())
688 template<Index Log2Dim>
689 template<
typename ValueT>
693 mValueMask(other.getValueMask()),
694 mBuffer(other.getValueMask()),
695 mOrigin(other.getOrigin())
697 if (offValue) {
if (!onValue)
mBuffer.mData.toggle();
else mBuffer.mData.setOn(); }
701 template<Index Log2Dim>
702 template<
typename ValueT>
706 mValueMask(other.getValueMask()),
708 mOrigin(other.getOrigin())
713 template<Index Log2Dim>
716 mValueMask(other.mValueMask),
717 mBuffer(other.mBuffer),
718 mOrigin(other.mOrigin)
723 template<Index Log2Dim>
733 template<Index Log2Dim>
741 template<Index Log2Dim>
756 template<Index Log2Dim>
757 template<
typename OtherType, Index OtherLog2Dim>
766 template<Index Log2Dim>
770 std::ostringstream ostr;
771 ostr <<
"LeafNode @" <<
mOrigin <<
": ";
780 template<Index Log2Dim>
784 assert ((xyz[0] &
DIM-1u) <
DIM && (xyz[1] &
DIM-1u) <
DIM && (xyz[2] &
DIM-1u) <
DIM);
785 return ((xyz[0] &
DIM-1u) << 2*Log2Dim) + ((xyz[1] &
DIM-1u) << Log2Dim) + (xyz[2] &
DIM-1u);
789 template<Index Log2Dim>
793 assert(n < (1 << 3*Log2Dim));
795 xyz.
setX(n >> 2*Log2Dim);
796 n &= ((1 << 2*Log2Dim) - 1);
797 xyz.
setY(n >> Log2Dim);
798 xyz.
setZ(n & ((1 << Log2Dim) - 1));
803 template<Index Log2Dim>
814 template<Index Log2Dim>
822 template<Index Log2Dim>
830 template<Index Log2Dim>
846 int8_t numBuffers = 0;
847 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
851 boost::shared_array<bool> buf(
new bool[
SIZE]);
852 io::readData<bool>(is, buf.get(),
SIZE,
true);
857 if (buf[i])
mBuffer.mData.setOn(i);
860 if (numBuffers > 1) {
863 for (
int i = 1; i < numBuffers; ++i) {
864 io::readData<bool>(is, buf.get(),
SIZE,
true);
871 template<Index Log2Dim>
887 template<Index Log2Dim>
895 template<Index Log2Dim>
906 template<Index Log2Dim>
913 if (!tolerance && !(
mBuffer.mData.isOn() ||
mBuffer.mData.isOff()))
return false;
916 constValue =
mBuffer.mData.isOn();
924 template<Index Log2Dim>
929 if (
mBuffer.mData.isOn(this->coord2offset(xyz)))
return sOn;
else return sOff;
933 template<Index Log2Dim>
937 assert(offset <
SIZE);
939 if (
mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
943 template<Index Log2Dim>
948 val =
mBuffer.mData.isOn(offset);
953 template<Index Log2Dim>
959 mBuffer.mData.set(offset, val);
963 template<Index Log2Dim>
971 template<Index Log2Dim>
977 mBuffer.mData.set(offset, val);
981 template<Index Log2Dim>
991 template<Index Log2Dim>
1001 template<Index Log2Dim>
1011 template<Index Log2Dim>
1019 template<Index Log2Dim>
1030 template<Index Log2Dim>
1034 if (newBackground != oldBackground) {
1043 template<Index Log2Dim>
1048 const Index n = iter.pos();
1056 template<Index Log2Dim>
1057 template<
typename OtherType>
1064 template<Index Log2Dim>
1065 template<
typename OtherType>
1073 template<Index Log2Dim>
1078 const Index offsetX = (x&
DIM-1u)<<2*Log2Dim;
1080 const Index offsetXY = offsetX + ((y&
DIM-1u)<< Log2Dim);
1082 const Index offset = offsetXY + (z&
DIM-1u);
1084 mBuffer.mData.set(offset, value);
1090 template<Index Log2Dim>
1097 template<Index Log2Dim>
1108 template<Index Log2Dim>
1109 template<
typename CombineOp>
1115 bool result =
false, aVal =
mBuffer.mData.isOn(i), bVal = other.
mBuffer.mData.isOn(i);
1120 .setResultRef(result));
1127 template<Index Log2Dim>
1128 template<
typename CombineOp>
1133 args.
setBRef(value).setBIsActive(valueIsActive);
1135 bool result =
false, aVal =
mBuffer.mData.isOn(i);
1138 .setResultRef(result));
1148 template<Index Log2Dim>
1149 template<
typename CombineOp>
1152 bool valueIsActive, CombineOp& op)
1155 args.
setBRef(value).setBIsActive(valueIsActive);
1157 bool result =
false, aVal = other.
mBuffer.mData.isOn(i);
1160 .setResultRef(result));
1167 template<Index Log2Dim>
1168 template<
typename CombineOp>
1171 bool valueIsActive, CombineOp& op)
1174 args.
setARef(value).setAIsActive(valueIsActive);
1176 bool result =
false, bVal = other.
mBuffer.mData.isOn(i);
1179 .setResultRef(result));
1186 template<Index Log2Dim>
1187 template<
typename CombineOp>
1196 bool result =
false, b0Val = b0.
mBuffer.mData.isOn(i), b1Val = b1.
mBuffer.mData.isOn(i);
1201 .setResultRef(result));
1210 template<Index Log2Dim>
1211 template<
typename BBoxOp>
1215 if (op.template descent<LEVEL>()) {
1233 template<Index Log2Dim>
1234 template<
typename VisitorOp>
1238 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1242 template<Index Log2Dim>
1243 template<
typename VisitorOp>
1247 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1251 template<Index Log2Dim>
1252 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1256 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1265 template<Index Log2Dim>
1266 template<
typename OtherLeafNodeType,
typename VisitorOp>
1271 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1275 template<Index Log2Dim>
1276 template<
typename OtherLeafNodeType,
typename VisitorOp>
1281 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1285 template<Index Log2Dim>
1288 typename OtherNodeT,
1290 typename ChildAllIterT,
1291 typename OtherChildAllIterT>
1296 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1297 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1299 ChildAllIterT iter =
self.beginChildAll();
1300 OtherChildAllIterT otherIter = other.beginChildAll();
1302 for ( ; iter && otherIter; ++iter, ++otherIter) {
1303 op(iter, otherIter);
1311 template<Index Log2Dim>
1312 template<
typename IterT,
typename VisitorOp>
1316 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(*
this, otherIter, op, otherIsLHS);
1320 template<Index Log2Dim>
1321 template<
typename IterT,
typename VisitorOp>
1325 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(*
this, otherIter, op, otherIsLHS);
1329 template<Index Log2Dim>
1333 typename ChildAllIterT,
1334 typename OtherChildAllIterT>
1337 VisitorOp& op,
bool otherIsLHS)
1339 if (!otherIter)
return;
1342 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1343 op(otherIter, iter);
1346 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1347 op(iter, otherIter);
1356 #endif // OPENVDB_TREE_LEAFNODEBOOL_HAS_BEEN_INCLUDED