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); }
212 const Buffer&
buffer()
const {
return mBuffer; }
219 void readTopology(std::istream&,
bool fromHalf =
false);
221 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
224 void readBuffers(std::istream&,
bool fromHalf =
false);
226 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
232 const bool& getValue(
const Coord& xyz)
const;
234 const bool& getValue(
Index offset)
const;
239 bool probeValue(
const Coord& xyz,
bool& val)
const;
245 void setActiveState(
const Coord& xyz,
bool on);
252 void setValueOff(
const Coord& xyz,
bool val);
259 void setValueOn(
const Coord& xyz,
bool val);
265 void setValueOnMin(
const Coord& xyz,
bool val);
268 void setValueOnMax(
const Coord& xyz,
bool val);
271 void setValueOnSum(
const Coord& xyz,
bool val);
276 this->setValueOnly(LeafNode::coord2offset(xyz), val);
279 mBuffer.mData.set(this->coord2offset(xyz), val);
283 void setValueOnly(
Index offset,
bool val) { assert(offset<SIZE); mBuffer.setValue(offset,val); }
287 void addValue(
bool val);
289 void scaleValue(
bool scale);
304 bool isValueOn(
const Coord& xyz)
const {
return mValueMask.isOn(this->coord2offset(xyz)); }
306 bool isValueOn(
Index offset)
const { assert(offset < SIZE);
return mValueMask.isOn(offset); }
313 void fill(
const CoordBBox& bbox,
bool value,
bool active =
true);
316 void fill(
const bool& value);
319 void fill(
const bool& value,
bool active);
323 template<
typename AccessorT>
328 template<
typename AccessorT>
333 template<
typename AccessorT>
339 template<
typename AccessorT>
344 template<
typename AccessorT>
345 void setValueOffAndCache(
const Coord& xyz,
bool value, AccessorT&)
347 this->setValueOff(xyz, value);
353 template<
typename AccessorT>
354 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&)
356 this->setActiveState(xyz, on);
362 template<
typename AccessorT>
363 bool probeValueAndCache(
const Coord& xyz,
bool& val, AccessorT&)
const
365 return this->probeValue(xyz, val);
371 template<
typename AccessorT>
374 const Index offset = this->coord2offset(xyz);
375 state = mValueMask.isOn(offset);
378 if (mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
380 template<
typename ProbeType,
typename AccessorT>
383 const Index offset = this->coord2offset(xyz);
384 p.setState(mValueMask.isOn(offset));
387 if (mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
389 template<
bool State,
bool Level,
typename AccessorT>
392 const Index offset = this->coord2offset(xyz);
393 if (State) state = mValueMask.isOn(offset);
394 if (Level) level = LEVEL;
396 if (mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
400 template<
typename AccessorT>
404 template<
typename AccessorT>
410 const bool&
getFirstValue()
const {
if (mValueMask.isOn(0))
return sOn;
else return sOff; }
414 const bool&
getLastValue()
const {
if (mValueMask.isOn(SIZE-1))
return sOn;
else return sOff; }
419 bool isConstant(
bool& constValue,
bool& state,
bool tolerance = 0)
const;
423 void resetBackground(
bool oldBackground,
bool newBackground);
425 void negate() { mBuffer.mData.toggle(); }
435 template<
typename OtherType>
446 template<
typename OtherType>
449 template<
typename CombineOp>
451 template<
typename CombineOp>
452 void combine(
bool,
bool valueIsActive, CombineOp& op);
454 template<
typename CombineOp>
455 void combine2(
const LeafNode& other,
bool,
bool valueIsActive, CombineOp&);
456 template<
typename CombineOp>
457 void combine2(
bool,
const LeafNode& other,
bool valueIsActive, CombineOp&);
458 template<
typename CombineOp>
465 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
467 template<
typename VisitorOp>
void visit(VisitorOp&);
468 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
470 template<
typename OtherLeafNodeType,
typename VisitorOp>
471 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
472 template<
typename OtherLeafNodeType,
typename VisitorOp>
473 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
474 template<
typename IterT,
typename VisitorOp>
475 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
476 template<
typename IterT,
typename VisitorOp>
477 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
482 template<
typename PruneOp>
void pruneOp(PruneOp&) {}
490 template<
typename AccessorT>
493 template<
typename AccessorT>
499 template<
typename AccessorT>
513 template<
typename MaskIterT,
typename NodeT,
typename ValueT>
517 public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
524 const bool&
getItem(
Index pos)
const {
return this->parent().getValue(pos); }
525 const bool&
getValue()
const {
return this->getItem(this->pos()); }
528 void setItem(
Index pos,
bool value)
const { this->parent().setValueOnly(pos, value); }
530 void setValue(
bool value)
const { this->setItem(this->pos(), value); }
534 template<
typename MaskIterT,
typename NodeT>
540 MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
543 template<
typename NodeT,
typename ValueT>
545 MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, void, ValueT>
555 value = this->parent().getValue(pos);
564 void unsetItem(
Index pos,
const ValueT& val)
const {this->parent().setValueOnly(pos, val);}
569 typedef ValueIter<MaskOnIter, const LeafNode, const bool>
ValueOnCIter;
643 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
644 static inline void doVisit(NodeT&, VisitorOp&);
646 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
647 typename ChildAllIterT,
typename OtherChildAllIterT>
648 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
650 template<
typename NodeT,
typename VisitorOp,
651 typename ChildAllIterT,
typename OtherChildAllIterT>
652 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
703 template<Index Log2Dim>
710 template<Index Log2Dim>
715 mOrigin(xyz & (~(DIM - 1)))
720 template<Index Log2Dim>
721 template<
typename ValueT>
724 mValueMask(other.getValueMask()),
725 mBuffer(other.getValueMask()),
726 mOrigin(other.getOrigin())
731 template<Index Log2Dim>
732 template<
typename ValueT>
736 mValueMask(other.getValueMask()),
737 mBuffer(other.getValueMask()),
738 mOrigin(other.getOrigin())
740 if (offValue) {
if (!onValue)
mBuffer.mData.toggle();
else mBuffer.mData.setOn(); }
744 template<Index Log2Dim>
745 template<
typename ValueT>
749 mValueMask(other.getValueMask()),
751 mOrigin(other.getOrigin())
756 template<Index Log2Dim>
759 mValueMask(other.mValueMask),
760 mBuffer(other.mBuffer),
761 mOrigin(other.mOrigin)
766 template<Index Log2Dim>
776 template<Index Log2Dim>
784 template<Index Log2Dim>
799 template<Index Log2Dim>
800 template<
typename OtherType, Index OtherLog2Dim>
809 template<Index Log2Dim>
813 std::ostringstream ostr;
814 ostr <<
"LeafNode @" <<
mOrigin <<
": ";
823 template<Index Log2Dim>
827 assert ((xyz[0] &
DIM-1u) <
DIM && (xyz[1] &
DIM-1u) <
DIM && (xyz[2] &
DIM-1u) <
DIM);
828 return ((xyz[0] &
DIM-1u) << 2*Log2Dim) + ((xyz[1] &
DIM-1u) << Log2Dim) + (xyz[2] &
DIM-1u);
832 template<Index Log2Dim>
836 assert(n < (1 << 3*Log2Dim));
838 xyz.
setX(n >> 2*Log2Dim);
839 n &= ((1 << 2*Log2Dim) - 1);
840 xyz.
setY(n >> Log2Dim);
841 xyz.
setZ(n & ((1 << Log2Dim) - 1));
846 template<Index Log2Dim>
857 template<Index Log2Dim>
865 template<Index Log2Dim>
873 template<Index Log2Dim>
889 int8_t numBuffers = 0;
890 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
894 boost::shared_array<bool> buf(
new bool[
SIZE]);
895 io::readData<bool>(is, buf.get(),
SIZE,
true);
900 if (buf[i])
mBuffer.mData.setOn(i);
903 if (numBuffers > 1) {
906 for (
int i = 1; i < numBuffers; ++i) {
907 io::readData<bool>(is, buf.get(),
SIZE,
true);
914 template<Index Log2Dim>
930 template<Index Log2Dim>
938 template<Index Log2Dim>
949 template<Index Log2Dim>
956 if (!tolerance && !(
mBuffer.mData.isOn() ||
mBuffer.mData.isOff()))
return false;
959 constValue =
mBuffer.mData.isOn();
967 template<Index Log2Dim>
972 if (
mBuffer.mData.isOn(this->coord2offset(xyz)))
return sOn;
else return sOff;
976 template<Index Log2Dim>
980 assert(offset <
SIZE);
982 if (
mBuffer.mData.isOn(offset))
return sOn;
else return sOff;
986 template<Index Log2Dim>
991 val =
mBuffer.mData.isOn(offset);
996 template<Index Log2Dim>
1002 mBuffer.mData.set(offset, val);
1006 template<Index Log2Dim>
1014 template<Index Log2Dim>
1020 mBuffer.mData.set(offset, val);
1024 template<Index Log2Dim>
1034 template<Index Log2Dim>
1044 template<Index Log2Dim>
1054 template<Index Log2Dim>
1062 template<Index Log2Dim>
1073 template<Index Log2Dim>
1077 if (newBackground != oldBackground) {
1086 template<Index Log2Dim>
1091 const Index n = iter.pos();
1099 template<Index Log2Dim>
1100 template<
typename OtherType>
1107 template<Index Log2Dim>
1108 template<
typename OtherType>
1116 template<Index Log2Dim>
1121 const Index offsetX = (x&
DIM-1u)<<2*Log2Dim;
1123 const Index offsetXY = offsetX + ((y&
DIM-1u)<< Log2Dim);
1125 const Index offset = offsetXY + (z&
DIM-1u);
1127 mBuffer.mData.set(offset, value);
1133 template<Index Log2Dim>
1140 template<Index Log2Dim>
1151 template<Index Log2Dim>
1152 template<
typename CombineOp>
1158 bool result =
false, aVal =
mBuffer.mData.isOn(i), bVal = other.
mBuffer.mData.isOn(i);
1163 .setResultRef(result));
1170 template<Index Log2Dim>
1171 template<
typename CombineOp>
1176 args.
setBRef(value).setBIsActive(valueIsActive);
1178 bool result =
false, aVal =
mBuffer.mData.isOn(i);
1181 .setResultRef(result));
1191 template<Index Log2Dim>
1192 template<
typename CombineOp>
1195 bool valueIsActive, CombineOp& op)
1198 args.
setBRef(value).setBIsActive(valueIsActive);
1200 bool result =
false, aVal = other.
mBuffer.mData.isOn(i);
1203 .setResultRef(result));
1210 template<Index Log2Dim>
1211 template<
typename CombineOp>
1214 bool valueIsActive, CombineOp& op)
1217 args.
setARef(value).setAIsActive(valueIsActive);
1219 bool result =
false, bVal = other.
mBuffer.mData.isOn(i);
1222 .setResultRef(result));
1229 template<Index Log2Dim>
1230 template<
typename CombineOp>
1239 bool result =
false, b0Val = b0.
mBuffer.mData.isOn(i), b1Val = b1.
mBuffer.mData.isOn(i);
1244 .setResultRef(result));
1253 template<Index Log2Dim>
1254 template<
typename BBoxOp>
1258 if (op.template descent<LEVEL>()) {
1276 template<Index Log2Dim>
1277 template<
typename VisitorOp>
1281 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1285 template<Index Log2Dim>
1286 template<
typename VisitorOp>
1290 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1294 template<Index Log2Dim>
1295 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1299 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1308 template<Index Log2Dim>
1309 template<
typename OtherLeafNodeType,
typename VisitorOp>
1314 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1318 template<Index Log2Dim>
1319 template<
typename OtherLeafNodeType,
typename VisitorOp>
1324 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1328 template<Index Log2Dim>
1331 typename OtherNodeT,
1333 typename ChildAllIterT,
1334 typename OtherChildAllIterT>
1339 BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
1340 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
1342 ChildAllIterT iter =
self.beginChildAll();
1343 OtherChildAllIterT otherIter = other.beginChildAll();
1345 for ( ; iter && otherIter; ++iter, ++otherIter) {
1346 op(iter, otherIter);
1354 template<Index Log2Dim>
1355 template<
typename IterT,
typename VisitorOp>
1359 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(*
this, otherIter, op, otherIsLHS);
1363 template<Index Log2Dim>
1364 template<
typename IterT,
typename VisitorOp>
1368 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(*
this, otherIter, op, otherIsLHS);
1372 template<Index Log2Dim>
1376 typename ChildAllIterT,
1377 typename OtherChildAllIterT>
1380 VisitorOp& op,
bool otherIsLHS)
1382 if (!otherIter)
return;
1385 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1386 op(otherIter, iter);
1389 for (ChildAllIterT iter =
self.
beginChildAll(); iter; ++iter) {
1390 op(iter, otherIter);
1399 #endif // OPENVDB_TREE_LEAFNODEBOOL_HAS_BEEN_INCLUDED