6 #ifndef OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
7 #define OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
23 #include <tbb/concurrent_hash_map.h>
49 virtual const Name&
type()
const = 0;
52 virtual Name valueType()
const = 0;
55 template<
typename TreeType>
56 bool isType()
const {
return (this->
type() == TreeType::treeType()); }
75 virtual bool evalLeafBoundingBox(
CoordBBox& bbox)
const = 0;
80 virtual bool evalLeafDim(Coord& dim)
const = 0;
89 virtual bool evalActiveVoxelBoundingBox(
CoordBBox& bbox)
const = 0;
94 virtual bool evalActiveVoxelDim(Coord& dim)
const = 0;
96 virtual void getIndexRange(
CoordBBox& bbox)
const = 0;
103 virtual void clipUnallocatedNodes() = 0;
105 #if OPENVDB_ABI_VERSION_NUMBER >= 12
106 virtual Index64 unallocatedLeafCount()
const = 0;
108 virtual Index32 unallocatedLeafCount()
const = 0;
118 virtual Index treeDepth()
const = 0;
120 #if OPENVDB_ABI_VERSION_NUMBER >= 12
121 virtual Index64 leafCount()
const = 0;
123 virtual Index32 leafCount()
const = 0;
128 #if OPENVDB_ABI_VERSION_NUMBER >= 12
129 virtual std::vector<Index64> nodeCount()
const = 0;
131 virtual std::vector<Index32> nodeCount()
const = 0;
134 #if OPENVDB_ABI_VERSION_NUMBER >= 12
135 virtual Index64 nonLeafCount()
const = 0;
137 virtual Index32 nonLeafCount()
const = 0;
140 virtual Index64 activeLeafVoxelCount()
const = 0;
142 virtual Index64 inactiveLeafVoxelCount()
const = 0;
144 virtual Index64 activeVoxelCount()
const = 0;
146 virtual Index64 inactiveVoxelCount()
const = 0;
148 virtual Index64 activeTileCount()
const = 0;
160 virtual void readTopology(std::istream&,
bool saveFloatAsHalf =
false);
164 virtual void writeTopology(std::ostream&,
bool saveFloatAsHalf =
false)
const;
167 virtual void readBuffers(std::istream&,
bool saveFloatAsHalf =
false) = 0;
169 virtual void readBuffers(std::istream&,
const CoordBBox&,
bool saveFloatAsHalf =
false) = 0;
175 virtual void readNonresidentBuffers()
const = 0;
177 virtual void writeBuffers(std::ostream&,
bool saveFloatAsHalf =
false)
const = 0;
186 virtual void print(std::ostream& os = std::cout,
int verboseLevel = 1)
const;
193 template<
typename _RootNodeType>
218 template<
typename OtherValueType>
239 template<
typename OtherRootType>
254 template<
typename OtherTreeType>
255 Tree(
const OtherTreeType& other,
275 template<
typename OtherTreeType>
313 template<
typename OtherRootNodeType>
333 void readTopology(std::istream&,
bool saveFloatAsHalf =
false)
override;
337 void writeTopology(std::ostream&,
bool saveFloatAsHalf =
false)
const override;
339 void readBuffers(std::istream&,
bool saveFloatAsHalf =
false)
override;
349 void writeBuffers(std::ostream&,
bool saveFloatAsHalf =
false)
const override;
351 void print(std::ostream& os = std::cout,
int verboseLevel = 1)
const override;
362 #if OPENVDB_ABI_VERSION_NUMBER >= 12
370 #if OPENVDB_ABI_VERSION_NUMBER >= 12
371 std::vector<Index64>
nodeCount()
const override
373 std::vector<Index64> vec(
DEPTH, 0);
374 mRoot.nodeCount( vec );
380 std::vector<Index32> vec(
DEPTH, 0);
382 mRoot.nodeCount( vec );
388 #if OPENVDB_ABI_VERSION_NUMBER >= 12
418 template<
typename AccessT>
const ValueType&
getValue(
const Coord& xyz, AccessT&)
const;
461 template<
typename ModifyOp>
483 template<
typename ModifyOp>
507 #if OPENVDB_ABI_VERSION_NUMBER >= 12
555 mRoot.prune(tolerance);
575 template<
typename NodeT>
588 template<
typename NodeType> NodeType*
probeNode(
const Coord& xyz);
589 template<
typename NodeType>
const NodeType*
probeConstNode(
const Coord& xyz)
const;
590 template<
typename NodeType>
const NodeType*
probeNode(
const Coord& xyz)
const;
624 template<
typename ArrayT>
void getNodes(ArrayT& array);
625 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
651 template<
typename ArrayT>
653 template<
typename ArrayT>
657 mRoot.stealNodes(array, value, state);
762 template<
typename OtherRootNodeType>
778 template<
typename OtherRootNodeType>
791 template<
typename OtherRootNodeType>
838 template<
typename CombineOp>
840 template<
typename CombineOp>
881 template<
typename ExtendedCombineOp>
883 template<
typename ExtendedCombineOp>
914 template<
typename CombineOp,
typename OtherTreeType >
916 template<
typename CombineOp,
typename OtherTreeType >
992 template<
typename ExtendedCombineOp,
typename OtherTreeType >
995 template<
typename ExtendedCombineOp,
typename OtherTreeType >
1078 template<
typename IterT> IterT
begin();
1081 template<
typename CIterT> CIterT
cbegin()
const;
1093 template<
typename NodeType>
1096 :
mNodes(nodes.
empty() ? nullptr : &nodes.front()) { }
1098 for (
size_t n = range.begin(),
N = range.
end();
n <
N; ++
n) {
1118 template<
typename T, Index N1=4, Index N2=3>
1128 template<
typename T, Index N1=5, Index N2=4, Index N3=3>
1137 template<
typename T, Index N1=6, Index N2=5, Index N3=4, Index N4=3>
1150 int32_t bufferCount;
1151 is.read(reinterpret_cast<char*>(&bufferCount),
sizeof(int32_t));
1152 if (bufferCount != 1)
OPENVDB_LOG_WARN(
"multi-buffer trees are no longer supported");
1159 int32_t bufferCount = 1;
1160 os.write(reinterpret_cast<char*>(&bufferCount),
sizeof(int32_t));
1167 os <<
" Tree Type: " <<
type()
1171 <<
" Leaf Node Count: " <<
leafCount() << std::endl
1172 <<
" Non-leaf Node Count: " <<
nonLeafCount() << std::endl;
1187 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnIter> {
1188 static typename TreeT::RootNodeType::ChildOnIter
begin(TreeT& tree) {
1189 return tree.beginRootChildren();
1193 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnCIter> {
1194 static typename TreeT::RootNodeType::ChildOnCIter
begin(
const TreeT& tree) {
1195 return tree.cbeginRootChildren();
1199 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffIter> {
1200 static typename TreeT::RootNodeType::ChildOffIter
begin(TreeT& tree) {
1201 return tree.beginRootTiles();
1205 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffCIter> {
1206 static typename TreeT::RootNodeType::ChildOffCIter
begin(
const TreeT& tree) {
1207 return tree.cbeginRootTiles();
1211 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllIter> {
1212 static typename TreeT::RootNodeType::ChildAllIter
begin(TreeT& tree) {
1213 return tree.beginRootDense();
1217 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllCIter> {
1218 static typename TreeT::RootNodeType::ChildAllCIter
begin(
const TreeT& tree) {
1219 return tree.cbeginRootDense();
1224 static typename TreeT::NodeIter
begin(TreeT& tree) {
return tree.beginNode(); }
1228 static typename TreeT::NodeCIter
begin(
const TreeT& tree) {
return tree.cbeginNode(); }
1232 static typename TreeT::LeafIter
begin(TreeT& tree) {
return tree.beginLeaf(); }
1236 static typename TreeT::LeafCIter
begin(
const TreeT& tree) {
return tree.cbeginLeaf(); }
1240 static typename TreeT::ValueOnIter
begin(TreeT& tree) {
return tree.beginValueOn(); }
1243 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::ValueOnCIter> {
1244 static typename TreeT::ValueOnCIter
begin(
const TreeT& tree) {
return tree.cbeginValueOn(); }
1247 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::ValueOffIter> {
1248 static typename TreeT::ValueOffIter
begin(TreeT& tree) {
return tree.beginValueOff(); }
1251 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::ValueOffCIter> {
1252 static typename TreeT::ValueOffCIter
begin(
const TreeT& tree) {
return tree.cbeginValueOff(); }
1255 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::ValueAllIter> {
1256 static typename TreeT::ValueAllIter
begin(TreeT& tree) {
return tree.beginValueAll(); }
1259 template<
typename TreeT>
struct TreeIterTraits<TreeT, typename TreeT::ValueAllCIter> {
1260 static typename TreeT::ValueAllCIter
begin(
const TreeT& tree) {
return tree.cbeginValueAll(); }
1264 template<
typename RootNodeType>
1265 template<
typename IterT>
1273 template<
typename RootNodeType>
1274 template<
typename IterT>
1285 template<
typename RootNodeType>
1289 this->clearAllAccessors();
1291 mRoot.readTopology(is, saveFloatAsHalf);
1295 template<
typename RootNodeType>
1300 mRoot.writeTopology(os, saveFloatAsHalf);
1304 template<
typename RootNodeType>
1308 this->clearAllAccessors();
1309 mRoot.readBuffers(is, saveFloatAsHalf);
1313 template<
typename RootNodeType>
1317 this->clearAllAccessors();
1318 mRoot.readBuffers(is, bbox, saveFloatAsHalf);
1322 template<
typename RootNodeType>
1326 for (
LeafCIter it = this->cbeginLeaf(); it; ++it) {
1328 it->getValue(
Index(0));
1333 template<
typename RootNodeType>
1337 mRoot.writeBuffers(os, saveFloatAsHalf);
1341 template<
typename RootNodeType>
1342 template<
typename ArrayT>
1348 "getNodes() does not work for the RootNode. Use Tree::root()");
1349 mRoot.getNodes(array);
1353 template<
typename RootNodeType>
1354 template<
typename ArrayT>
1360 "getNodes() does not work for the RootNode. Use Tree::root()");
1361 mRoot.getNodes(array);
1365 template<
typename RootNodeType>
1369 std::vector<LeafNodeType*> leafnodes;
1370 this->stealNodes(leafnodes);
1375 std::vector<typename RootNodeType::ChildNodeType*> internalNodes;
1376 this->stealNodes(internalNodes);
1383 this->clearAllAccessors();
1390 template<
typename RootNodeType>
1397 template<
typename RootNodeType>
1404 template<
typename RootNodeType>
1411 template<
typename RootNodeType>
1418 template<
typename RootNodeType>
1425 template<
typename RootNodeType>
1429 typename AccessorRegistry::accessor
a;
1430 mAccessorRegistry.insert(a, &accessor);
1434 template<
typename RootNodeType>
1438 typename ConstAccessorRegistry::accessor
a;
1439 mConstAccessorRegistry.insert(a, &accessor);
1443 template<
typename RootNodeType>
1447 mAccessorRegistry.erase(&accessor);
1451 template<
typename RootNodeType>
1455 mConstAccessorRegistry.erase(&accessor);
1459 template<
typename RootNodeType>
1463 for (
typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1464 it != mAccessorRegistry.end(); ++it)
1466 if (it->first) it->first->clear();
1469 for (
typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1470 it != mConstAccessorRegistry.end(); ++it)
1472 if (it->first) it->first->clear();
1477 template<
typename RootNodeType>
1481 mAccessorRegistry.erase(
nullptr);
1482 for (
typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1483 it != mAccessorRegistry.end(); ++it)
1485 it->first->release();
1487 mAccessorRegistry.clear();
1489 mAccessorRegistry.erase(
nullptr);
1490 for (
typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1491 it != mConstAccessorRegistry.end(); ++it)
1493 it->first->release();
1495 mConstAccessorRegistry.clear();
1502 template<
typename RootNodeType>
1506 return mRoot.getValue(xyz);
1510 template<
typename RootNodeType>
1511 template<
typename AccessT>
1515 return accessor.getValue(xyz);
1519 template<
typename RootNodeType>
1523 return mRoot.getValueDepth(xyz);
1527 template<
typename RootNodeType>
1531 mRoot.setValueOff(xyz);
1535 template<
typename RootNodeType>
1539 mRoot.setValueOff(xyz, value);
1543 template<
typename RootNodeType>
1547 mRoot.setActiveState(xyz, on);
1551 template<
typename RootNodeType>
1555 mRoot.setValueOn(xyz, value);
1558 template<
typename RootNodeType>
1562 mRoot.setValueOnly(xyz, value);
1565 template<
typename RootNodeType>
1566 template<
typename AccessT>
1570 accessor.setValue(xyz, value);
1574 template<
typename RootNodeType>
1578 mRoot.setActiveState(xyz,
true);
1582 template<
typename RootNodeType>
1586 mRoot.setValueOn(xyz, value);
1590 template<
typename RootNodeType>
1591 template<
typename ModifyOp>
1595 mRoot.modifyValue(xyz, op);
1599 template<
typename RootNodeType>
1600 template<
typename ModifyOp>
1604 mRoot.modifyValueAndActiveState(xyz, op);
1608 template<
typename RootNodeType>
1612 return mRoot.probeValue(xyz, value);
1619 template<
typename RootNodeType>
1624 mRoot.addTile(level, xyz, value, active);
1628 template<
typename RootNodeType>
1629 template<
typename NodeT>
1633 this->clearAllAccessors();
1634 return mRoot.template stealNode<NodeT>(xyz,
value,
active);
1638 template<
typename RootNodeType>
1639 inline typename RootNodeType::LeafNodeType*
1642 return mRoot.touchLeaf(xyz);
1646 template<
typename RootNodeType>
1647 inline typename RootNodeType::LeafNodeType*
1650 return mRoot.probeLeaf(xyz);
1654 template<
typename RootNodeType>
1655 inline const typename RootNodeType::LeafNodeType*
1658 return mRoot.probeConstLeaf(xyz);
1662 template<
typename RootNodeType>
1663 template<
typename NodeType>
1667 return mRoot.template probeNode<NodeType>(xyz);
1671 template<
typename RootNodeType>
1672 template<
typename NodeType>
1673 inline const NodeType*
1676 return this->
template probeConstNode<NodeType>(xyz);
1680 template<
typename RootNodeType>
1681 template<
typename NodeType>
1682 inline const NodeType*
1685 return mRoot.template probeConstNode<NodeType>(xyz);
1692 template<
typename RootNodeType>
1696 this->clearAllAccessors();
1697 return mRoot.clip(bbox);
1701 template<
typename RootNodeType>
1705 this->clearAllAccessors();
1706 for (
LeafIter it = this->beginLeaf(); it; ) {
1709 if (!leaf->isAllocated()) {
1710 this->addTile(0, leaf->origin(), this->background(),
false);
1715 #if OPENVDB_ABI_VERSION_NUMBER >= 12
1716 template<
typename RootNodeType>
1721 for (
auto it = this->cbeginLeaf(); it; ++it)
if (!it->isAllocated()) ++sum;
1725 template<
typename RootNodeType>
1730 for (
auto it = this->cbeginLeaf(); it; ++it)
if (!it->isAllocated()) ++sum;
1736 template<
typename RootNodeType>
1740 this->clearAllAccessors();
1741 return mRoot.sparseFill(bbox, value, active);
1745 template<
typename RootNodeType>
1749 this->clearAllAccessors();
1750 return mRoot.denseFill(bbox, value, active);
1754 template<
typename RootNodeType>
1758 this->clearAllAccessors();
1759 mRoot.voxelizeActiveTiles(threaded);
1763 template<
typename RootNodeType>
1771 if (result->typeName() == MetadataT::staticTypeName()) {
1772 MetadataT* m =
static_cast<MetadataT*
>(result.get());
1773 m->value() = mRoot.background();
1783 template<
typename RootNodeType>
1787 this->clearAllAccessors();
1791 mRoot.template merge<MERGE_ACTIVE_STATES>(other.
mRoot);
break;
1793 mRoot.template merge<MERGE_NODES>(other.
mRoot);
break;
1795 mRoot.template merge<MERGE_ACTIVE_STATES_AND_NODES>(other.
mRoot);
break;
1800 template<
typename RootNodeType>
1801 template<
typename OtherRootNodeType>
1805 this->clearAllAccessors();
1806 mRoot.topologyUnion(other.
root(), preserveTiles);
1809 template<
typename RootNodeType>
1810 template<
typename OtherRootNodeType>
1814 this->clearAllAccessors();
1815 mRoot.topologyIntersection(other.
root());
1818 template<
typename RootNodeType>
1819 template<
typename OtherRootNodeType>
1823 this->clearAllAccessors();
1824 mRoot.topologyDifference(other.
root());
1832 template<
typename AValueT,
typename CombineOp,
typename BValueT = AValueT>
1845 template<
typename RootNodeType>
1846 template<
typename CombineOp>
1851 this->combineExtended(other, extendedOp, prune);
1857 template<
typename RootNodeType>
1858 template<
typename CombineOp>
1863 this->combineExtended(other, extendedOp, prune);
1867 template<
typename RootNodeType>
1868 template<
typename ExtendedCombineOp>
1872 this->clearAllAccessors();
1879 template<
typename RootNodeType>
1880 template<
typename ExtendedCombineOp>
1884 this->clearAllAccessors();
1885 mRoot.template combine<const ExtendedCombineOp>(other.
mRoot,
op,
prune);
1889 template<
typename RootNodeType>
1890 template<
typename CombineOp,
typename OtherTreeType>
1895 this->combine2Extended(a, b, extendedOp, prune);
1901 template<
typename RootNodeType>
1902 template<
typename CombineOp,
typename OtherTreeType>
1907 this->combine2Extended(a, b, extendedOp, prune);
1911 template<
typename RootNodeType>
1912 template<
typename ExtendedCombineOp,
typename OtherTreeType>
1915 ExtendedCombineOp&
op,
bool prune)
1917 this->clearAllAccessors();
1925 template<
typename RootNodeType>
1926 template<
typename ExtendedCombineOp,
typename OtherTreeType>
1929 const ExtendedCombineOp&
op,
bool prune)
1931 this->clearAllAccessors();
1932 mRoot.template combine2<const ExtendedCombineOp>(a.
root(), b.root(),
op,
prune);
1939 template<
typename RootNodeType>
1943 static std::string sTreeTypeName = []()
1946 std::vector<Index> dims;
1948 std::ostringstream ostr;
1949 ostr <<
"Tree_" << typeNameAsString<BuildType>();
1950 for (
size_t i = 1,
N = dims.size(); i <
N; ++i) {
1951 ostr <<
"_" << dims[i];
1955 return sTreeTypeName;
1959 template<
typename RootNodeType>
1960 template<
typename OtherRootNodeType>
1964 return mRoot.hasSameTopology(other.
root());
1968 template<
typename RootNodeType>
1974 if (this->empty())
return false;
1976 mRoot.evalActiveBoundingBox(bbox,
false);
1978 return !bbox.empty();
1981 template<
typename RootNodeType>
1987 if (this->empty())
return false;
1989 mRoot.evalActiveBoundingBox(bbox,
true);
1991 return !bbox.empty();
1995 template<
typename RootNodeType>
2000 bool notEmpty = this->evalActiveVoxelBoundingBox(bbox);
2001 dim = bbox.extents();
2006 template<
typename RootNodeType>
2011 bool notEmpty = this->evalLeafBoundingBox(bbox);
2012 dim = bbox.extents();
2017 template<
typename RootNodeType>
2021 minVal = maxVal = zeroVal<ValueType>();
2023 minVal = maxVal = *iter;
2024 for (++iter; iter; ++iter) {
2033 template<
typename RootNodeType>
2038 RootNodeType::getNodeLog2Dims(dims);
2042 template<
typename RootNodeType>
2046 if (verboseLevel <= 0)
return;
2051 std::streamsize savedPrecision;
2052 OnExit(std::ostream& _os): os(_os), savedPrecision(os.precision()) {}
2053 ~
OnExit() { os.precision(savedPrecision); }
2055 OnExit restorePrecision(os);
2057 std::vector<Index> dims;
2060 os <<
"Information about Tree:\n"
2061 <<
" Type: " << this->
type() <<
"\n";
2063 os <<
" Configuration:\n";
2065 if (verboseLevel <= 1) {
2067 os <<
" Root(" << mRoot.getTableSize() <<
")";
2068 if (dims.size() > 1) {
2069 for (
size_t i = 1,
N = dims.size() - 1; i <
N; ++i) {
2070 os <<
", Internal(" << (1 << dims[i]) <<
"^3)";
2072 os <<
", Leaf(" << (1 << dims.back()) <<
"^3)\n";
2074 os <<
" Background value: " << mRoot.background() <<
"\n";
2080 ValueType minVal = zeroVal<ValueType>(), maxVal = zeroVal<ValueType>();
2081 if (verboseLevel > 3) {
2084 minVal = extrema.
min();
2085 maxVal = extrema.
max();
2088 const auto nodeCount = this->nodeCount();
2089 const Index64 leafCount = nodeCount.front();
2093 for (
size_t i = 0; i < nodeCount.size(); ++i) totalNodeCount += nodeCount[i];
2096 os <<
" Root(1 x " << mRoot.getTableSize() <<
")";
2097 if (dims.size() >= 2) {
2098 for (
size_t i = 1,
N = dims.size() - 1; i <
N; ++i) {
2100 os <<
" x " << (1 << dims[i]) <<
"^3)";
2103 os <<
" x " << (1 << dims.back()) <<
"^3)\n";
2105 os <<
" Background value: " << mRoot.background() <<
"\n";
2109 if (verboseLevel > 3) {
2110 os <<
" Min value: " << minVal <<
"\n";
2111 os <<
" Max value: " << maxVal <<
"\n";
2115 numActiveVoxels = this->activeVoxelCount(),
2116 numActiveLeafVoxels = this->activeLeafVoxelCount(),
2117 numActiveTiles = this->activeTileCount();
2124 if (numActiveVoxels) {
2126 this->evalActiveVoxelBoundingBox(bbox);
2127 dim = bbox.extents();
2128 totalVoxels = dim.x() * uint64_t(dim.y()) * dim.z();
2130 os <<
" Bounding box of active voxels: " << bbox <<
"\n";
2131 os <<
" Dimensions of active voxels: "
2132 << dim[0] <<
" x " << dim[1] <<
" x " << dim[2] <<
"\n";
2134 const double activeRatio = (100.0 * double(numActiveVoxels)) /
double(totalVoxels);
2135 os <<
" Percentage of active voxels: " << std::setprecision(3) << activeRatio <<
"%\n";
2137 if (leafCount > 0) {
2138 const double fillRatio = (100.0 * double(numActiveLeafVoxels))
2139 / (
double(leafCount) * double(LeafNodeType::NUM_VOXELS));
2140 os <<
" Average leaf node fill ratio: " << fillRatio <<
"%\n";
2143 if (verboseLevel > 2) {
2145 for (
auto it = this->cbeginLeaf(); it; ++it)
if (!it->isAllocated()) ++sum;
2146 os <<
" Number of unallocated nodes: "
2148 << (100.0 * double(sum) / double(totalNodeCount)) <<
"%)\n";
2151 os <<
" Tree is empty!\n";
2155 if (verboseLevel == 2)
return;
2159 actualMem = this->memUsage(),
2160 denseMem =
sizeof(
ValueType) * totalVoxels,
2161 voxelsMem =
sizeof(
ValueType) * numActiveLeafVoxels;
2164 os <<
"Memory footprint:\n";
2168 if (numActiveVoxels) {
2170 os <<
" Actual footprint is " << (100.0 * double(actualMem) / double(denseMem))
2171 <<
"% of an equivalent dense volume\n";
2172 os <<
" Leaf voxel footprint is " << (100.0 * double(voxelsMem) / double(actualMem))
2173 <<
"% of actual footprint\n";
2181 #endif // OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
virtual Index64 activeTileCount() const =0
Return the total number of active tiles.
const AValueType & result() const
Get the output value.
tbb::concurrent_hash_map< ValueAccessorBase< Tree, true > *, bool > AccessorRegistry
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOnCIter > ValueOnCIter
virtual void readTopology(std::istream &, bool saveFloatAsHalf=false)
Read the tree topology from a stream.
ValueOffIter beginValueOff()
Return an iterator over inactive values (tile and voxel) across all nodes.
void releaseAccessor(ValueAccessorBase< Tree, true > &) const
Deregister an accessor so that it is no longer automatically cleared.
AccessorRegistry mAccessorRegistry
UnsafeAccessor getUnsafeAccessor()
Return an unsafe accessor that provides random read and write access to this tree's voxels...
bool operator==(const Tree &) const
virtual void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const
Write the tree topology to a stream.
bool hasSameTopology(const Tree< OtherRootNodeType > &other) const
Return true if the given tree has the same node and active value topology as this tree...
void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const override
Write out all data buffers for this tree.
SharedPtr< TreeBase > Ptr
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
LeafIteratorBase< Tree, typename RootNodeType::ChildOnIter > LeafIter
Iterator over all leaf nodes in this tree.
static TreeT::ValueAllIter begin(TreeT &tree)
hboost::math::policies::policy< hboost::math::policies::domain_error< hboost::math::policies::ignore_error >, hboost::math::policies::pole_error< hboost::math::policies::ignore_error >, hboost::math::policies::overflow_error< hboost::math::policies::ignore_error >, hboost::math::policies::underflow_error< hboost::math::policies::ignore_error >, hboost::math::policies::denorm_error< hboost::math::policies::ignore_error >, hboost::math::policies::rounding_error< hboost::math::policies::ignore_error >, hboost::math::policies::evaluation_error< hboost::math::policies::ignore_error >, hboost::math::policies::indeterminate_result_error< hboost::math::policies::ignore_error > > policy
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
void stealNodes(ArrayT &array, const ValueType &value, bool state)
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
ValueAccessor< Tree, false > UnsafeAccessor
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
virtual Metadata::Ptr getBackgroundValue() const
Return this tree's background value wrapped as metadata.
void attachAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
static const Name & treeType()
Return the name of this type of tree.
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOnIter > ValueOnIter
void addLeaf(LeafNodeType *leaf)
Add the given leaf node to this tree, creating a new branch if necessary. If a leaf node with the sam...
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
RootNodeType::ChildOffCIter cbeginRootTiles() const
Return an iterator over non-child entries of the root node's table.
Index64 inactiveVoxelCount() const override
Return the number of inactive voxels within the bounding box of all active voxels.
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
GLsizei const GLfloat * value
void addTile(Index level, const Coord &xyz, const ValueType &value, bool active)
Add a tile containing voxel (x, y, z) at the specified tree level, creating a new branch if necessary...
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
TreeIterTraits provides, for all tree iterators, a begin(tree) function that returns an iterator over...
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Base class for tree-traversal iterators over all nodes.
static TreeT::NodeCIter begin(const TreeT &tree)
#define OPENVDB_LOG_WARN(mesg)
ValueAllCIter beginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
DeallocateNodes(std::vector< NodeType * > &nodes)
RootNodeType::ChildOffCIter beginRootTiles() const
Return an iterator over non-child entries of the root node's table.
NodeIteratorBase< Tree, typename RootNodeType::ChildOnIter > NodeIter
Iterator over all nodes in this tree.
static TreeT::LeafCIter begin(const TreeT &tree)
GLboolean GLboolean GLboolean GLboolean a
Tree(const OtherTreeType &other, const ValueType &inactiveValue, const ValueType &activeValue, TopologyCopy)
Topology copy constructor from a tree of a different type.
RootNodeType::ChildAllCIter cbeginRootDense() const
Return an iterator over all entries of the root node's table.
RootNodeType & root()
Return this tree's root node.
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
virtual Index64 activeVoxelCount() const =0
Return the total number of active voxels.
static TreeT::RootNodeType::ChildOffIter begin(TreeT &tree)
**But if you need a result
TreeValueIteratorBase< Tree, typename RootNodeType::ValueAllIter > ValueAllIter
virtual Index32 leafCount() const =0
Return the number of leaf nodes.
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueAllCIter > ValueAllCIter
Tree(const ValueType &background)
Empty tree constructor.
bool isValueOff(const Coord &xyz) const
Return true if the value at the given coordinates is inactive.
Index32 unallocatedLeafCount() const override
Return the total number of unallocated leaf nodes residing in this tree.
void readNonresidentBuffers() const override
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
ValueAccessor< Tree, true > Accessor
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Index64 memUsage() const override
Return the total amount of memory in bytes occupied by this tree.
ValueOffCIter cbeginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
RootNodeType::ChildOffIter beginRootTiles()
Return an iterator over non-child entries of the root node's table.
static TreeT::LeafIter begin(TreeT &tree)
bool operator!=(const Tree &) const
void topologyIntersection(const Tree< OtherRootNodeType > &other)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
void releaseAllAccessors()
Notify all registered accessors, by calling ValueAccessor::release(), that this tree is about to be d...
virtual Index64 inactiveVoxelCount() const =0
Return the number of inactive voxels within the bounding box of all active voxels.
Tree4<T, N1, N2, N3>::Type is the type of a four-level tree (Root, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2 and N3, respectively.
bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
ConstUnsafeAccessor getConstUnsafeAccessor()
Return an unsafe accessor that provides random read-only access to this tree's voxels.
ValueAllIter beginValueAll()
Return an iterator over all values (tile and voxel) across all nodes.
Tree & operator=(const Tree &)=delete
#define OPENVDB_ASSERT(X)
CombineOpAdapter(CombineOp &_op)
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
std::shared_ptr< T > SharedPtr
void clear()
Remove all tiles from this tree and all nodes other than the root node.
void topologyDifference(const Tree< OtherRootNodeType > &other)
Difference this tree's set of active values with the active values of the other tree, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this tree and inactive in the other tree.
SYS_FORCE_INLINE const_iterator end() const
const AValueType & a() const
Get the A input value.
RootNodeType::ChildOnCIter beginRootChildren() const
Return an iterator over children of the root node.
Name valueType() const override
Return the name of the type of a voxel's value (e.g., "float" or "vec3d")
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
void readBuffers(std::istream &, bool saveFloatAsHalf=false) override
Read all data buffers for this tree.
const ValueType & background() const
Return this tree's background value.
bool isType() const
Return true if this tree is of the same type as the template parameter.
static TreeT::RootNodeType::ChildOnCIter begin(const TreeT &tree)
ConstAccessor getConstAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
tbb::concurrent_hash_map< ValueAccessorBase< const Tree, true > *, bool > ConstAccessorRegistry
LeafCIter beginLeaf() const
Return an iterator over all leaf nodes in this tree.
void operator()(CombineArgs< AValueT, BValueT > &args) const
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
void print(std::ostream &os=std::cout, int verboseLevel=1) const override
Print statistics, memory usage and other information about this tree.
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Index64 activeTileCount() const override
Return the total number of active tiles.
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
TreeBase::Ptr copy() const override
Return a pointer to a deep copy of this tree.
Index64 activeLeafVoxelCount() const override
Return the number of active voxels stored in leaf nodes.
void releaseAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Iterator over all leaf nodes in this tree.
Index32 leafCount() const override
Return the number of leaf nodes.
void attachAccessor(ValueAccessorBase< Tree, true > &) const
Register an accessor for this tree. Registered accessors are automatically cleared whenever one of th...
NodeCIter beginNode() const
Return an iterator over all nodes in this tree.
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
bool evalActiveVoxelDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all active voxels. This is a tighter bounding box than the leaf node bounding box.
ValueConverter<T>::Type is the type of a tree having the same hierarchy as this tree but a different ...
const RootNodeType & root() const
Return this tree's root node.
Functions to count tiles, nodes or voxels in a grid.
Tree3<T, N1, N2>::Type is the type of a three-level tree (Root, Internal, Leaf) with value type T and...
const ValueType & max() const
Return the maximum value.
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Helper class to adapt a three-argument (a, b, result) CombineOp functor into a single-argument functo...
bool probeValue(const Coord &xyz, ValueType &value) const
Get the value of the voxel at the given coordinates.
ValueOffCIter beginValueOff() const
Return an iterator over inactive values (tile and voxel) across all nodes.
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists...
Index64 inactiveLeafVoxelCount() const override
Return the number of inactive voxels stored in leaf nodes.
const LeafNodeType * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Templated class to compute the minimum and maximum values.
void attachAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
static TreeT::ValueOffCIter begin(const TreeT &tree)
GLboolean GLboolean GLboolean b
void operator()(const tbb::blocked_range< size_t > &range) const
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
static TreeT::ValueAllCIter begin(const TreeT &tree)
bool evalLeafBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values...
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
typename RootNodeType::ValueType ValueType
NodeIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > NodeCIter
Iterator over all nodes in this tree.
static TreeT::RootNodeType::ChildOnIter begin(TreeT &tree)
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOffIter > ValueOffIter
The root node of an OpenVDB tree.
bool hasActiveTiles() const
Return true if this tree has any active tiles.
void releaseAccessor(ValueAccessorBase< const Tree, false > &) const
Dummy implementations.
void evalMinMax(ValueType &min, ValueType &max) const
Return the minimum and maximum active values in this tree.
CIterT cbegin() const
Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>() is equivalent to cbeginVa...
ValueAllCIter cbeginValueAll() const
Return an iterator over all values (tile and voxel) across all nodes.
Base class for typed trees.
static TreeT::NodeIter begin(TreeT &tree)
static TreeT::ValueOffIter begin(TreeT &tree)
Index64 activeVoxelCount() const override
Return the total number of active voxels.
Index32 nonLeafCount() const override
Return the number of non-leaf nodes.
virtual Index32 nonLeafCount() const =0
Return the number of non-leaf nodes.
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOffCIter > ValueOffCIter
static void getNodeLog2Dims(std::vector< Index > &dims)
Traverse the type hierarchy of nodes, and return, in dims, a list of the Log2Dims of nodes in order f...
Accessor getAccessor()
Return an accessor that provides random read and write access to this tree's voxels.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
typename RootNodeType::LeafNodeType LeafNodeType
Tree(const Tree &other)
Deep copy constructor.
ConstAccessorRegistry mConstAccessorRegistry
ValueOnCIter beginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
void readTopology(std::istream &, bool saveFloatAsHalf=false) override
Read the tree topology from a stream.
virtual void print(std::ostream &os=std::cout, int verboseLevel=1) const
Print statistics, memory usage and other information about this tree.
const ValueType & min() const
Return the minimum value.
LeafData & operator=(const LeafData &)=delete
typename RootNodeType::BuildType BuildType
ValueAccessor< const Tree, true > ConstAccessor
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
static TreeT::RootNodeType::ChildAllIter begin(TreeT &tree)
ValueOnIter beginValueOn()
Return an iterator over active values (tile and voxel) across all nodes.
Base class for tree-traversal iterators over tile and voxel values.
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
RootNodeType::ChildAllIter beginRootDense()
Return an iterator over all entries of the root node's table.
NodeCIter cbeginNode() const
Return an iterator over all nodes in this tree.
RootNodeType::ChildOnIter beginRootChildren()
Return an iterator over children of the root node.
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool active)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
void getIndexRange(CoordBBox &bbox) const override
Min and max are both inclusive.
GA_API const UT_StringHolder N
_RootNodeType RootNodeType
FormattedInt< IntT > formattedInt(IntT n)
ValueAccessor< const Tree, false > ConstUnsafeAccessor
SharedPtr< const TreeBase > ConstPtr
static TreeT::ValueOnCIter begin(const TreeT &tree)
void combine2Extended(const Tree &a, const OtherTreeType &b, ExtendedCombineOp &op, bool prune=false)
**If you just want to fire and args
RootNodeType::ChildOnCIter cbeginRootChildren() const
Return an iterator over children of the root node.
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
void combine2(const Tree &a, const OtherTreeType &b, CombineOp &op, bool prune=false)
OPENVDB_API int printBytes(std::ostream &os, uint64_t bytes, const std::string &head="", const std::string &tail="\n", bool exact=false, int width=8, int precision=3)
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists...
const Name & type() const override
Return the name of this type of tree.
void clipUnallocatedNodes() override
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
RootNodeType::ChildAllCIter beginRootDense() const
Return an iterator over all entries of the root node's table.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
const BValueType & b() const
Get the B input value.
ValueOnCIter cbeginValueOn() const
Return an iterator over active values (tile and voxel) across all nodes.
virtual const Name & type() const =0
Return the name of this tree's type.
Metadata::Ptr getBackgroundValue() const override
Return this tree's background value wrapped as metadata.
NodeIter beginNode()
Return an iterator over all nodes in this tree.
bool isValueOn(const Coord &xyz) const
Return true if the value at the given coordinates is active.
bool evalLeafDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
IterT begin()
Return an iterator of type IterT (for example, begin<ValueOnIter>() is equivalent to beginValueOn())...
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one that preserves the values and active states of all voxels.
Tree(const OtherTreeType &other, const ValueType &background, TopologyCopy)
Topology copy constructor from a tree of a different type.
bool empty() const
Return true if this tree contains no nodes other than the root node and no tiles other than backgroun...
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
FMT_INLINE void print(format_string< T...> fmt, T &&...args)
std::vector< Index32 > nodeCount() const override
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
void topologyUnion(const Tree< OtherRootNodeType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
static TreeT::RootNodeType::ChildOffCIter begin(const TreeT &tree)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
static TreeT::RootNodeType::ChildAllCIter begin(const TreeT &tree)
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree (Root, Internal, Internal, Internal, Leaf) with value type T and internal and leaf node log dimensions N1, N2, N3 and N4, respectively.
void combine(Tree &other, CombineOp &op, bool prune=false)
Internal table nodes for OpenVDB trees.
Index treeDepth() const override
Return the depth of this tree.
#define OPENVDB_THROW(exception, message)
void combineExtended(Tree &other, ExtendedCombineOp &op, bool prune=false)
void clearAllAccessors()
Clear all registered accessors.
void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const override
Write the tree topology to a stream.
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Tree(const Tree< OtherRootType > &other)
Value conversion deep copy constructor.
static TreeT::ValueOnIter begin(TreeT &tree)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.