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; }
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;
183 const Coord& origin()
const {
return mOrigin; }
199 std::string str()
const;
203 template<
typename OtherType, Index OtherLog2Dim>
215 void swap(Buffer& other) { mBuffer.swap(other); }
216 const Buffer&
buffer()
const {
return mBuffer; }
223 void readTopology(std::istream&,
bool fromHalf =
false);
225 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
228 void readBuffers(std::istream&,
bool fromHalf =
false);
230 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
236 const bool& getValue(
const Coord& xyz)
const;
238 const bool& getValue(
Index offset)
const;
243 bool probeValue(
const Coord& xyz,
bool& val)
const;
249 void setActiveState(
const Coord& xyz,
bool on);
256 void setValueOff(
const Coord& xyz,
bool val);
263 void setValueOn(
const Coord& xyz,
bool val);
269 void setValueOnMin(
const Coord& xyz,
bool val);
272 void setValueOnMax(
const Coord& xyz,
bool val);
275 void setValueOnSum(
const Coord& xyz,
bool val);
280 this->setValueOnly(LeafNode::coord2offset(xyz), val);
284 void setValueOnly(
Index offset,
bool val) { assert(offset<SIZE); mBuffer.setValue(offset,val); }
297 bool isValueOn(
const Coord& xyz)
const {
return mValueMask.isOn(this->coord2offset(xyz)); }
299 bool isValueOn(
Index offset)
const { assert(offset < SIZE);
return mValueMask.isOn(offset); }
306 void fill(
const CoordBBox& bbox,
bool value,
bool active =
true);
309 void fill(
const bool& value);
312 void fill(
const bool& value,
bool active);
325 template<
typename DenseT>
344 template<
typename DenseT>
349 template<
typename AccessorT>
354 template<
typename AccessorT>
359 template<
typename AccessorT>
365 template<
typename AccessorT>
370 template<
typename AccessorT>
373 this->setValueOff(xyz, value);
379 template<
typename AccessorT>
382 this->setActiveState(xyz, on);
388 template<
typename AccessorT>
391 return this->probeValue(xyz, val);
396 template<
typename AccessorT>
402 const bool&
getFirstValue()
const {
if (mValueMask.isOn(0))
return sOn;
else return sOff; }
406 const bool&
getLastValue()
const {
if (mValueMask.isOn(SIZE-1))
return sOn;
else return sOff; }
411 bool isConstant(
bool& constValue,
bool& state,
bool tolerance = 0)
const;
415 void resetBackground(
bool oldBackground,
bool newBackground);
417 void negate() { mBuffer.mData.toggle(); }
429 template<
typename OtherType>
443 template<
typename OtherType>
457 template<
typename OtherType>
460 template<
typename CombineOp>
462 template<
typename CombineOp>
463 void combine(
bool,
bool valueIsActive, CombineOp& op);
465 template<
typename CombineOp>
466 void combine2(
const LeafNode& other,
bool,
bool valueIsActive, CombineOp&);
467 template<
typename CombineOp>
468 void combine2(
bool,
const LeafNode& other,
bool valueIsActive, CombineOp&);
469 template<
typename CombineOp>
476 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
478 template<
typename VisitorOp>
void visit(VisitorOp&);
479 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
481 template<
typename OtherLeafNodeType,
typename VisitorOp>
482 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
483 template<
typename OtherLeafNodeType,
typename VisitorOp>
484 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
485 template<
typename IterT,
typename VisitorOp>
486 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
487 template<
typename IterT,
typename VisitorOp>
488 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
491 void signedFloodFill(
bool) {}
495 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
499 template<
typename AccessorT>
501 template<
typename NodeT>
503 template<
typename NodeT>
505 template<
typename NodeT>
508 template<
typename AccessorT>
515 template<
typename AccessorT>
518 template<
typename AccessorT>
520 template<
typename NodeT,
typename AccessorT>
524 if (!(boost::is_same<NodeT,LeafNode>::value))
return NULL;
525 return reinterpret_cast<NodeT*
>(
this);
530 const LeafNode* probeLeaf(
const Coord&)
const {
return this; }
532 template<
typename AccessorT>
535 template<
typename AccessorT>
537 template<
typename NodeT,
typename AccessorT>
541 if (!(boost::is_same<NodeT,LeafNode>::value))
return NULL;
542 return reinterpret_cast<const NodeT*
>(
this);
546 template<
typename NodeT>
548 static bool hasNodeType() {
return (boost::is_same<NodeT,LeafNode>::value); }
560 template<
typename MaskIterT,
typename NodeT,
typename ValueT>
564 public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
571 const bool&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
572 const bool&
getValue()
const {
return this->getItem(this->pos()); }
575 void setItem(
Index pos,
bool value)
const { this->parent().setValueOnly(pos, value); }
577 void setValue(
bool value)
const { this->setItem(this->pos(), value); }
581 template<
typename MaskIterT,
typename NodeT>
587 MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
590 template<
typename NodeT,
typename ValueT>
592 MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, void, ValueT>
602 value = this->parent().getValue(pos);
611 void unsetItem(
Index pos,
const ValueT& val)
const {this->parent().setValueOnly(pos, val);}
616 typedef ValueIter<MaskOnIter, const LeafNode, const bool>
ValueOnCIter;
691 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
692 static inline void doVisit(NodeT&, VisitorOp&);
694 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
695 typename ChildAllIterT,
typename OtherChildAllIterT>
696 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
698 template<
typename NodeT,
typename VisitorOp,
699 typename ChildAllIterT,
typename OtherChildAllIterT>
700 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
751 template<Index Log2Dim>
758 template<Index Log2Dim>
763 mOrigin(xyz & (~(DIM - 1)))
768 template<Index Log2Dim>
769 template<
typename ValueT>
772 mValueMask(other.getValueMask()),
773 mBuffer(other.getValueMask()),
774 mOrigin(other.getOrigin())
779 template<Index Log2Dim>
780 template<
typename ValueT>
784 mValueMask(other.getValueMask()),
785 mBuffer(other.getValueMask()),
786 mOrigin(other.getOrigin())
788 if (offValue) {
if (!onValue)
mBuffer.mData.toggle();
else mBuffer.mData.setOn(); }
792 template<Index Log2Dim>
793 template<
typename ValueT>
797 mValueMask(other.getValueMask()),
799 mOrigin(other.getOrigin())
804 template<Index Log2Dim>
807 mValueMask(other.mValueMask),
808 mBuffer(other.mBuffer),
809 mOrigin(other.mOrigin)
814 template<Index Log2Dim>
824 template<Index Log2Dim>
832 template<Index Log2Dim>
847 template<Index Log2Dim>
848 template<
typename OtherType, Index OtherLog2Dim>
857 template<Index Log2Dim>
861 std::ostringstream ostr;
862 ostr <<
"LeafNode @" <<
mOrigin <<
": ";
871 template<Index Log2Dim>
875 assert ((xyz[0] &
DIM-1u) <
DIM && (xyz[1] &
DIM-1u) <
DIM && (xyz[2] &
DIM-1u) <
DIM);
876 return ((xyz[0] &
DIM-1u) << 2*Log2Dim) + ((xyz[1] &
DIM-1u) << Log2Dim) + (xyz[2] &
DIM-1u);
880 template<Index Log2Dim>
884 assert(n < (1 << 3*Log2Dim));
886 xyz.
setX(n >> 2*Log2Dim);
887 n &= ((1 << 2*Log2Dim) - 1);
888 xyz.
setY(n >> Log2Dim);
889 xyz.
setZ(n & ((1 << Log2Dim) - 1));
894 template<Index Log2Dim>
905 template<Index Log2Dim>
913 template<Index Log2Dim>
921 template<Index Log2Dim>
937 int8_t numBuffers = 0;
938 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
942 boost::shared_array<bool> buf(
new bool[
SIZE]);
943 io::readData<bool>(is, buf.get(),
SIZE,
true);
948 if (buf[i])
mBuffer.mData.setOn(i);
951 if (numBuffers > 1) {
954 for (
int i = 1; i < numBuffers; ++i) {
955 io::readData<bool>(is, buf.get(),
SIZE,
true);
962 template<Index Log2Dim>
978 template<Index Log2Dim>
986 template<Index Log2Dim>
997 template<Index Log2Dim>
1004 if (!tolerance && !(
mBuffer.mData.isOn() ||
mBuffer.mData.isOff()))
return false;
1007 constValue =
mBuffer.mData.isOn();
1015 template<Index Log2Dim>
1020 if (
mBuffer.mData.isOn(this->coord2offset(xyz)))
return sOn;
else return sOff;
1024 template<Index Log2Dim>
1028 assert(offset <
SIZE);
1030 if (
mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
1034 template<Index Log2Dim>
1039 val =
mBuffer.mData.isOn(offset);
1044 template<Index Log2Dim>
1050 mBuffer.mData.set(offset, val);
1054 template<Index Log2Dim>
1062 template<Index Log2Dim>
1068 mBuffer.mData.set(offset, val);
1072 template<Index Log2Dim>
1082 template<Index Log2Dim>
1092 template<Index Log2Dim>
1102 template<Index Log2Dim>
1110 template<Index Log2Dim>
1121 template<Index Log2Dim>
1125 if (newBackground != oldBackground) {
1134 template<Index Log2Dim>
1139 const Index n = iter.pos();
1147 template<Index Log2Dim>
1148 template<
typename OtherType>
1155 template<Index Log2Dim>
1156 template<
typename OtherType>
1164 template<Index Log2Dim>
1165 template<
typename OtherType>
1173 template<Index Log2Dim>
1178 const Index offsetX = (x&
DIM-1u)<<2*Log2Dim;
1180 const Index offsetXY = offsetX + ((y&
DIM-1u)<< Log2Dim);
1182 const Index offset = offsetXY + (z&
DIM-1u);
1184 mBuffer.mData.set(offset, value);
1190 template<Index Log2Dim>
1197 template<Index Log2Dim>
1209 template<Index Log2Dim>
1210 template<
typename DenseT>
1214 const size_t xStride = dense.xStride(), yStride = dense.yStride();
1215 const Coord&
min = dense.bbox().min();
1216 bool* t0 = dense.data() + bbox.
min()[2]-min[2];
1218 for (
Int32 x = bbox.
min()[0], ex=bbox.
max()[0]+1; x<ex; ++x) {
1219 bool* t1 = t0 + xStride*(x-min[0]);
1221 for (
Int32 y = bbox.
min()[1], ey=bbox.
max()[1]+1; y<ey; ++y) {
1222 bool* t2 = t1 + yStride*(y-min[1]);
1224 for (
Int32 z = bbox.
min()[2], ez=bbox.
max()[2]+1; z<ez ; ++z) {
1225 *t2++ =
mBuffer.mData.isOn(n2++);
1232 template<Index Log2Dim>
1233 template<
typename DenseT>
1238 const size_t xStride = dense.xStride(), yStride = dense.yStride();
1239 const Coord&
min = dense.bbox().min();
1240 const bool* s0 = dense.data() + bbox.
min()[2]-min[2];
1242 for (
Int32 x = bbox.
min()[0], ex=bbox.
max()[0]+1; x<ex; ++x) {
1243 const bool* s1 = s0 + xStride*(x-min[0]);
1245 for (
Int32 y = bbox.
min()[1], ey=bbox.
max()[1]+1; y<ey; ++y) {
1246 const bool* s2 = s1 + yStride*(y-min[1]);
1248 for (
Int32 z = bbox.
min()[2], ez=bbox.
max()[2]+1; z<ez ; ++z, ++n2, ++s2) {
1250 if (tolerance || background == *s2) {
1252 mBuffer.mData.set(n2, background);
1266 template<Index Log2Dim>
1267 template<
typename CombineOp>
1273 bool result =
false, aVal =
mBuffer.mData.isOn(i), bVal = other.
mBuffer.mData.isOn(i);
1278 .setResultRef(result));
1285 template<Index Log2Dim>
1286 template<
typename CombineOp>
1291 args.
setBRef(value).setBIsActive(valueIsActive);
1293 bool result =
false, aVal =
mBuffer.mData.isOn(i);
1296 .setResultRef(result));
1306 template<Index Log2Dim>
1307 template<
typename CombineOp>
1310 bool valueIsActive, CombineOp& op)
1313 args.
setBRef(value).setBIsActive(valueIsActive);
1315 bool result =
false, aVal = other.
mBuffer.mData.isOn(i);
1318 .setResultRef(result));
1325 template<Index Log2Dim>
1326 template<
typename CombineOp>
1329 bool valueIsActive, CombineOp& op)
1332 args.
setARef(value).setAIsActive(valueIsActive);
1334 bool result =
false, bVal = other.
mBuffer.mData.isOn(i);
1337 .setResultRef(result));
1344 template<Index Log2Dim>
1345 template<
typename CombineOp>
1354 bool result =
false, b0Val = b0.
mBuffer.mData.isOn(i), b1Val = b1.
mBuffer.mData.isOn(i);
1359 .setResultRef(result));
1368 template<Index Log2Dim>
1369 template<
typename BBoxOp>
1373 if (op.template descent<LEVEL>()) {
1391 template<Index Log2Dim>
1392 template<
typename VisitorOp>
1396 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1400 template<Index Log2Dim>
1401 template<
typename VisitorOp>
1405 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1409 template<Index Log2Dim>
1410 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1414 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1423 template<Index Log2Dim>
1424 template<
typename OtherLeafNodeType,
typename VisitorOp>
1429 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1433 template<Index Log2Dim>
1434 template<
typename OtherLeafNodeType,
typename VisitorOp>
1439 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1443 template<Index Log2Dim>
1446 typename OtherNodeT,
1448 typename ChildAllIterT,
1449 typename OtherChildAllIterT>
1454 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1455 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1457 ChildAllIterT iter =
self.beginChildAll();
1458 OtherChildAllIterT otherIter = other.beginChildAll();
1460 for ( ; iter && otherIter; ++iter, ++otherIter) {
1461 op(iter, otherIter);
1469 template<Index Log2Dim>
1470 template<
typename IterT,
typename VisitorOp>
1474 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(*
this, otherIter, op, otherIsLHS);
1478 template<Index Log2Dim>
1479 template<
typename IterT,
typename VisitorOp>
1483 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(*
this, otherIter, op, otherIsLHS);
1487 template<Index Log2Dim>
1491 typename ChildAllIterT,
1492 typename OtherChildAllIterT>
1495 VisitorOp& op,
bool otherIsLHS)
1497 if (!otherIter)
return;
1500 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1501 op(otherIter, iter);
1504 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1505 op(iter, otherIter);
1514 #endif // OPENVDB_TREE_LEAFNODEBOOL_HAS_BEEN_INCLUDED