Loading...
Searching...
No Matches
ValueAccessor.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
/// @file tree/ValueAccessor.h
///
/// When traversing a grid in a spatially coherent pattern (e.g., iterating
/// over neighboring voxels), request a @c ValueAccessor from the grid
/// (with Grid::getAccessor()) and use the accessor's @c getValue() and
/// @c setValue() methods. These will typically be significantly faster
/// than accessing voxels directly in the grid's tree.
///
/// @par Example:
///
/// @code
/// FloatGrid grid;
/// FloatGrid::Accessor acc = grid.getAccessor();
/// // First access is slow:
/// acc.setValue(Coord(0, 0, 0), 100);
/// // Subsequent nearby accesses are fast, since the accessor now holds pointers
/// // to nodes that contain (0, 0, 0) along the path from the root of the grid's
/// // tree to the leaf:
/// acc.setValue(Coord(0, 0, 1), 100);
/// acc.getValue(Coord(0, 2, 0), 100);
/// // Slow, because the accessor must be repopulated:
/// acc.getValue(Coord(-1, -1, -1));
/// // Fast:
/// acc.getValue(Coord(-1, -1, -2));
/// acc.setValue(Coord(-1, -2, 0), -100);
/// @endcode
#ifndef OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
#define OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
#include <openvdb/version.h>
#include <openvdb/Types.h>
#include <tbb/null_mutex.h>
#include <tbb/spin_mutex.h>
#include <cassert>
#include <limits>
#include <type_traits>
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace tree {
// Forward declarations of local classes that are not intended for general use
// The IsSafe template parameter is explained in the warning below.
template<typename TreeType, bool IsSafe = true>
class ValueAccessor0;
template<typename TreeType, bool IsSafe = true, Index L0 = 0>
class ValueAccessor1;
template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1>
class ValueAccessor2;
template<typename TreeType, bool IsSafe = true, Index L0 = 0, Index L1 = 1, Index L2 = 2>
class ValueAccessor3;
template<typename TreeCacheT, typename NodeVecT, bool AtRoot
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, bool BypassLeafAPI =
std::is_same<typename NodeVecT::Front, typename NodeVecT::Front::LeafNodeType>::value &&
std::is_same<typename NodeVecT::Front::LeafNodeType::Buffer::StorageType, typename NodeVecT::Front::ValueType>::value
#endif
> class CacheItem;
/// @brief This base class for ValueAccessors manages registration of an accessor
/// with a tree so that the tree can automatically clear the accessor whenever
/// one of its nodes is deleted.
///
/// @internal A base class is needed because ValueAccessor is templated on both
/// a Tree type and a mutex type. The various instantiations of the template
/// are distinct, unrelated types, so they can't easily be stored in a container
/// such as the Tree's CacheRegistry. This base class, in contrast, is templated
/// only on the Tree type, so for any given Tree, only two distinct instantiations
/// are possible, ValueAccessorBase<Tree> and ValueAccessorBase<const Tree>.
///
/// @warning If IsSafe = false then the ValueAccessor will not register itself
/// with the tree from which it is constructed. While in some rare cases this can
/// lead to better performance (since it avoids the small overhead of insertion
/// on creation and deletion on destruction) it is also unsafe if the tree is
/// modified. So unless you're an expert it is highly recommended to set
/// IsSafe = true, which is the default in all derived ValueAccessors defined
/// below. However if you know that the tree is no being modifed for the lifespan
/// of the ValueAccessor AND the work performed per ValueAccessor is small relative
/// to overhead of registering it you should consider setting IsSafe = false. If
/// this turns out to improve performance you should really rewrite your code so as
/// to better amortize the construction of the ValueAccessor, i.e. reuse it as much
/// as possible!
template<typename TreeType, bool IsSafe>
class ValueAccessorBase
{
public:
static const bool IsConstTree = std::is_const<TreeType>::value;
/// @brief Return true if this accessor is safe, i.e. registered
/// by the tree from which it is constructed. Un-registered
/// accessors can in rare cases be faster because it avoids the
/// (small) overhead of registration, but they are unsafe if the
/// tree is modified. So unless you're an expert it is highly
/// recommended to set IsSafe = true (which is the default).
static bool isSafe() { return IsSafe; }
ValueAccessorBase(TreeType& tree): mTree(&tree)
{
if (IsSafe) tree.attachAccessor(*this);
}
virtual ~ValueAccessorBase() { if (IsSafe && mTree) mTree->releaseAccessor(*this); }
/// @brief Return a pointer to the tree associated with this accessor.
/// @details The pointer will be null only if the tree from which this accessor
/// was constructed was subsequently deleted (which generally leaves the
/// accessor in an unsafe state).
TreeType* getTree() const { return mTree; }
/// Return a reference to the tree associated with this accessor.
TreeType& tree() const { assert(mTree); return *mTree; }
ValueAccessorBase(const ValueAccessorBase& other): mTree(other.mTree)
{
if (IsSafe && mTree) mTree->attachAccessor(*this);
}
ValueAccessorBase& operator=(const ValueAccessorBase& other)
{
if (&other != this) {
if (IsSafe && mTree) mTree->releaseAccessor(*this);
mTree = other.mTree;
if (IsSafe && mTree) mTree->attachAccessor(*this);
}
return *this;
}
virtual void clear() = 0;
protected:
// Allow trees to deregister themselves.
template<typename> friend class Tree;
virtual void release() { mTree = nullptr; }
TreeType* mTree;
}; // class ValueAccessorBase
////////////////////////////////////////
/// When traversing a grid in a spatially coherent pattern (e.g., iterating
/// over neighboring voxels), request a @c ValueAccessor from the grid
/// (with Grid::getAccessor()) and use the accessor's @c getValue() and
/// @c setValue() methods. These will typically be significantly faster
/// than accessing voxels directly in the grid's tree.
///
/// A ValueAccessor caches pointers to tree nodes along the path to a voxel (x, y, z).
/// A subsequent access to voxel (x', y', z') starts from the cached leaf node and
/// moves up until a cached node that encloses (x', y', z') is found, then traverses
/// down the tree from that node to a leaf, updating the cache with the new path.
/// This leads to significant acceleration of spatially-coherent accesses.
///
/// @param _TreeType the type of the tree to be accessed [required]
/// @param IsSafe if IsSafe = false then the ValueAccessor will
/// not register itself with the tree from which
/// it is constructed (see warning).
/// @param CacheLevels the number of nodes to be cached, starting from the leaf level
/// and not including the root (i.e., CacheLevels < DEPTH),
/// and defaulting to all non-root nodes
/// @param MutexType the type of mutex to use (see note)
///
/// @warning If IsSafe = false then the ValueAccessor will not register itself
/// with the tree from which it is constructed. While in some rare cases this can
/// lead to better performance (since it avoids the small overhead of insertion
/// on creation and deletion on destruction) it is also unsafe if the tree is
/// modified. So unless you're an expert it is highly recommended to set
/// IsSafe = true, which is the default. However if you know that the tree is no
/// being modifed for the lifespan of the ValueAccessor AND the work performed
/// per ValueAccessor is small relative to overhead of registering it you should
/// consider setting IsSafe = false. If this improves performance you should
/// really rewrite your code so as to better amortize the construction of the
/// ValueAccessor, i.e. reuse it as much as possible!
///
/// @note If @c MutexType is a TBB-compatible mutex, then multiple threads may
/// safely access a single, shared accessor. However, it is highly recommended
/// that, instead, each thread be assigned its own, non-mutex-protected accessor.
template<typename _TreeType,
bool IsSafe = true,
Index CacheLevels = _TreeType::DEPTH-1,
typename MutexType = tbb::null_mutex>
class ValueAccessor: public ValueAccessorBase<_TreeType, IsSafe>
{
public:
static_assert(CacheLevels < _TreeType::DEPTH, "cache size exceeds tree depth");
using TreeType = _TreeType;
using RootNodeT = typename TreeType::RootNodeType;
using LeafNodeT = typename TreeType::LeafNodeType;
using ValueType = typename RootNodeT::ValueType;
using BaseT = ValueAccessorBase<TreeType, IsSafe>;
using LockT = typename MutexType::scoped_lock;
using BaseT::IsConstTree;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// If the last node being cached is a leaf node and the storage type matches
// the ValueType, we can cache the buffer pointer instead of using the delay
// load locked leaf API
static constexpr bool BypassLeafAPI = CacheLevels >= 1 &&
std::is_same<typename LeafNodeT::Buffer::StorageType, ValueType>::value;
#endif
ValueAccessor(TreeType& tree): BaseT(tree), mCache(*this)
{
mCache.insert(Coord(), &tree.root());
}
ValueAccessor(const ValueAccessor& other) : BaseT(other), mCache(*this, other.mCache) {}
ValueAccessor& operator=(const ValueAccessor& other)
{
if (&other != this) {
this->BaseT::operator=(other);
mCache.copy(*this, other.mCache);
}
return *this;
}
~ValueAccessor() override = default;
/// Return the number of cache levels employed by this accessor.
static Index numCacheLevels() { return CacheLevels; }
/// Return @c true if nodes along the path to the given voxel have been cached.
bool isCached(const Coord& xyz) const { LockT lock(mMutex); return mCache.isCached(xyz); }
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz) const
{
LockT lock(mMutex);
return mCache.getValue(xyz);
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz) const { LockT lock(mMutex); return mCache.isValueOn(xyz); }
/// Return the active state of the voxel as well as its value
bool probeValue(const Coord& xyz, ValueType& value) const
{
LockT lock(mMutex);
return mCache.probeValue(xyz,value);
}
/// Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides,
/// or -1 if (x, y, z) isn't explicitly represented in the tree (i.e., if it is
/// implicitly a background voxel).
int getValueDepth(const Coord& xyz) const
{
LockT lock(mMutex);
return mCache.getValueDepth(xyz);
}
/// Return @c true if the value of voxel (x, y, z) resides at the leaf level
/// of the tree, i.e., if it is not a tile value.
bool isVoxel(const Coord& xyz) const { LockT lock(mMutex); return mCache.isVoxel(xyz); }
//@{
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
LockT lock(mMutex);
mCache.setValue(xyz, value);
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
//@}
/// Set the value of the voxel at the given coordinate but don't change its active state.
void setValueOnly(const Coord& xyz, const ValueType& value)
{
LockT lock(mMutex);
mCache.setValueOnly(xyz, value);
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
LockT lock(mMutex);
mCache.setValueOff(xyz, value);
}
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
LockT lock(mMutex);
mCache.modifyValue(xyz, op);
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
LockT lock(mMutex);
mCache.modifyValueAndActiveState(xyz, op);
}
/// Set the active state of the voxel at the given coordinates but don't change its value.
void setActiveState(const Coord& xyz, bool on = true)
{
LockT lock(mMutex);
mCache.setActiveState(xyz, on);
}
/// Mark the voxel at the given coordinates as active but don't change its value.
void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
/// Mark the voxel at the given coordinates as inactive but don't change its value.
void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
/// Return the cached node of type @a NodeType. [Mainly for internal use]
template<typename NodeType>
NodeType* getNode()
{
LockT lock(mMutex);
NodeType* node = nullptr;
mCache.getNode(node);
return node;
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z). [Mainly for internal use]
template<typename NodeType>
void insertNode(const Coord& xyz, NodeType& node)
{
LockT lock(mMutex);
mCache.insert(xyz, &node);
}
/// If a node of the given type exists in the cache, remove it, so that
/// isCached(xyz) returns @c false for any voxel (x, y, z) contained in
/// that node. [Mainly for internal use]
template<typename NodeType>
void eraseNode() { LockT lock(mMutex); NodeType* node = nullptr; mCache.erase(node); }
/// @brief Add the specified leaf to this tree, possibly creating a child branch
/// in the process. If the leaf node already exists, replace it.
void addLeaf(LeafNodeT* leaf)
{
LockT lock(mMutex);
mCache.addLeaf(leaf);
}
/// @brief Add a tile at the specified tree level that contains voxel (x, y, z),
/// possibly deleting existing nodes or creating new nodes in the process.
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
LockT lock(mMutex);
mCache.addTile(level, xyz, value, state);
}
/// @brief Return a pointer to the leaf node that contains voxel (x, y, z).
/// If no such node exists, create one, but preserve the values and
/// active states of all voxels.
/// @details Use this method to preallocate a static tree topology
/// over which to safely perform multithreaded processing.
LeafNodeT* touchLeaf(const Coord& xyz)
{
LockT lock(mMutex);
return mCache.touchLeaf(xyz);
}
//@{
/// @brief Return a pointer to the node of the specified type that contains
/// voxel (x, y, z), or @c nullptr if no such node exists.
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
LockT lock(mMutex);
return mCache.template probeNode<NodeT>(xyz);
}
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz) const
{
LockT lock(mMutex);
return mCache.template probeConstNode<NodeT>(xyz);
}
template<typename NodeT>
const NodeT* probeNode(const Coord& xyz) const
{
return this->template probeConstNode<NodeT>(xyz);
}
//@}
//@{
/// @brief Return a pointer to the leaf node that contains voxel (x, y, z),
/// or @c nullptr if no such node exists.
LeafNodeT* probeLeaf(const Coord& xyz)
{
LockT lock(mMutex);
return mCache.probeLeaf(xyz);
}
const LeafNodeT* probeConstLeaf(const Coord& xyz) const
{
LockT lock(mMutex);
return mCache.probeConstLeaf(xyz);
}
const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
//@}
/// Remove all nodes from this cache, then reinsert the root node.
void clear() override
{
LockT lock(mMutex);
mCache.clear();
if (this->mTree) mCache.insert(Coord(), &(this->mTree->root()));
}
private:
// Allow nodes to insert themselves into the cache.
template<typename> friend class RootNode;
template<typename, Index> friend class InternalNode;
template<typename, Index> friend class LeafNode;
// Allow trees to deregister themselves.
template<typename> friend class Tree;
/// Prevent this accessor from calling Tree::releaseCache() on a tree that
/// no longer exists. (Called by mTree when it is destroyed.)
void release() override
{
LockT lock(mMutex);
this->BaseT::release();
mCache.clear();
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z).
/// @note This operation is not mutex-protected and is intended to be called
/// only by nodes and only in the context of a getValue() or setValue() call.
template<typename NodeType>
void insert(const Coord& xyz, NodeType* node) { mCache.insert(xyz, node); }
// Define a list of all tree node types from LeafNode to RootNode
using InvTreeT = typename RootNodeT::NodeChainType;
// Remove all tree node types that are excluded from the cache
static constexpr int64_t First = CacheLevels;
static constexpr int64_t Last = InvTreeT::template Index<RootNodeT>;
using SubtreeT = typename InvTreeT::template RemoveByIndex<First, Last-1>;
using CacheItemT = CacheItem<ValueAccessor, SubtreeT, SubtreeT::Size==1>;
// Private member data
mutable CacheItemT mCache;
mutable MutexType mMutex;
}; // class ValueAccessor
/// @brief Template specialization of the ValueAccessor with no mutex and no cache levels
/// @details This specialization is provided mainly for benchmarking.
/// Accessors with caching will almost always be faster.
template<typename TreeType, bool IsSafe>
class ValueAccessor<TreeType, IsSafe, 0, tbb::null_mutex>
: public ValueAccessor0<TreeType, IsSafe>
{
public:
ValueAccessor(TreeType& tree): ValueAccessor0<TreeType, IsSafe>(tree) {}
ValueAccessor(const ValueAccessor& other): ValueAccessor0<TreeType, IsSafe>(other) {}
~ValueAccessor() override = default;
};
/// Template specialization of the ValueAccessor with no mutex and one cache level
template<typename TreeType, bool IsSafe>
class ValueAccessor<TreeType, IsSafe, 1, tbb::null_mutex>
: public ValueAccessor1<TreeType, IsSafe>
{
public:
ValueAccessor(TreeType& tree): ValueAccessor1<TreeType, IsSafe>(tree) {}
ValueAccessor(const ValueAccessor& other): ValueAccessor1<TreeType, IsSafe>(other) {}
~ValueAccessor() override = default;
};
/// Template specialization of the ValueAccessor with no mutex and two cache levels
template<typename TreeType, bool IsSafe>
class ValueAccessor<TreeType, IsSafe, 2, tbb::null_mutex>
: public ValueAccessor2<TreeType, IsSafe>
{
public:
ValueAccessor(TreeType& tree): ValueAccessor2<TreeType, IsSafe>(tree) {}
ValueAccessor(const ValueAccessor& other): ValueAccessor2<TreeType, IsSafe>(other) {}
~ValueAccessor() override = default;
};
/// Template specialization of the ValueAccessor with no mutex and three cache levels
template<typename TreeType, bool IsSafe>
class ValueAccessor<TreeType, IsSafe, 3, tbb::null_mutex>: public ValueAccessor3<TreeType, IsSafe>
{
public:
ValueAccessor(TreeType& tree): ValueAccessor3<TreeType, IsSafe>(tree) {}
ValueAccessor(const ValueAccessor&) = default;
ValueAccessor& operator=(const ValueAccessor&) = default;
~ValueAccessor() override = default;
};
////////////////////////////////////////
/// @brief This accessor is thread-safe (at the cost of speed) for both reading and
/// writing to a tree. That is, multiple threads may safely access a single,
/// shared ValueAccessorRW.
///
/// @warning Since the mutex-locking employed by the ValueAccessorRW
/// can seriously impair performance of multithreaded applications, it
/// is recommended that, instead, each thread be assigned its own
/// (non-mutex protected) accessor.
template<typename TreeType, bool IsSafe = true>
class ValueAccessorRW: public ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>
{
public:
ValueAccessorRW(TreeType& tree)
: ValueAccessor<TreeType, IsSafe, TreeType::DEPTH-1, tbb::spin_mutex>(tree)
{
}
};
////////////////////////////////////////
//
// The classes below are for internal use and should rarely be used directly.
//
// An element of a compile-time linked list of node pointers, ordered from LeafNode to RootNode
template<typename TreeCacheT, typename NodeVecT, bool AtRoot
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, bool BypassLeafAPI
#endif
>
class CacheItem
{
public:
using NodeType = typename NodeVecT::Front;
using ValueType = typename NodeType::ValueType;
using LeafNodeType = typename NodeType::LeafNodeType;
using CoordLimits = std::numeric_limits<Int32>;
CacheItem(TreeCacheT& parent)
: mParent(&parent)
, mHash(CoordLimits::max())
, mNode(nullptr)
, mNext(parent)
{
}
//@{
/// Copy another CacheItem's node pointers and hash keys, but not its parent pointer.
CacheItem(TreeCacheT& parent, const CacheItem& other)
: mParent(&parent)
, mHash(other.mHash)
, mNode(other.mNode)
, mNext(parent, other.mNext)
{
}
CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
{
mParent = &parent;
mHash = other.mHash;
mNode = other.mNode;
mNext.copy(parent, other.mNext);
return *this;
}
//@}
bool isCached(const Coord& xyz) const
{
return (this->isHashed(xyz) || mNext.isCached(xyz));
}
/// Cache the given node at this level.
void insert(const Coord& xyz, const NodeType* node)
{
mHash = (node != nullptr) ? xyz & ~(NodeType::DIM-1) : Coord::max();
mNode = node;
}
/// Forward the given node to another level of the cache.
template<typename OtherNodeType>
void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
/// Erase the node at this level.
void erase(const NodeType*) { mHash = Coord::max(); mNode = nullptr; }
/// Erase the node at another level of the cache.
template<typename OtherNodeType>
void erase(const OtherNodeType* node) { mNext.erase(node); }
/// Erase the nodes at this and lower levels of the cache.
void clear() { mHash = Coord::max(); mNode = nullptr; mNext.clear(); }
/// Return the cached node (if any) at this level.
void getNode(const NodeType*& node) const { node = mNode; }
void getNode(const NodeType*& node) { node = mNode; }
void getNode(NodeType*& node)
{
// This combination of a static assertion and a const_cast might not be elegant,
// but it is a lot simpler than specializing TreeCache for const Trees.
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
node = const_cast<NodeType*>(mNode);
}
/// Forward the request to another level of the cache.
template<typename OtherNodeType>
void getNode(OtherNodeType*& node) { mNext.getNode(node); }
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->getValueAndCache(xyz, *mParent);
}
return mNext.getValue(xyz);
}
void addLeaf(LeafNodeType* leaf)
{
static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
if (NodeType::LEVEL == 0) {
mNext.addLeaf(leaf);
return;
}
if (this->isHashed(leaf->origin())) {
assert(mNode);
return const_cast<NodeType*>(mNode)->addLeafAndCache(leaf, *mParent);
}
else {
mNext.addLeaf(leaf);
}
}
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
if (NodeType::LEVEL >= level && this->isHashed(xyz)) {
assert(mNode);
const_cast<NodeType*>(mNode)->addTileAndCache(level, xyz, value, state, *mParent);
return;
}
mNext.addTile(level, xyz, value, state);
}
LeafNodeType* touchLeaf(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed(xyz)) {
assert(mNode);
return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
}
return mNext.touchLeaf(xyz);
}
LeafNodeType* probeLeaf(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed(xyz)) {
assert(mNode);
return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
}
return mNext.probeLeaf(xyz);
}
const LeafNodeType* probeConstLeaf(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->probeConstLeafAndCache(xyz, *mParent);
}
return mNext.probeConstLeaf(xyz);
}
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if constexpr ((std::is_same<NodeT, NodeType>::value)) {
if (this->isHashed(xyz)) {
assert(mNode);
return reinterpret_cast<NodeT*>(const_cast<NodeType*>(mNode));
}
}
if (NodeT::LEVEL < NodeType::LEVEL && mNode) {
// don't need to ascend the chain, descend the tree
return const_cast<NodeType*>(mNode)->template probeNodeAndCache<NodeT>(xyz, *mParent);
}
else {
// ascend
return mNext.template probeNode<NodeT>(xyz);
}
}
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz)
{
if constexpr ((std::is_same<NodeT, NodeType>::value)) {
if (this->isHashed(xyz)) {
assert(mNode);
return reinterpret_cast<const NodeT*>(mNode);
}
}
if (NodeT::LEVEL < NodeType::LEVEL && mNode) {
// don't need to ascend the chain, descend the tree
return mNode->template probeConstNodeAndCache<NodeT>(xyz, *mParent);
}
else {
// ascend
return mNext.template probeConstNode<NodeT>(xyz);
}
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->isValueOnAndCache(xyz, *mParent);
}
return mNext.isValueOn(xyz);
}
/// Return the active state and value of the voxel at the given coordinates.
bool probeValue(const Coord& xyz, ValueType& value)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->probeValueAndCache(xyz, value, *mParent);
}
return mNext.probeValue(xyz, value);
}
int getValueDepth(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
} else {
return mNext.getValueDepth(xyz);
}
}
bool isVoxel(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->getValueLevelAndCache(xyz, *mParent)==0;
} else {
return mNext.isVoxel(xyz);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->setValueAndCache(xyz, value, *mParent);
} else {
mNext.setValue(xyz, value);
}
}
void setValueOnly(const Coord& xyz, const ValueType& value)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
} else {
mNext.setValueOnly(xyz, value);
}
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->modifyValueAndCache(xyz, op, *mParent);
} else {
mNext.modifyValue(xyz, op);
}
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
} else {
mNext.modifyValueAndActiveState(xyz, op);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->setValueOffAndCache(xyz, value, *mParent);
} else {
mNext.setValueOff(xyz, value);
}
}
/// Set the active state of the voxel at the given coordinates.
void setActiveState(const Coord& xyz, bool on)
{
if (this->isHashed(xyz)) {
assert(mNode);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<NodeType*>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
} else {
mNext.setActiveState(xyz, on);
}
}
private:
CacheItem(const CacheItem&);
CacheItem& operator=(const CacheItem&);
bool isHashed(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
&& (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
&& (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
}
TreeCacheT* mParent;
Coord mHash;
const NodeType* mNode;
using RestT = typename NodeVecT::PopFront;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// Next item is never a leaf node as a leaf node is only ever at
// the front of the chain
CacheItem<TreeCacheT, RestT, /*AtRoot=*/RestT::Size == 1, false> mNext;
#else
CacheItem<TreeCacheT, RestT, /*AtRoot=*/RestT::Size == 1> mNext;
#endif
};// end of CacheItem
#if OPENVDB_ABI_VERSION_NUMBER >= 10
template<typename TreeCacheT, typename NodeVecT>
class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/false, true>
{
public:
using NodeType = typename NodeVecT::Front;
using ValueType = typename NodeType::ValueType;
using LeafNodeType = typename NodeType::LeafNodeType;
using CoordLimits = std::numeric_limits<Int32>;
static_assert(std::is_same<NodeType, LeafNodeType>::value);
CacheItem(TreeCacheT& parent)
: mParent(&parent)
, mHash(CoordLimits::max())
, mNode(nullptr)
, mNext(parent)
, mBuffer(nullptr) {}
//@{
/// Copy another CacheItem's node pointers and hash keys, but not its parent pointer.
CacheItem(TreeCacheT& parent, const CacheItem& other)
: mParent(&parent)
, mHash(other.mHash)
, mNode(other.mNode)
, mNext(parent, other.mNext)
, mBuffer(other.mBuffer) {}
CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
{
mParent = &parent;
mHash = other.mHash;
mNode = other.mNode;
mNext.copy(parent, other.mNext);
mBuffer = other.mBuffer;
return *this;
}
//@}
bool isCached(const Coord& xyz) const
{
return (this->isHashed(xyz) || mNext.isCached(xyz));
}
/// Cache the given node at this level.
void insert(const Coord& xyz, const NodeType* node)
{
mHash = (node != nullptr) ? xyz & ~(NodeType::DIM-1) : Coord::max();
mNode = node;
mBuffer = node ? node->buffer().data() : nullptr;
}
/// Forward the given node to another level of the cache.
template<typename OtherNodeType>
void insert(const Coord& xyz, const OtherNodeType* node) { mNext.insert(xyz, node); }
/// Erase the node at this level.
void erase(const NodeType*) { mHash = Coord::max(); mNode = nullptr; }
/// Erase the node at another level of the cache.
template<typename OtherNodeType>
void erase(const OtherNodeType* node) { mNext.erase(node); }
/// Erase the nodes at this and lower levels of the cache.
void clear() { mHash = Coord::max(); mNode = nullptr; mNext.clear(); }
/// Return the cached node (if any) at this level.
void getNode(const NodeType*& node) const { node = mNode; }
void getNode(const NodeType*& node) { node = mNode; }
void getNode(NodeType*& node)
{
// This combination of a static assertion and a const_cast might not be elegant,
// but it is a lot simpler than specializing TreeCache for const Trees.
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
node = const_cast<NodeType*>(mNode);
}
/// Forward the request to another level of the cache.
template<typename OtherNodeType>
void getNode(OtherNodeType*& node) { mNext.getNode(node); }
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mBuffer[LeafNodeType::coordToOffset(xyz)];
}
return mNext.getValue(xyz);
}
void addLeaf(LeafNodeType* leaf)
{
mNext.addLeaf(leaf);
}
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
if (NodeType::LEVEL >= level && this->isHashed(xyz)) {
assert(mNode);
const_cast<NodeType*>(mNode)->addTileAndCache(level, xyz, value, state, *mParent);
return;
}
mNext.addTile(level, xyz, value, state);
}
LeafNodeType* touchLeaf(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed(xyz)) {
assert(mNode);
return const_cast<NodeType*>(mNode)->touchLeafAndCache(xyz, *mParent);
}
return mNext.touchLeaf(xyz);
}
LeafNodeType* probeLeaf(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed(xyz)) {
assert(mNode);
return const_cast<NodeType*>(mNode)->probeLeafAndCache(xyz, *mParent);
}
return mNext.probeLeaf(xyz);
}
const LeafNodeType* probeConstLeaf(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->probeConstLeafAndCache(xyz, *mParent);
}
return mNext.probeConstLeaf(xyz);
}
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
if constexpr ((std::is_same<NodeT, NodeType>::value)) {
if (this->isHashed(xyz)) {
assert(mNode);
return reinterpret_cast<NodeT*>(const_cast<NodeType*>(mNode));
}
}
if (NodeT::LEVEL < NodeType::LEVEL && mNode) {
// don't need to ascend the chain, descend the tree
return const_cast<NodeType*>(mNode)->template probeNodeAndCache<NodeT>(xyz, *mParent);
}
else {
// ascend
return mNext.template probeNode<NodeT>(xyz);
}
}
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz)
{
if constexpr ((std::is_same<NodeT, NodeType>::value)) {
if (this->isHashed(xyz)) {
assert(mNode);
return reinterpret_cast<const NodeT*>(mNode);
}
}
if (NodeT::LEVEL < NodeType::LEVEL && mNode) {
// don't need to ascend the chain, descend the tree
return mNode->template probeConstNodeAndCache<NodeT>(xyz, *mParent);
}
else {
// ascend
return mNext.template probeConstNode<NodeT>(xyz);
}
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->isValueOnAndCache(xyz, *mParent);
}
return mNext.isValueOn(xyz);
}
/// Return the active state and value of the voxel at the given coordinates.
bool probeValue(const Coord& xyz, ValueType& value)
{
if (this->isHashed(xyz)) {
assert(mNode);
assert(mBuffer);
const auto offset = LeafNodeType::coordToOffset(xyz);
value = mBuffer[offset];
return mNode->isValueOn(offset);
}
return mNext.probeValue(xyz, value);
}
int getValueDepth(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
} else {
return mNext.getValueDepth(xyz);
}
}
bool isVoxel(const Coord& xyz)
{
if (this->isHashed(xyz)) {
assert(mNode);
return mNode->getValueLevelAndCache(xyz, *mParent)==0;
} else {
return mNext.isVoxel(xyz);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
assert(mBuffer);
const auto offset = LeafNodeType::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
const_cast<NodeType*>(mNode)->setValueOn(offset);
} else {
mNext.setValue(xyz, value);
}
}
void setValueOnly(const Coord& xyz, const ValueType& value)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
assert(mBuffer);
const auto offset = LeafNodeType::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
} else {
mNext.setValueOnly(xyz, value);
}
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
assert(mBuffer);
const auto offset = LeafNodeType::coordToOffset(xyz);
op(const_cast<ValueType&>(mBuffer[offset]));
const_cast<NodeType*>(mNode)->setActiveState(offset, true);
} else {
mNext.modifyValue(xyz, op);
}
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
assert(mBuffer);
const auto offset = LeafNodeType::coordToOffset(xyz);
bool state = mNode->isValueOn(offset);
op(const_cast<ValueType&>(mBuffer[offset]), state);
const_cast<NodeType*>(mNode)->setActiveState(offset, state);
} else {
mNext.modifyValueAndActiveState(xyz, op);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
const_cast<NodeType*>(mNode)->setValueOffAndCache(xyz, value, *mParent);
} else {
mNext.setValueOff(xyz, value);
}
}
/// Set the active state of the voxel at the given coordinates.
void setActiveState(const Coord& xyz, bool on)
{
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode);
const_cast<NodeType*>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
} else {
mNext.setActiveState(xyz, on);
}
}
private:
CacheItem(const CacheItem&);
CacheItem& operator=(const CacheItem&);
bool isHashed(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
&& (xyz[1] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[1]
&& (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
}
TreeCacheT* mParent;
Coord mHash;
const NodeType* mNode;
using RestT = typename NodeVecT::PopFront;
CacheItem<TreeCacheT, RestT, /*AtRoot=*/RestT::Size == 1> mNext;
const ValueType* mBuffer;
};// end of CacheItem
#endif
/// The tail of a compile-time list of cached node pointers, ordered from LeafNode to RootNode
template<typename TreeCacheT, typename NodeVecT>
class CacheItem<TreeCacheT, NodeVecT, /*AtRoot=*/true
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, /*BypassLeafAPI=*/false
#endif
>
{
public:
using RootNodeType = typename NodeVecT::Front;
using ValueType = typename RootNodeType::ValueType;
using LeafNodeType = typename RootNodeType::LeafNodeType;
CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(nullptr) {}
CacheItem(TreeCacheT& parent, const CacheItem& other): mParent(&parent), mRoot(other.mRoot) {}
CacheItem& copy(TreeCacheT& parent, const CacheItem& other)
{
mParent = &parent;
mRoot = other.mRoot;
return *this;
}
bool isCached(const Coord& xyz) const { return this->isHashed(xyz); }
void insert(const Coord&, const RootNodeType* root) { mRoot = root; }
// Needed for node types that are not cached
template<typename OtherNodeType>
void insert(const Coord&, const OtherNodeType*) {}
void erase(const RootNodeType*) { mRoot = nullptr; }
void clear() { mRoot = nullptr; }
void getNode(RootNodeType*& node)
{
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
node = const_cast<RootNodeType*>(mRoot);
}
void getNode(const RootNodeType*& node) const { node = mRoot; }
void addLeaf(LeafNodeType* leaf)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't add a node to a const tree");
const_cast<RootNodeType*>(mRoot)->addLeafAndCache(leaf, *mParent);
}
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't add a tile to a const tree");
const_cast<RootNodeType*>(mRoot)->addTileAndCache(level, xyz, value, state, *mParent);
}
LeafNodeType* touchLeaf(const Coord& xyz)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
return const_cast<RootNodeType*>(mRoot)->touchLeafAndCache(xyz, *mParent);
}
LeafNodeType* probeLeaf(const Coord& xyz)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
return const_cast<RootNodeType*>(mRoot)->probeLeafAndCache(xyz, *mParent);
}
const LeafNodeType* probeConstLeaf(const Coord& xyz)
{
assert(mRoot);
return mRoot->probeConstLeafAndCache(xyz, *mParent);
}
template<typename NodeType>
NodeType* probeNode(const Coord& xyz)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't get a non-const node from a const tree");
return const_cast<RootNodeType*>(mRoot)->
template probeNodeAndCache<NodeType>(xyz, *mParent);
}
template<typename NodeType>
const NodeType* probeConstNode(const Coord& xyz)
{
assert(mRoot);
return mRoot->template probeConstNodeAndCache<NodeType>(xyz, *mParent);
}
int getValueDepth(const Coord& xyz)
{
assert(mRoot);
return mRoot->getValueDepthAndCache(xyz, *mParent);
}
bool isValueOn(const Coord& xyz)
{
assert(mRoot);
return mRoot->isValueOnAndCache(xyz, *mParent);
}
bool probeValue(const Coord& xyz, ValueType& value)
{
assert(mRoot);
return mRoot->probeValueAndCache(xyz, value, *mParent);
}
bool isVoxel(const Coord& xyz)
{
assert(mRoot);
return mRoot->getValueDepthAndCache(xyz, *mParent) ==
static_cast<int>(RootNodeType::LEVEL);
}
const ValueType& getValue(const Coord& xyz)
{
assert(mRoot);
return mRoot->getValueAndCache(xyz, *mParent);
}
void setValue(const Coord& xyz, const ValueType& value)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->setValueAndCache(xyz, value, *mParent);
}
void setValueOnly(const Coord& xyz, const ValueType& value)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->modifyValueAndCache(xyz, op, *mParent);
}
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
}
void setValueOff(const Coord& xyz, const ValueType& value)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
}
void setActiveState(const Coord& xyz, bool on)
{
assert(mRoot);
static_assert(!TreeCacheT::IsConstTree, "can't modify a const tree's values");
const_cast<RootNodeType*>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
}
private:
CacheItem(const CacheItem&);
CacheItem& operator=(const CacheItem&);
bool isHashed(const Coord&) const { return false; }
TreeCacheT* mParent;
const RootNodeType* mRoot;
};// end of CacheItem specialized for RootNode
////////////////////////////////////////
/// @brief ValueAccessor with no mutex and no node caching.
/// @details This specialization is provided mainly for benchmarking.
/// Accessors with caching will almost always be faster.
template<typename _TreeType, bool IsSafe>
class ValueAccessor0: public ValueAccessorBase<_TreeType, IsSafe>
{
public:
using TreeType = _TreeType;
using ValueType = typename TreeType::ValueType;
using RootNodeT = typename TreeType::RootNodeType;
using LeafNodeT = typename TreeType::LeafNodeType;
using BaseT = ValueAccessorBase<TreeType, IsSafe>;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// No caching, nothing to do
static constexpr bool BypassLeafAPI = false;
#endif
ValueAccessor0(TreeType& tree): BaseT(tree) {}
ValueAccessor0(const ValueAccessor0& other): BaseT(other) {}
/// Return the number of cache levels employed by this accessor.
static Index numCacheLevels() { return 0; }
ValueAccessor0& operator=(const ValueAccessor0& other)
{
if (&other != this) this->BaseT::operator=(other);
return *this;
}
~ValueAccessor0() override = default;
/// Return @c true if nodes along the path to the given voxel have been cached.
bool isCached(const Coord&) const { return false; }
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz) const
{
assert(BaseT::mTree);
return BaseT::mTree->getValue(xyz);
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz) const
{
assert(BaseT::mTree);
return BaseT::mTree->isValueOn(xyz);
}
/// Return the active state and, in @a value, the value of the voxel at the given coordinates.
bool probeValue(const Coord& xyz, ValueType& value) const
{
assert(BaseT::mTree);
return BaseT::mTree->probeValue(xyz, value);
}
/// Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides,
/// or -1 if (x, y, z) isn't explicitly represented in the tree (i.e., if it is
/// implicitly a background voxel).
int getValueDepth(const Coord& xyz) const
{
assert(BaseT::mTree);
return BaseT::mTree->getValueDepth(xyz);
}
/// Return @c true if the value of voxel (x, y, z) resides at the leaf level
/// of the tree, i.e., if it is not a tile value.
bool isVoxel(const Coord& xyz) const
{
assert(BaseT::mTree);
return BaseT::mTree->getValueDepth(xyz) == static_cast<int>(RootNodeT::LEVEL);
}
//@{
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->setValue(xyz, value);
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
//@}
/// Set the value of the voxel at the given coordinate but don't change its active state.
void setValueOnly(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->setValueOnly(xyz, value);
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->root().setValueOff(xyz, value);
}
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->modifyValue(xyz, op);
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->modifyValueAndActiveState(xyz, op);
}
/// Set the active state of the voxel at the given coordinates but don't change its value.
void setActiveState(const Coord& xyz, bool on = true)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
BaseT::mTree->setActiveState(xyz, on);
}
/// Mark the voxel at the given coordinates as active but don't change its value.
void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
/// Mark the voxel at the given coordinates as inactive but don't change its value.
void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
/// Return the cached node of type @a NodeType. [Mainly for internal use]
template<typename NodeT> NodeT* getNode() { return nullptr; }
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z). [Mainly for internal use]
template<typename NodeT> void insertNode(const Coord&, NodeT&) {}
/// @brief Add the specified leaf to this tree, possibly creating a child branch
/// in the process. If the leaf node already exists, replace it.
void addLeaf(LeafNodeT* leaf)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
BaseT::mTree->root().addLeaf(leaf);
}
/// @brief Add a tile at the specified tree level that contains voxel (x, y, z),
/// possibly deleting existing nodes or creating new nodes in the process.
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
BaseT::mTree->root().addTile(level, xyz, value, state);
}
/// If a node of the given type exists in the cache, remove it, so that
/// isCached(xyz) returns @c false for any voxel (x, y, z) contained in
/// that node. [Mainly for internal use]
template<typename NodeT> void eraseNode() {}
LeafNodeT* touchLeaf(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
return BaseT::mTree->touchLeaf(xyz);
}
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
return BaseT::mTree->template probeNode<NodeT>(xyz);
}
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz) const
{
assert(BaseT::mTree);
return BaseT::mTree->template probeConstNode<NodeT>(xyz);
}
LeafNodeT* probeLeaf(const Coord& xyz)
{
return this->template probeNode<LeafNodeT>(xyz);
}
const LeafNodeT* probeConstLeaf(const Coord& xyz) const
{
return this->template probeConstNode<LeafNodeT>(xyz);
}
const LeafNodeT* probeLeaf(const Coord& xyz) const
{
return this->probeConstLeaf(xyz);
}
/// Remove all nodes from this cache, then reinsert the root node.
void clear() override {}
private:
// Allow trees to deregister themselves.
template<typename> friend class Tree;
/// Prevent this accessor from calling Tree::releaseCache() on a tree that
/// no longer exists. (Called by mTree when it is destroyed.)
void release() override { this->BaseT::release(); }
}; // ValueAccessor0
/// @brief Value accessor with one level of node caching.
/// @details The node cache level is specified by L0 with the default value 0
/// (defined in the forward declaration) corresponding to a LeafNode.
///
/// @note This class is for experts only and should rarely be used
/// directly. Instead use ValueAccessor with its default template arguments.
template<typename _TreeType, bool IsSafe, Index L0>
class ValueAccessor1 : public ValueAccessorBase<_TreeType, IsSafe>
{
public:
static_assert(_TreeType::DEPTH >= 2, "cache size exceeds tree depth");
static_assert(L0 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
using TreeType = _TreeType;
using ValueType = typename TreeType::ValueType;
using RootNodeT = typename TreeType::RootNodeType;
using LeafNodeT = typename TreeType::LeafNodeType;
using BaseT = ValueAccessorBase<TreeType, IsSafe>;
using InvTreeT = typename RootNodeT::NodeChainType;
using NodeT0 = typename InvTreeT::template Get<L0>;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// If the last node being cached is a leaf node and the storage type matches
// the ValueType, we can cache the buffer pointer instead of using the delay
// load locked leaf API
static constexpr bool BypassLeafAPI =
std::is_same<NodeT0, LeafNodeT>::value &&
std::is_same<typename LeafNodeT::Buffer::StorageType, ValueType>::value;
#endif
/// Constructor from a tree
ValueAccessor1(TreeType& tree)
: BaseT(tree)
, mKey0(Coord::max()), mNode0(nullptr)
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, mBuffer(nullptr)
#endif
{}
/// Copy constructor
ValueAccessor1(const ValueAccessor1& other) : BaseT(other) { this->copy(other); }
/// Return the number of cache levels employed by this ValueAccessor
static Index numCacheLevels() { return 1; }
/// Assignment operator
ValueAccessor1& operator=(const ValueAccessor1& other)
{
if (&other != this) {
this->BaseT::operator=(other);
this->copy(other);
}
return *this;
}
/// Virtual destructor
~ValueAccessor1() override = default;
/// Return @c true if any of the nodes along the path to the given
/// voxel have been cached.
bool isCached(const Coord& xyz) const
{
assert(BaseT::mTree);
return this->isHashed(xyz);
}
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
return mBuffer[LeafNodeT::coordToOffset(xyz)];
}
#endif
return mNode0->getValueAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueAndCache(xyz, this->self());
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed(xyz)) {
assert(mNode0);
return mNode0->isValueOnAndCache(xyz, this->self());
}
return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
}
/// Return the active state of the voxel as well as its value
bool probeValue(const Coord& xyz, ValueType& value) const
{
assert(BaseT::mTree);
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
value = mBuffer[offset];
return mNode0->isValueOn(offset);
}
#endif
return mNode0->probeValueAndCache(xyz, value, this->self());
}
return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
}
/// Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides,
/// or -1 if (x, y, z) isn't explicitly represented in the tree (i.e., if it is
/// implicitly a background voxel).
int getValueDepth(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed(xyz)) {
assert(mNode0);
return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
}
/// Return @c true if the value of voxel (x, y, z) resides at the leaf level
/// of the tree, i.e., if it is not a tile value.
bool isVoxel(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed(xyz)) {
assert(mNode0);
return mNode0->getValueLevelAndCache(xyz, this->self()) == 0;
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
static_cast<int>(RootNodeT::LEVEL);
}
//@{
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
const_cast<NodeT0*>(mNode0)->setValueOn(offset);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueAndCache(xyz, value, *this);
}
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
//@}
/// Set the value of the voxel at the given coordinate but preserves its active state.
void setValueOnly(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
}
}
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
op(const_cast<ValueType&>(mBuffer[offset]));
const_cast<NodeT0*>(mNode0)->setActiveState(offset, true);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
}
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
bool state = mNode0->isValueOn(offset);
op(const_cast<ValueType&>(mBuffer[offset]), state);
const_cast<NodeT0*>(mNode0)->setActiveState(offset, state);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
}
}
/// Set the active state of the voxel at the given coordinates but don't change its value.
void setActiveState(const Coord& xyz, bool on = true)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
} else {
BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
}
}
/// Mark the voxel at the given coordinates as active but don't change its value.
void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
/// Mark the voxel at the given coordinates as inactive but don't change its value.
void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
/// Return the cached node of type @a NodeType. [Mainly for internal use]
template<typename NodeT>
NodeT* getNode()
{
const NodeT* node = nullptr;
this->getNode(node);
return const_cast<NodeT*>(node);
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z). [Mainly for internal use]
template<typename NodeT>
void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
/// If a node of the given type exists in the cache, remove it, so that
/// isCached(xyz) returns @c false for any voxel (x, y, z) contained in
/// that node. [Mainly for internal use]
template<typename NodeT>
void eraseNode()
{
const NodeT* node = nullptr;
this->eraseNode(node);
}
/// @brief Add the specified leaf to this tree, possibly creating a child branch
/// in the process. If the leaf node already exists, replace it.
void addLeaf(LeafNodeT* leaf)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
BaseT::mTree->root().addLeaf(leaf);
}
/// @brief Add a tile at the specified tree level that contains voxel (x, y, z),
/// possibly deleting existing nodes or creating new nodes in the process.
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
BaseT::mTree->root().addTile(level, xyz, value, state);
}
/// @brief @return the leaf node that contains voxel (x, y, z) and
/// if it doesn't exist, create it, but preserve the values and
/// active states of all voxels.
///
/// Use this method to preallocate a static tree topology over which to
/// safely perform multithreaded processing.
LeafNodeT* touchLeaf(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed(xyz)) {
assert(mNode0);
return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
}
return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
}
/// @brief @return a pointer to the node of the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed(xyz)) {
assert(mNode0);
return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr (NodeT::LEVEL < NodeT0::LEVEL) {
// Might still be worth caching this path if a NodeT0
// is accessed in the future
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeNode<NodeT>(xyz);
}
}
LeafNodeT* probeLeaf(const Coord& xyz)
{
return this->template probeNode<LeafNodeT>(xyz);
}
/// @brief @return a const pointer to the nodeof the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz) const
{
assert(BaseT::mTree);
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed(xyz)) {
assert(mNode0);
return reinterpret_cast<const NodeT*>(mNode0);
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr (NodeT::LEVEL < NodeT0::LEVEL) {
// Might still be worth caching this path if a NodeT0
// is accessed in the future
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeConstNode<NodeT>(xyz);
}
}
const LeafNodeT* probeConstLeaf(const Coord& xyz) const
{
return this->template probeConstNode<LeafNodeT>(xyz);
}
const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
/// Remove all the cached nodes and invalidate the corresponding hash-keys.
void clear() override
{
mKey0 = Coord::max();
mNode0 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
private:
// Allow nodes to insert themselves into the cache.
template<typename> friend class RootNode;
template<typename, Index> friend class InternalNode;
template<typename, Index> friend class LeafNode;
// Allow trees to deregister themselves.
template<typename> friend class Tree;
// This private method is merely for convenience.
inline ValueAccessor1& self() const { return const_cast<ValueAccessor1&>(*this); }
void getNode(const NodeT0*& node) { node = mNode0; }
void getNode(const RootNodeT*& node)
{
node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
}
template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
void eraseNode(const NodeT0*)
{
mKey0 = Coord::max();
mNode0 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
/// Private copy method
inline void copy(const ValueAccessor1& other)
{
mKey0 = other.mKey0;
mNode0 = other.mNode0;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = other.mBuffer;
#endif
}
/// Prevent this accessor from calling Tree::releaseCache() on a tree that
/// no longer exists. (Called by mTree when it is destroyed.)
void release() override
{
this->BaseT::release();
this->clear();
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z).
/// @note This operation is not mutex-protected and is intended to be called
/// only by nodes and only in the context of a getValue() or setValue() call.
inline void insert(const Coord& xyz, const NodeT0* node)
{
assert(node);
mKey0 = xyz & ~(NodeT0::DIM-1);
mNode0 = node;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
mBuffer = node->buffer().data();
}
#endif
}
/// No-op in case a tree traversal attemps to insert a node that
/// is not cached by the ValueAccessor
template<typename OtherNodeType> inline void insert(const Coord&, const OtherNodeType*) {}
inline bool isHashed(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
&& (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
&& (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
}
mutable Coord mKey0;
mutable const NodeT0* mNode0;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mutable const ValueType* mBuffer;
#endif
}; // ValueAccessor1
/// @brief Value accessor with two levels of node caching.
/// @details The node cache levels are specified by L0 and L1
/// with the default values 0 and 1 (defined in the forward declaration)
/// corresponding to a LeafNode and its parent InternalNode.
///
/// @note This class is for experts only and should rarely be used directly.
/// Instead use ValueAccessor with its default template arguments.
template<typename _TreeType, bool IsSafe, Index L0, Index L1>
class ValueAccessor2 : public ValueAccessorBase<_TreeType, IsSafe>
{
public:
static_assert(_TreeType::DEPTH >= 3, "cache size exceeds tree depth");
static_assert(L0 < L1, "invalid cache level");
static_assert(L1 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
using TreeType = _TreeType;
using ValueType = typename TreeType::ValueType;
using RootNodeT = typename TreeType::RootNodeType;
using LeafNodeT = typename TreeType::LeafNodeType;
using BaseT = ValueAccessorBase<TreeType, IsSafe>;
using InvTreeT = typename RootNodeT::NodeChainType;
using NodeT0 = typename InvTreeT::template Get<L0>;
using NodeT1 = typename InvTreeT::template Get<L1>;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// If the last node being cached is a leaf node and the storage type matches
// the ValueType, we can cache the buffer pointer instead of using the delay
// load locked leaf API
static constexpr bool BypassLeafAPI =
std::is_same<NodeT0, LeafNodeT>::value &&
std::is_same<typename LeafNodeT::Buffer::StorageType, ValueType>::value;
#endif
/// Constructor from a tree
ValueAccessor2(TreeType& tree)
: BaseT(tree)
, mKey0(Coord::max()), mNode0(nullptr)
, mKey1(Coord::max()), mNode1(nullptr)
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, mBuffer(nullptr)
#endif
{}
/// Copy constructor
ValueAccessor2(const ValueAccessor2& other) : BaseT(other) { this->copy(other); }
/// Return the number of cache levels employed by this ValueAccessor
static Index numCacheLevels() { return 2; }
/// Assignment operator
ValueAccessor2& operator=(const ValueAccessor2& other)
{
if (&other != this) {
this->BaseT::operator=(other);
this->copy(other);
}
return *this;
}
/// Virtual destructor
~ValueAccessor2() override = default;
/// Return @c true if any of the nodes along the path to the given
/// voxel have been cached.
bool isCached(const Coord& xyz) const
{
assert(BaseT::mTree);
return this->isHashed1(xyz) || this->isHashed0(xyz);
}
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
return mBuffer[LeafNodeT::coordToOffset(xyz)];
}
#endif
return mNode0->getValueAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->getValueAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueAndCache(xyz, this->self());
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return mNode0->isValueOnAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->isValueOnAndCache(xyz, this->self());
}
return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
}
/// Return the active state of the voxel as well as its value
bool probeValue(const Coord& xyz, ValueType& value) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
value = mBuffer[offset];
return mNode0->isValueOn(offset);
}
#endif
return mNode0->probeValueAndCache(xyz, value, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->probeValueAndCache(xyz, value, this->self());
}
return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
}
/// Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides,
/// or -1 if (x, y, z) isn't explicitly represented in the tree (i.e., if it is
/// implicitly a background voxel).
int getValueDepth(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
}
/// Return @c true if the value of voxel (x, y, z) resides at the leaf level
/// of the tree, i.e., if it is not a tile value.
bool isVoxel(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return mNode0->getValueLevelAndCache(xyz, this->self())==0;
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->getValueLevelAndCache(xyz, this->self())==0;
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
static_cast<int>(RootNodeT::LEVEL);
}
//@{
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
const_cast<NodeT0*>(mNode0)->setValueOn(offset);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueAndCache(xyz, value, *this);
}
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
//@}
/// Set the value of the voxel at the given coordinate but preserves its active state.
void setValueOnly(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
}
}
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
op(const_cast<ValueType&>(mBuffer[offset]));
const_cast<NodeT0*>(mNode0)->setActiveState(offset, true);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
}
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
bool state = mNode0->isValueOn(offset);
op(const_cast<ValueType&>(mBuffer[offset]), state);
const_cast<NodeT0*>(mNode0)->setActiveState(offset, state);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
}
}
/// Set the active state of the voxel at the given coordinates without changing its value.
void setActiveState(const Coord& xyz, bool on = true)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
} else {
BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
}
}
/// Mark the voxel at the given coordinates as active without changing its value.
void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
/// Mark the voxel at the given coordinates as inactive without changing its value.
void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
/// Return the cached node of type @a NodeType. [Mainly for internal use]
template<typename NodeT>
NodeT* getNode()
{
const NodeT* node = nullptr;
this->getNode(node);
return const_cast<NodeT*>(node);
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z). [Mainly for internal use]
template<typename NodeT>
void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
/// If a node of the given type exists in the cache, remove it, so that
/// isCached(xyz) returns @c false for any voxel (x, y, z) contained in
/// that node. [Mainly for internal use]
template<typename NodeT>
void eraseNode()
{
const NodeT* node = nullptr;
this->eraseNode(node);
}
/// @brief Add the specified leaf to this tree, possibly creating a child branch
/// in the process. If the leaf node already exists, replace it.
void addLeaf(LeafNodeT* leaf)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
if (this->isHashed1(leaf->origin())) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
}
BaseT::mTree->root().addLeafAndCache(leaf, *this);
}
/// @brief Add a tile at the specified tree level that contains voxel (x, y, z),
/// possibly deleting existing nodes or creating new nodes in the process.
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
}
BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
}
/// @brief @return the leaf node that contains voxel (x, y, z) and
/// if it doesn't exist, create it, but preserve the values and
/// active states of all voxels.
///
/// Use this method to preallocate a static tree topology over which to
/// safely perform multithreaded processing.
LeafNodeT* touchLeaf(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed0(xyz)) {
assert(mNode0);
return const_cast<NodeT0*>(mNode0)->touchLeafAndCache(xyz, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
}
return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
}
/// @brief @return a pointer to the node of the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed0(xyz)) {
assert(mNode0);
return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr ((std::is_same<NodeT, NodeT1>::value)) {
if (this->isHashed1(xyz)) {
assert(mNode1);
return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr (NodeT::LEVEL < NodeT1::LEVEL) {
// Might still be worth caching this path if a NodeT0 or NodeT1
// are accessed in the future
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeNode<NodeT>(xyz);
}
}
/// @brief @return a const pointer to the node of the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz) const
{
assert(BaseT::mTree);
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed0(xyz)) {
assert(mNode0);
return reinterpret_cast<const NodeT*>(mNode0);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr ((std::is_same<NodeT, NodeT1>::value)) {
if (this->isHashed1(xyz)) {
assert(mNode1);
return reinterpret_cast<const NodeT*>(mNode1);
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr (NodeT::LEVEL < NodeT1::LEVEL) {
// Might still be worth caching this path if a NodeT0 or NodeT1
// are accessed in the future
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeConstNode<NodeT>(xyz);
}
}
/// @brief @return a pointer to the leaf node that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
/// @brief @return a const pointer to the leaf node that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
const LeafNodeT* probeConstLeaf(const Coord& xyz) const
{
return this->template probeConstNode<LeafNodeT>(xyz);
}
/// Remove all the cached nodes and invalidate the corresponding hash-keys.
void clear() override
{
mKey0 = Coord::max();
mNode0 = nullptr;
mKey1 = Coord::max();
mNode1 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
private:
// Allow nodes to insert themselves into the cache.
template<typename> friend class RootNode;
template<typename, Index> friend class InternalNode;
template<typename, Index> friend class LeafNode;
// Allow trees to deregister themselves.
template<typename> friend class Tree;
// This private method is merely for convenience.
inline ValueAccessor2& self() const { return const_cast<ValueAccessor2&>(*this); }
void getNode(const NodeT0*& node) { node = mNode0; }
void getNode(const NodeT1*& node) { node = mNode1; }
void getNode(const RootNodeT*& node)
{
node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
}
template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
void eraseNode(const NodeT0*)
{
mKey0 = Coord::max();
mNode0 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
/// Private copy method
inline void copy(const ValueAccessor2& other)
{
mKey0 = other.mKey0;
mNode0 = other.mNode0;
mKey1 = other.mKey1;
mNode1 = other.mNode1;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = other.mBuffer;
#endif
}
/// Prevent this accessor from calling Tree::releaseCache() on a tree that
/// no longer exists. (Called by mTree when it is destroyed.)
void release() override
{
this->BaseT::release();
this->clear();
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z).
/// @note This operation is not mutex-protected and is intended to be called
/// only by nodes and only in the context of a getValue() or setValue() call.
inline void insert(const Coord& xyz, const NodeT0* node)
{
assert(node);
mKey0 = xyz & ~(NodeT0::DIM-1);
mNode0 = node;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
mBuffer = node->buffer().data();
}
#endif
}
inline void insert(const Coord& xyz, const NodeT1* node)
{
assert(node);
mKey1 = xyz & ~(NodeT1::DIM-1);
mNode1 = node;
}
/// No-op in case a tree traversal attemps to insert a node that
/// is not cached by the ValueAccessor
template<typename NodeT> inline void insert(const Coord&, const NodeT*) {}
inline bool isHashed0(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
&& (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
&& (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
}
inline bool isHashed1(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
&& (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
&& (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
}
mutable Coord mKey0;
mutable const NodeT0* mNode0;
mutable Coord mKey1;
mutable const NodeT1* mNode1;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mutable const ValueType* mBuffer;
#endif
}; // ValueAccessor2
/// @brief Value accessor with three levels of node caching.
/// @details The node cache levels are specified by L0, L1, and L2
/// with the default values 0, 1 and 2 (defined in the forward declaration)
/// corresponding to a LeafNode, its parent InternalNode, and its parent InternalNode.
/// Since the default configuration of all typed trees and grids, e.g.,
/// FloatTree or FloatGrid, has a depth of four, this value accessor is the one
/// used by default.
///
/// @note This class is for experts only and should rarely be used
/// directly. Instead use ValueAccessor with its default template arguments
template<typename _TreeType, bool IsSafe, Index L0, Index L1, Index L2>
class ValueAccessor3 : public ValueAccessorBase<_TreeType, IsSafe>
{
public:
static_assert(_TreeType::DEPTH >= 4, "cache size exceeds tree depth");
static_assert(L0 < L1, "invalid cache level");
static_assert(L1 < L2, "invalid cache level");
static_assert(L2 < _TreeType::RootNodeType::LEVEL, "invalid cache level");
using TreeType = _TreeType;
using ValueType = typename TreeType::ValueType;
using RootNodeT = typename TreeType::RootNodeType;
using LeafNodeT = typename TreeType::LeafNodeType;
using BaseT = ValueAccessorBase<TreeType, IsSafe>;
using InvTreeT = typename RootNodeT::NodeChainType;
using NodeT0 = typename InvTreeT::template Get<L0>;
using NodeT1 = typename InvTreeT::template Get<L1>;
using NodeT2 = typename InvTreeT::template Get<L2>;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
// If the last node being cached is a leaf node and the storage type matches
// the ValueType, we can cache the buffer pointer instead of using the delay
// load locked leaf API
static constexpr bool BypassLeafAPI =
std::is_same<NodeT0, LeafNodeT>::value &&
std::is_same<typename LeafNodeT::Buffer::StorageType, ValueType>::value;
#endif
/// Constructor from a tree
ValueAccessor3(TreeType& tree)
: BaseT(tree)
, mKey0(Coord::max()), mNode0(nullptr)
, mKey1(Coord::max()), mNode1(nullptr)
, mKey2(Coord::max()), mNode2(nullptr)
#if OPENVDB_ABI_VERSION_NUMBER >= 10
, mBuffer(nullptr)
#endif
{}
/// Copy constructor
ValueAccessor3(const ValueAccessor3& other) : BaseT(other) { this->copy(other); }
/// Assignment operator
ValueAccessor3& operator=(const ValueAccessor3& other)
{
if (&other != this) {
this->BaseT::operator=(other);
this->copy(other);
}
return *this;
}
/// Return the number of cache levels employed by this ValueAccessor
static Index numCacheLevels() { return 3; }
/// Virtual destructor
~ValueAccessor3() override = default;
/// Return @c true if any of the nodes along the path to the given
/// voxel have been cached.
bool isCached(const Coord& xyz) const
{
assert(BaseT::mTree);
return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
}
/// Return the value of the voxel at the given coordinates.
const ValueType& getValue(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
return mBuffer[LeafNodeT::coordToOffset(xyz)];
}
#endif
return mNode0->getValueAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->getValueAndCache(xyz, this->self());
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->getValueAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueAndCache(xyz, this->self());
}
/// Return the active state of the voxel at the given coordinates.
bool isValueOn(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return mNode0->isValueOnAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->isValueOnAndCache(xyz, this->self());
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->isValueOnAndCache(xyz, this->self());
}
return BaseT::mTree->root().isValueOnAndCache(xyz, this->self());
}
/// Return the active state of the voxel as well as its value
bool probeValue(const Coord& xyz, ValueType& value) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
value = mBuffer[offset];
return mNode0->isValueOn(offset);
}
#endif
return mNode0->probeValueAndCache(xyz, value, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->probeValueAndCache(xyz, value, this->self());
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->probeValueAndCache(xyz, value, this->self());
}
return BaseT::mTree->root().probeValueAndCache(xyz, value, this->self());
}
/// Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides,
/// or -1 if (x, y, z) isn't explicitly represented in the tree (i.e., if it is
/// implicitly a background voxel).
int getValueDepth(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->self());
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->self());
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->self());
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self());
}
/// Return @c true if the value of voxel (x, y, z) resides at the leaf level
/// of the tree, i.e., if it is not a tile value.
bool isVoxel(const Coord& xyz) const
{
assert(BaseT::mTree);
if (this->isHashed0(xyz)) {
assert(mNode0);
return mNode0->getValueLevelAndCache(xyz, this->self())==0;
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->getValueLevelAndCache(xyz, this->self())==0;
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->getValueLevelAndCache(xyz, this->self())==0;
}
return BaseT::mTree->root().getValueDepthAndCache(xyz, this->self()) ==
static_cast<int>(RootNodeT::LEVEL);
}
//@{
/// Set the value of the voxel at the given coordinates and mark the voxel as active.
void setValue(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
const_cast<NodeT0*>(mNode0)->setValueOn(offset);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueAndCache(xyz, value, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->setValueAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueAndCache(xyz, value, *this);
}
}
void setValueOn(const Coord& xyz, const ValueType& value) { this->setValue(xyz, value); }
//@}
/// Set the value of the voxel at the given coordinate but preserves its active state.
void setValueOnly(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
const_cast<ValueType&>(mBuffer[offset]) = value;
return;
}
#endif
const_cast<NodeT0*>(mNode0)->setValueOnlyAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueOnlyAndCache(xyz, value, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->setValueOnlyAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *this);
}
}
/// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOff(const Coord& xyz, const ValueType& value)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setValueOffAndCache(xyz, value, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setValueOffAndCache(xyz, value, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->setValueOffAndCache(xyz, value, *this);
} else {
BaseT::mTree->root().setValueOffAndCache(xyz, value, *this);
}
}
/// @brief Apply a functor to the value of the voxel at the given coordinates
/// and mark the voxel as active.
/// @details See Tree::modifyValue() for details.
template<typename ModifyOp>
void modifyValue(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
op(const_cast<ValueType&>(mBuffer[offset]));
const_cast<NodeT0*>(mNode0)->setActiveState(offset, true);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndCache(xyz, op, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->modifyValueAndCache(xyz, op, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->modifyValueAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndCache(xyz, op, *this);
}
}
/// @brief Apply a functor to the voxel at the given coordinates.
/// @details See Tree::modifyValueAndActiveState() for details.
template<typename ModifyOp>
void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
assert(mBuffer);
const auto offset = LeafNodeT::coordToOffset(xyz);
bool state = mNode0->isValueOn(offset);
op(const_cast<ValueType&>(mBuffer[offset]), state);
const_cast<NodeT0*>(mNode0)->setActiveState(offset, state);
return;
}
#endif
const_cast<NodeT0*>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->modifyValueAndActiveStateAndCache(xyz, op, *this);
} else {
BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *this);
}
}
/// Set the active state of the voxel at the given coordinates without changing its value.
void setActiveState(const Coord& xyz, bool on = true)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't modify a const tree's values");
if (this->isHashed0(xyz)) {
assert(mNode0);
const_cast<NodeT0*>(mNode0)->setActiveStateAndCache(xyz, on, *this);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
const_cast<NodeT1*>(mNode1)->setActiveStateAndCache(xyz, on, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
const_cast<NodeT2*>(mNode2)->setActiveStateAndCache(xyz, on, *this);
} else {
BaseT::mTree->root().setActiveStateAndCache(xyz, on, *this);
}
}
/// Mark the voxel at the given coordinates as active without changing its value.
void setValueOn(const Coord& xyz) { this->setActiveState(xyz, true); }
/// Mark the voxel at the given coordinates as inactive without changing its value.
void setValueOff(const Coord& xyz) { this->setActiveState(xyz, false); }
/// Return the cached node of type @a NodeType. [Mainly for internal use]
template<typename NodeT>
NodeT* getNode()
{
const NodeT* node = nullptr;
this->getNode(node);
return const_cast<NodeT*>(node);
}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z). [Mainly for internal use]
template<typename NodeT>
void insertNode(const Coord& xyz, NodeT& node) { this->insert(xyz, &node); }
/// If a node of the given type exists in the cache, remove it, so that
/// isCached(xyz) returns @c false for any voxel (x, y, z) contained in
/// that node. [Mainly for internal use]
template<typename NodeT>
void eraseNode()
{
const NodeT* node = nullptr;
this->eraseNode(node);
}
/// @brief Add the specified leaf to this tree, possibly creating a child branch
/// in the process. If the leaf node already exists, replace it.
void addLeaf(LeafNodeT* leaf)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a node to a const tree");
if (this->isHashed1(leaf->origin())) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->addLeafAndCache(leaf, *this);
} else if (this->isHashed2(leaf->origin())) {
assert(mNode2);
return const_cast<NodeT2*>(mNode2)->addLeafAndCache(leaf, *this);
}
BaseT::mTree->root().addLeafAndCache(leaf, *this);
}
/// @brief Add a tile at the specified tree level that contains voxel (x, y, z),
/// possibly deleting existing nodes or creating new nodes in the process.
void addTile(Index level, const Coord& xyz, const ValueType& value, bool state)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't add a tile to a const tree");
if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->addTileAndCache(level, xyz, value, state, *this);
} if (this->isHashed2(xyz)) {
assert(mNode2);
return const_cast<NodeT2*>(mNode2)->addTileAndCache(level, xyz, value, state, *this);
}
BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *this);
}
/// @brief @return the leaf node that contains voxel (x, y, z) and
/// if it doesn't exist, create it, but preserve the values and
/// active states of all voxels.
///
/// Use this method to preallocate a static tree topology over which to
/// safely perform multithreaded processing.
LeafNodeT* touchLeaf(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if (this->isHashed0(xyz)) {
assert(mNode0);
return const_cast<NodeT0*>(mNode0);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->touchLeafAndCache(xyz, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return const_cast<NodeT2*>(mNode2)->touchLeafAndCache(xyz, *this);
}
return BaseT::mTree->root().touchLeafAndCache(xyz, *this);
}
/// @brief @return a pointer to the node of the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
NodeT* probeNode(const Coord& xyz)
{
assert(BaseT::mTree);
static_assert(!BaseT::IsConstTree, "can't get a non-const node from a const tree");
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed0(xyz)) {
assert(mNode0);
return reinterpret_cast<NodeT*>(const_cast<NodeT0*>(mNode0));
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return const_cast<NodeT1*>(mNode1)->template probeNodeAndCache<NodeT>(xyz, *this);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr ((std::is_same<NodeT, NodeT1>::value)) {
if (this->isHashed1(xyz)) {
assert(mNode1);
return reinterpret_cast<NodeT*>(const_cast<NodeT1*>(mNode1));
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return const_cast<NodeT2*>(mNode2)->template probeNodeAndCache<NodeT>(xyz, *this);
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr ((std::is_same<NodeT, NodeT2>::value)) {
if (this->isHashed2(xyz)) {
assert(mNode2);
return reinterpret_cast<NodeT*>(const_cast<NodeT2*>(mNode2));
}
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else if constexpr (NodeT::LEVEL < NodeT2::LEVEL) {
// Might still be worth caching this path if a NodeT0 or NodeT1
// are accessed in the future
return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *this);
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeNode<NodeT>(xyz);
}
}
/// @brief @return a pointer to the leaf node that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
LeafNodeT* probeLeaf(const Coord& xyz) { return this->template probeNode<LeafNodeT>(xyz); }
/// @brief @return a const pointer to the node of the specified type that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
template<typename NodeT>
const NodeT* probeConstNode(const Coord& xyz) const
{
assert(BaseT::mTree);
if constexpr ((std::is_same<NodeT, NodeT0>::value)) {
if (this->isHashed0(xyz)) {
assert(mNode0);
return reinterpret_cast<const NodeT*>(mNode0);
} else if (this->isHashed1(xyz)) {
assert(mNode1);
return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr ((std::is_same<NodeT, NodeT1>::value)) {
if (this->isHashed1(xyz)) {
assert(mNode1);
return reinterpret_cast<const NodeT*>(mNode1);
} else if (this->isHashed2(xyz)) {
assert(mNode2);
return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->self());
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr ((std::is_same<NodeT, NodeT2>::value)) {
if (this->isHashed2(xyz)) {
assert(mNode2);
return reinterpret_cast<const NodeT*>(mNode2);
}
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else if constexpr (NodeT::LEVEL < NodeT2::LEVEL) {
// Might still be worth caching this path if a NodeT0 or NodeT1
// are accessed in the future
return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->self());
} else {
// If we're accessing a node above our top most cache level then
// there's no point trying to cache it
return BaseT::mTree->root().template probeConstNode<NodeT>(xyz);
}
}
/// @brief @return a const pointer to the leaf node that contains
/// voxel (x, y, z) and if it doesn't exist, return @c nullptr.
const LeafNodeT* probeConstLeaf(const Coord& xyz) const
{
return this->template probeConstNode<LeafNodeT>(xyz);
}
const LeafNodeT* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
/// Remove all the cached nodes and invalidate the corresponding hash-keys.
void clear() override
{
mKey0 = Coord::max();
mNode0 = nullptr;
mKey1 = Coord::max();
mNode1 = nullptr;
mKey2 = Coord::max();
mNode2 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
private:
// Allow nodes to insert themselves into the cache.
template<typename> friend class RootNode;
template<typename, Index> friend class InternalNode;
template<typename, Index> friend class LeafNode;
// Allow trees to deregister themselves.
template<typename> friend class Tree;
// This private method is merely for convenience.
inline ValueAccessor3& self() const { return const_cast<ValueAccessor3&>(*this); }
/// Private copy method
inline void copy(const ValueAccessor3& other)
{
mKey0 = other.mKey0;
mNode0 = other.mNode0;
mKey1 = other.mKey1;
mNode1 = other.mNode1;
mKey2 = other.mKey2;
mNode2 = other.mNode2;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = other.mBuffer;
#endif
}
/// Prevent this accessor from calling Tree::releaseCache() on a tree that
/// no longer exists. (Called by mTree when it is destroyed.)
void release() override
{
this->BaseT::release();
this->clear();
}
void getNode(const NodeT0*& node) { node = mNode0; }
void getNode(const NodeT1*& node) { node = mNode1; }
void getNode(const NodeT2*& node) { node = mNode2; }
void getNode(const RootNodeT*& node)
{
node = (BaseT::mTree ? &BaseT::mTree->root() : nullptr);
}
template<typename OtherNodeType> void getNode(const OtherNodeType*& node) { node = nullptr; }
void eraseNode(const NodeT0*)
{
mKey0 = Coord::max();
mNode0 = nullptr;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mBuffer = nullptr;
#endif
}
void eraseNode(const NodeT1*) { mKey1 = Coord::max(); mNode1 = nullptr; }
void eraseNode(const NodeT2*) { mKey2 = Coord::max(); mNode2 = nullptr; }
template<typename OtherNodeType> void eraseNode(const OtherNodeType*) {}
/// Cache the given node, which should lie along the path from the root node to
/// the node containing voxel (x, y, z).
/// @note This operation is not mutex-protected and is intended to be called
/// only by nodes and only in the context of a getValue() or setValue() call.
inline void insert(const Coord& xyz, const NodeT0* node)
{
assert(node);
mKey0 = xyz & ~(NodeT0::DIM-1);
mNode0 = node;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
if constexpr(BypassLeafAPI) {
mBuffer = node->buffer().data();
}
#endif
}
inline void insert(const Coord& xyz, const NodeT1* node)
{
assert(node);
mKey1 = xyz & ~(NodeT1::DIM-1);
mNode1 = node;
}
inline void insert(const Coord& xyz, const NodeT2* node)
{
assert(node);
mKey2 = xyz & ~(NodeT2::DIM-1);
mNode2 = node;
}
/// No-op in case a tree traversal attemps to insert a node that
/// is not cached by the ValueAccessor
template<typename OtherNodeType>
inline void insert(const Coord&, const OtherNodeType*)
{
}
inline bool isHashed0(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
&& (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
&& (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
}
inline bool isHashed1(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
&& (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
&& (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
}
inline bool isHashed2(const Coord& xyz) const
{
return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
&& (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
&& (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
}
mutable Coord mKey0;
mutable const NodeT0* mNode0;
mutable Coord mKey1;
mutable const NodeT1* mNode1;
mutable Coord mKey2;
mutable const NodeT2* mNode2;
#if OPENVDB_ABI_VERSION_NUMBER >= 10
mutable const ValueType* mBuffer;
#endif
}; // ValueAccessor3
} // namespace tree
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
value
ValueT value
Definition GridBuilder.h:1290
openvdb::v10_0::Coord::ValueType
Int32 ValueType
Definition Coord.h:32
openvdb::v10_0::Coord::max
static Coord max()
Return the largest possible coordinate.
Definition Coord.h:46
openvdb::v10_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:25
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:979
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::CoordLimits
std::numeric_limits< Int32 > CoordLimits
Definition ValueAccessor.h:873
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getNode
void getNode(const NodeType *&node) const
Return the cached node (if any) at this level.
Definition ValueAccessor.h:930
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::erase
void erase(const OtherNodeType *node)
Erase the node at another level of the cache.
Definition ValueAccessor.h:924
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:969
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::CacheItem
CacheItem(TreeCacheT &parent, const CacheItem &other)
Copy another CacheItem's node pointers and hash keys, but not its parent pointer.
Definition ValueAccessor.h:886
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::LeafNodeType
typename NodeType::LeafNodeType LeafNodeType
Definition ValueAccessor.h:872
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::insert
void insert(const Coord &xyz, const NodeType *node)
Cache the given node at this level.
Definition ValueAccessor.h:910
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::probeValue
bool probeValue(const Coord &xyz, ValueType &value)
Return the active state and value of the voxel at the given coordinates.
Definition ValueAccessor.h:1050
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::copy
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Definition ValueAccessor.h:893
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getNode
void getNode(NodeType *&node)
Definition ValueAccessor.h:932
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition ValueAccessor.h:958
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:1133
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1098
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::insert
void insert(const Coord &xyz, const OtherNodeType *node)
Forward the given node to another level of the cache.
Definition ValueAccessor.h:918
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::probeConstNode
const NodeT * probeConstNode(const Coord &xyz)
Definition ValueAccessor.h:1020
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::addLeaf
void addLeaf(LeafNodeType *leaf)
Definition ValueAccessor.h:953
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getValueDepth
int getValueDepth(const Coord &xyz)
Definition ValueAccessor.h:1062
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:1149
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::NodeType
typename NodeVecT::Front NodeType
Definition ValueAccessor.h:870
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::setActiveState
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:1161
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:1084
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::CacheItem
CacheItem(TreeCacheT &parent)
Definition ValueAccessor.h:877
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getNode
void getNode(const NodeType *&node)
Definition ValueAccessor.h:931
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::modifyValue
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.
Definition ValueAccessor.h:1116
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::isValueOn
bool isValueOn(const Coord &xyz)
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:1040
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getValue
const ValueType & getValue(const Coord &xyz)
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:944
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::clear
void clear()
Erase the nodes at this and lower levels of the cache.
Definition ValueAccessor.h:927
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:904
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::ValueType
typename NodeType::ValueType ValueType
Definition ValueAccessor.h:871
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::getNode
void getNode(OtherNodeType *&node)
Forward the request to another level of the cache.
Definition ValueAccessor.h:941
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition ValueAccessor.h:989
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1110
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::erase
void erase(const NodeType *)
Erase the node at this level.
Definition ValueAccessor.h:921
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::isVoxel
bool isVoxel(const Coord &xyz)
Definition ValueAccessor.h:1073
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, false, true >::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:999
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:1256
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::insert
void insert(const Coord &, const RootNodeType *root)
Definition ValueAccessor.h:1218
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::probeNode
NodeType * probeNode(const Coord &xyz)
Definition ValueAccessor.h:1270
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::getNode
void getNode(const RootNodeType *&node) const
Definition ValueAccessor.h:1233
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:1249
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::CacheItem
CacheItem(TreeCacheT &parent, const CacheItem &other)
Definition ValueAccessor.h:1207
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::probeValue
bool probeValue(const Coord &xyz, ValueType &value)
Definition ValueAccessor.h:1296
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::copy
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Definition ValueAccessor.h:1209
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::probeConstNode
const NodeType * probeConstNode(const Coord &xyz)
Definition ValueAccessor.h:1279
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::RootNodeType
typename NodeVecT::Front RootNodeType
Definition ValueAccessor.h:1202
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition ValueAccessor.h:1242
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Definition ValueAccessor.h:1336
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1319
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::addLeaf
void addLeaf(LeafNodeType *leaf)
Definition ValueAccessor.h:1235
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::getValueDepth
int getValueDepth(const Coord &xyz)
Definition ValueAccessor.h:1285
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1343
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::getNode
void getNode(RootNodeType *&node)
Definition ValueAccessor.h:1228
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::setActiveState
void setActiveState(const Coord &xyz, bool on)
Definition ValueAccessor.h:1350
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::setValue
void setValue(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1313
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::erase
void erase(const RootNodeType *)
Definition ValueAccessor.h:1224
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::CacheItem
CacheItem(TreeCacheT &parent)
Definition ValueAccessor.h:1206
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::ValueType
typename RootNodeType::ValueType ValueType
Definition ValueAccessor.h:1203
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::insert
void insert(const Coord &, const OtherNodeType *)
Definition ValueAccessor.h:1222
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::modifyValue
void modifyValue(const Coord &xyz, const ModifyOp &op)
Definition ValueAccessor.h:1328
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::isValueOn
bool isValueOn(const Coord &xyz)
Definition ValueAccessor.h:1290
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::getValue
const ValueType & getValue(const Coord &xyz)
Definition ValueAccessor.h:1307
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::clear
void clear()
Definition ValueAccessor.h:1226
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:1216
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition ValueAccessor.h:1204
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition ValueAccessor.h:1263
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1325
openvdb::v10_0::tree::CacheItem< TreeCacheT, NodeVecT, true, false >::isVoxel
bool isVoxel(const Coord &xyz)
Definition ValueAccessor.h:1301
openvdb::v10_0::tree::CacheItem
Definition ValueAccessor.h:541
openvdb::v10_0::tree::CacheItem::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:662
openvdb::v10_0::tree::CacheItem< ValueAccessor, SubtreeT, SubtreeT::Size==1 >::CoordLimits
std::numeric_limits< Int32 > CoordLimits
Definition ValueAccessor.h:546
openvdb::v10_0::tree::CacheItem::getNode
void getNode(const NodeType *&node) const
Return the cached node (if any) at this level.
Definition ValueAccessor.h:601
openvdb::v10_0::tree::CacheItem::erase
void erase(const OtherNodeType *node)
Erase the node at another level of the cache.
Definition ValueAccessor.h:595
openvdb::v10_0::tree::CacheItem::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:652
openvdb::v10_0::tree::CacheItem::CacheItem
CacheItem(TreeCacheT &parent, const CacheItem &other)
Copy another CacheItem's node pointers and hash keys, but not its parent pointer.
Definition ValueAccessor.h:558
openvdb::v10_0::tree::CacheItem< ValueAccessor, SubtreeT, SubtreeT::Size==1 >::LeafNodeType
typename NodeType::LeafNodeType LeafNodeType
Definition ValueAccessor.h:545
openvdb::v10_0::tree::CacheItem::insert
void insert(const Coord &xyz, const NodeType *node)
Cache the given node at this level.
Definition ValueAccessor.h:582
openvdb::v10_0::tree::CacheItem::probeValue
bool probeValue(const Coord &xyz, ValueType &value)
Return the active state and value of the voxel at the given coordinates.
Definition ValueAccessor.h:733
openvdb::v10_0::tree::CacheItem::copy
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Definition ValueAccessor.h:566
openvdb::v10_0::tree::CacheItem::getNode
void getNode(NodeType *&node)
Definition ValueAccessor.h:603
openvdb::v10_0::tree::CacheItem::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Definition ValueAccessor.h:641
openvdb::v10_0::tree::CacheItem::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:804
openvdb::v10_0::tree::CacheItem::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:774
openvdb::v10_0::tree::CacheItem::insert
void insert(const Coord &xyz, const OtherNodeType *node)
Forward the given node to another level of the cache.
Definition ValueAccessor.h:589
openvdb::v10_0::tree::CacheItem::probeConstNode
const NodeT * probeConstNode(const Coord &xyz)
Definition ValueAccessor.h:703
openvdb::v10_0::tree::CacheItem::addLeaf
void addLeaf(LeafNodeType *leaf)
Definition ValueAccessor.h:624
openvdb::v10_0::tree::CacheItem::getValueDepth
int getValueDepth(const Coord &xyz)
Definition ValueAccessor.h:742
openvdb::v10_0::tree::CacheItem::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:816
openvdb::v10_0::tree::CacheItem< ValueAccessor, SubtreeT, SubtreeT::Size==1 >::NodeType
typename SubtreeT::Front NodeType
Definition ValueAccessor.h:543
openvdb::v10_0::tree::CacheItem::setActiveState
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:828
openvdb::v10_0::tree::CacheItem::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:764
openvdb::v10_0::tree::CacheItem::CacheItem
CacheItem(TreeCacheT &parent)
Definition ValueAccessor.h:548
openvdb::v10_0::tree::CacheItem::getNode
void getNode(const NodeType *&node)
Definition ValueAccessor.h:602
openvdb::v10_0::tree::CacheItem::modifyValue
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.
Definition ValueAccessor.h:790
openvdb::v10_0::tree::CacheItem::isValueOn
bool isValueOn(const Coord &xyz)
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:723
openvdb::v10_0::tree::CacheItem::getValue
const ValueType & getValue(const Coord &xyz)
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:615
openvdb::v10_0::tree::CacheItem::clear
void clear()
Erase the nodes at this and lower levels of the cache.
Definition ValueAccessor.h:598
openvdb::v10_0::tree::CacheItem::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:576
openvdb::v10_0::tree::CacheItem< ValueAccessor, SubtreeT, SubtreeT::Size==1 >::ValueType
typename NodeType::ValueType ValueType
Definition ValueAccessor.h:544
openvdb::v10_0::tree::CacheItem::getNode
void getNode(OtherNodeType *&node)
Forward the request to another level of the cache.
Definition ValueAccessor.h:612
openvdb::v10_0::tree::CacheItem::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz)
Definition ValueAccessor.h:672
openvdb::v10_0::tree::CacheItem::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:784
openvdb::v10_0::tree::CacheItem::erase
void erase(const NodeType *)
Erase the node at this level.
Definition ValueAccessor.h:592
openvdb::v10_0::tree::CacheItem::isVoxel
bool isVoxel(const Coord &xyz)
Definition ValueAccessor.h:753
openvdb::v10_0::tree::CacheItem::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:682
openvdb::v10_0::tree::ValueAccessor0::getValueDepth
int getValueDepth(const Coord &xyz) const
Definition ValueAccessor.h:1431
openvdb::v10_0::tree::ValueAccessor0::BypassLeafAPI
static constexpr bool BypassLeafAPI
Definition ValueAccessor.h:1386
openvdb::v10_0::tree::ValueAccessor0::insertNode
void insertNode(const Coord &, NodeT &)
Definition ValueAccessor.h:1510
openvdb::v10_0::tree::ValueAccessor0::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:1415
openvdb::v10_0::tree::ValueAccessor0::setActiveState
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition ValueAccessor.h:1494
openvdb::v10_0::tree::ValueAccessor0::isVoxel
bool isVoxel(const Coord &xyz) const
Definition ValueAccessor.h:1439
openvdb::v10_0::tree::ValueAccessor0::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:1535
openvdb::v10_0::tree::ValueAccessor0::ValueAccessor0
ValueAccessor0(const ValueAccessor0 &other)
Definition ValueAccessor.h:1391
openvdb::v10_0::tree::ValueAccessor0::ValueType
typename TreeType::ValueType ValueType
Definition ValueAccessor.h:1379
openvdb::v10_0::tree::ValueAccessor0::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition ValueAccessor.h:1514
openvdb::v10_0::tree::ValueAccessor0::numCacheLevels
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition ValueAccessor.h:1394
openvdb::v10_0::tree::ValueAccessor0::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:1557
openvdb::v10_0::tree::ValueAccessor0::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition ValueAccessor.h:1523
openvdb::v10_0::tree::ValueAccessor0::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition ValueAccessor.h:1562
openvdb::v10_0::tree::ValueAccessor0::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:1486
openvdb::v10_0::tree::ValueAccessor0::operator=
ValueAccessor0 & operator=(const ValueAccessor0 &other)
Definition ValueAccessor.h:1396
openvdb::v10_0::tree::ValueAccessor0::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don't change its active state.
Definition ValueAccessor.h:1457
openvdb::v10_0::tree::ValueAccessor0::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition ValueAccessor.h:1380
openvdb::v10_0::tree::ValueAccessor0::isCached
bool isCached(const Coord &) const
Return true if nodes along the path to the given voxel have been cached.
Definition ValueAccessor.h:1405
openvdb::v10_0::tree::ValueAccessor0::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:1465
openvdb::v10_0::tree::ValueAccessor0::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state and, in value, the value of the voxel at the given coordinates.
Definition ValueAccessor.h:1422
openvdb::v10_0::tree::ValueAccessor0::LeafNodeT
typename TreeType::LeafNodeType LeafNodeT
Definition ValueAccessor.h:1381
openvdb::v10_0::tree::ValueAccessor0::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:1447
openvdb::v10_0::tree::ValueAccessor0< TreeType, IsSafe >::ValueAccessor0
ValueAccessor0(TreeType &tree)
Definition ValueAccessor.h:1389
openvdb::v10_0::tree::ValueAccessor0::eraseNode
void eraseNode()
Definition ValueAccessor.h:1533
openvdb::v10_0::tree::ValueAccessor0::~ValueAccessor0
~ValueAccessor0() override=default
openvdb::v10_0::tree::ValueAccessor0::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition ValueAccessor.h:1503
openvdb::v10_0::tree::ValueAccessor0::getNode
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition ValueAccessor.h:1506
openvdb::v10_0::tree::ValueAccessor0::Tree
friend class Tree
Definition ValueAccessor.h:1577
openvdb::v10_0::tree::ValueAccessor0::modifyValue
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.
Definition ValueAccessor.h:1476
openvdb::v10_0::tree::ValueAccessor0::probeLeaf
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition ValueAccessor.h:1567
openvdb::v10_0::tree::ValueAccessor0::probeConstNode
const NodeT * probeConstNode(const Coord &xyz) const
Definition ValueAccessor.h:1551
openvdb::v10_0::tree::ValueAccessor0::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition ValueAccessor.h:1501
openvdb::v10_0::tree::ValueAccessor0::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1453
openvdb::v10_0::tree::ValueAccessor0::TreeType
_TreeType TreeType
Definition ValueAccessor.h:1378
openvdb::v10_0::tree::ValueAccessor0::BaseT
ValueAccessorBase< TreeType, IsSafe > BaseT
Definition ValueAccessor.h:1382
openvdb::v10_0::tree::ValueAccessor0::clear
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition ValueAccessor.h:1573
openvdb::v10_0::tree::ValueAccessor0::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:1543
openvdb::v10_0::tree::ValueAccessor0::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:1408
openvdb::v10_0::tree::ValueAccessor1::getValueDepth
int getValueDepth(const Coord &xyz) const
Definition ValueAccessor.h:1701
openvdb::v10_0::tree::ValueAccessor1::BypassLeafAPI
static constexpr bool BypassLeafAPI
Definition ValueAccessor.h:1610
openvdb::v10_0::tree::ValueAccessor1::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:1669
openvdb::v10_0::tree::ValueAccessor1::setActiveState
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition ValueAccessor.h:1834
openvdb::v10_0::tree::ValueAccessor1::isVoxel
bool isVoxel(const Coord &xyz) const
Definition ValueAccessor.h:1713
openvdb::v10_0::tree::ValueAccessor1::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:1898
openvdb::v10_0::tree::ValueAccessor1::ValueType
typename TreeType::ValueType ValueType
Definition ValueAccessor.h:1599
openvdb::v10_0::tree::ValueAccessor1::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition ValueAccessor.h:1876
openvdb::v10_0::tree::ValueAccessor1::numCacheLevels
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition ValueAccessor.h:1628
openvdb::v10_0::tree::ValueAccessor1< TreeType, IsSafe >::ValueAccessor1
ValueAccessor1(TreeType &tree)
Definition ValueAccessor.h:1616
openvdb::v10_0::tree::ValueAccessor1::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:1932
openvdb::v10_0::tree::ValueAccessor1::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition ValueAccessor.h:1885
openvdb::v10_0::tree::ValueAccessor1::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition ValueAccessor.h:1959
openvdb::v10_0::tree::ValueAccessor1::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:1811
openvdb::v10_0::tree::ValueAccessor1::InternalNode
friend class InternalNode
Definition ValueAccessor.h:1978
openvdb::v10_0::tree::ValueAccessor1::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition ValueAccessor.h:1750
openvdb::v10_0::tree::ValueAccessor1::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition ValueAccessor.h:1600
openvdb::v10_0::tree::ValueAccessor1::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:1771
openvdb::v10_0::tree::ValueAccessor1::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition ValueAccessor.h:1680
openvdb::v10_0::tree::ValueAccessor1::ValueAccessor1
ValueAccessor1(const ValueAccessor1 &other)
Copy constructor.
Definition ValueAccessor.h:1625
openvdb::v10_0::tree::ValueAccessor1::LeafNodeT
typename TreeType::LeafNodeType LeafNodeT
Definition ValueAccessor.h:1601
openvdb::v10_0::tree::ValueAccessor1::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:1726
openvdb::v10_0::tree::ValueAccessor1::~ValueAccessor1
~ValueAccessor1() override=default
Virtual destructor.
openvdb::v10_0::tree::ValueAccessor1::eraseNode
void eraseNode()
Definition ValueAccessor.h:1868
openvdb::v10_0::tree::ValueAccessor1::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition ValueAccessor.h:1848
openvdb::v10_0::tree::ValueAccessor1::getNode
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition ValueAccessor.h:1852
openvdb::v10_0::tree::ValueAccessor1::InvTreeT
typename RootNodeT::NodeChainType InvTreeT
Definition ValueAccessor.h:1603
openvdb::v10_0::tree::ValueAccessor1::Tree
friend class Tree
Definition ValueAccessor.h:1981
openvdb::v10_0::tree::ValueAccessor1::modifyValue
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.
Definition ValueAccessor.h:1787
openvdb::v10_0::tree::ValueAccessor1::LeafNode
friend class LeafNode
Definition ValueAccessor.h:1979
openvdb::v10_0::tree::ValueAccessor1::operator=
ValueAccessor1 & operator=(const ValueAccessor1 &other)
Assignment operator.
Definition ValueAccessor.h:1631
openvdb::v10_0::tree::ValueAccessor1::probeLeaf
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition ValueAccessor.h:1963
openvdb::v10_0::tree::ValueAccessor1::insertNode
void insertNode(const Coord &xyz, NodeT &node)
Definition ValueAccessor.h:1862
openvdb::v10_0::tree::ValueAccessor1::probeConstNode
const NodeT * probeConstNode(const Coord &xyz) const
Definition ValueAccessor.h:1940
openvdb::v10_0::tree::ValueAccessor1::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:1645
openvdb::v10_0::tree::ValueAccessor1::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition ValueAccessor.h:1846
openvdb::v10_0::tree::ValueAccessor1::NodeT0
typename InvTreeT::template Get< L0 > NodeT0
Definition ValueAccessor.h:1604
openvdb::v10_0::tree::ValueAccessor1::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:1746
openvdb::v10_0::tree::ValueAccessor1::TreeType
_TreeType TreeType
Definition ValueAccessor.h:1598
openvdb::v10_0::tree::ValueAccessor1::BaseT
ValueAccessorBase< TreeType, IsSafe > BaseT
Definition ValueAccessor.h:1602
openvdb::v10_0::tree::ValueAccessor1::clear
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition ValueAccessor.h:1966
openvdb::v10_0::tree::ValueAccessor1::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:1912
openvdb::v10_0::tree::ValueAccessor1::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:1652
openvdb::v10_0::tree::ValueAccessor1::RootNode
friend class RootNode
Definition ValueAccessor.h:1977
openvdb::v10_0::tree::ValueAccessor2::getValueDepth
int getValueDepth(const Coord &xyz) const
Definition ValueAccessor.h:2186
openvdb::v10_0::tree::ValueAccessor2::BypassLeafAPI
static constexpr bool BypassLeafAPI
Definition ValueAccessor.h:2085
openvdb::v10_0::tree::ValueAccessor2::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:2148
openvdb::v10_0::tree::ValueAccessor2::setActiveState
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
Definition ValueAccessor.h:2340
openvdb::v10_0::tree::ValueAccessor2::isVoxel
bool isVoxel(const Coord &xyz) const
Definition ValueAccessor.h:2201
openvdb::v10_0::tree::ValueAccessor2::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:2415
openvdb::v10_0::tree::ValueAccessor2::ValueType
typename TreeType::ValueType ValueType
Definition ValueAccessor.h:2073
openvdb::v10_0::tree::ValueAccessor2::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition ValueAccessor.h:2385
openvdb::v10_0::tree::ValueAccessor2::numCacheLevels
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition ValueAccessor.h:2104
openvdb::v10_0::tree::ValueAccessor2::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:2496
openvdb::v10_0::tree::ValueAccessor2::ValueAccessor2
ValueAccessor2(const ValueAccessor2 &other)
Copy constructor.
Definition ValueAccessor.h:2101
openvdb::v10_0::tree::ValueAccessor2::operator=
ValueAccessor2 & operator=(const ValueAccessor2 &other)
Assignment operator.
Definition ValueAccessor.h:2107
openvdb::v10_0::tree::ValueAccessor2::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition ValueAccessor.h:2398
openvdb::v10_0::tree::ValueAccessor2::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition ValueAccessor.h:2501
openvdb::v10_0::tree::ValueAccessor2::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:2314
openvdb::v10_0::tree::ValueAccessor2::InternalNode
friend class InternalNode
Definition ValueAccessor.h:2521
openvdb::v10_0::tree::ValueAccessor2::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition ValueAccessor.h:2244
openvdb::v10_0::tree::ValueAccessor2::NodeT1
typename InvTreeT::template Get< L1 > NodeT1
Definition ValueAccessor.h:2079
openvdb::v10_0::tree::ValueAccessor2::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition ValueAccessor.h:2074
openvdb::v10_0::tree::ValueAccessor2::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:2268
openvdb::v10_0::tree::ValueAccessor2::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition ValueAccessor.h:2162
openvdb::v10_0::tree::ValueAccessor2::LeafNodeT
typename TreeType::LeafNodeType LeafNodeT
Definition ValueAccessor.h:2075
openvdb::v10_0::tree::ValueAccessor2::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:2217
openvdb::v10_0::tree::ValueAccessor2::eraseNode
void eraseNode()
Definition ValueAccessor.h:2377
openvdb::v10_0::tree::ValueAccessor2::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition ValueAccessor.h:2357
openvdb::v10_0::tree::ValueAccessor2::getNode
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition ValueAccessor.h:2361
openvdb::v10_0::tree::ValueAccessor2::InvTreeT
typename RootNodeT::NodeChainType InvTreeT
Definition ValueAccessor.h:2077
openvdb::v10_0::tree::ValueAccessor2< TreeType, IsSafe >::ValueAccessor2
ValueAccessor2(TreeType &tree)
Definition ValueAccessor.h:2091
openvdb::v10_0::tree::ValueAccessor2::Tree
friend class Tree
Definition ValueAccessor.h:2524
openvdb::v10_0::tree::ValueAccessor2::modifyValue
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.
Definition ValueAccessor.h:2287
openvdb::v10_0::tree::ValueAccessor2::LeafNode
friend class LeafNode
Definition ValueAccessor.h:2522
openvdb::v10_0::tree::ValueAccessor2::probeLeaf
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition ValueAccessor.h:2497
openvdb::v10_0::tree::ValueAccessor2::insertNode
void insertNode(const Coord &xyz, NodeT &node)
Definition ValueAccessor.h:2371
openvdb::v10_0::tree::ValueAccessor2::probeConstNode
const NodeT * probeConstNode(const Coord &xyz) const
Definition ValueAccessor.h:2465
openvdb::v10_0::tree::ValueAccessor2::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:2121
openvdb::v10_0::tree::ValueAccessor2::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition ValueAccessor.h:2355
openvdb::v10_0::tree::ValueAccessor2::~ValueAccessor2
~ValueAccessor2() override=default
Virtual destructor.
openvdb::v10_0::tree::ValueAccessor2::NodeT0
typename InvTreeT::template Get< L0 > NodeT0
Definition ValueAccessor.h:2078
openvdb::v10_0::tree::ValueAccessor2::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:2240
openvdb::v10_0::tree::ValueAccessor2::TreeType
_TreeType TreeType
Definition ValueAccessor.h:2072
openvdb::v10_0::tree::ValueAccessor2::BaseT
ValueAccessorBase< TreeType, IsSafe > BaseT
Definition ValueAccessor.h:2076
openvdb::v10_0::tree::ValueAccessor2::clear
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition ValueAccessor.h:2507
openvdb::v10_0::tree::ValueAccessor2::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:2432
openvdb::v10_0::tree::ValueAccessor2::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:2128
openvdb::v10_0::tree::ValueAccessor2::RootNode
friend class RootNode
Definition ValueAccessor.h:2520
openvdb::v10_0::tree::ValueAccessor3
Value accessor with three levels of node caching.
Definition ValueAccessor.h:2628
openvdb::v10_0::tree::ValueAccessor3::getValueDepth
int getValueDepth(const Coord &xyz) const
Definition ValueAccessor.h:2760
openvdb::v10_0::tree::ValueAccessor3::ValueAccessor3
ValueAccessor3(const ValueAccessor3 &other)
Copy constructor.
Definition ValueAccessor.h:2666
openvdb::v10_0::tree::ValueAccessor3::BypassLeafAPI
static constexpr bool BypassLeafAPI
Definition ValueAccessor.h:2649
openvdb::v10_0::tree::ValueAccessor3::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:2716
openvdb::v10_0::tree::ValueAccessor3::setActiveState
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
Definition ValueAccessor.h:2935
openvdb::v10_0::tree::ValueAccessor3::isVoxel
bool isVoxel(const Coord &xyz) const
Definition ValueAccessor.h:2778
openvdb::v10_0::tree::ValueAccessor3::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Definition ValueAccessor.h:3019
openvdb::v10_0::tree::ValueAccessor3::ValueType
typename TreeType::ValueType ValueType
Definition ValueAccessor.h:2636
openvdb::v10_0::tree::ValueAccessor3::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition ValueAccessor.h:2983
openvdb::v10_0::tree::ValueAccessor3::numCacheLevels
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
Definition ValueAccessor.h:2679
openvdb::v10_0::tree::ValueAccessor3::NodeT2
typename InvTreeT::template Get< L2 > NodeT2
Definition ValueAccessor.h:2643
openvdb::v10_0::tree::ValueAccessor3::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Definition ValueAccessor.h:3081
openvdb::v10_0::tree::ValueAccessor3::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition ValueAccessor.h:2999
openvdb::v10_0::tree::ValueAccessor3::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition ValueAccessor.h:3128
openvdb::v10_0::tree::ValueAccessor3::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:2906
openvdb::v10_0::tree::ValueAccessor3::InternalNode
friend class InternalNode
Definition ValueAccessor.h:3151
openvdb::v10_0::tree::ValueAccessor3::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
Definition ValueAccessor.h:2827
openvdb::v10_0::tree::ValueAccessor3::NodeT1
typename InvTreeT::template Get< L1 > NodeT1
Definition ValueAccessor.h:2642
openvdb::v10_0::tree::ValueAccessor3::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition ValueAccessor.h:2637
openvdb::v10_0::tree::ValueAccessor3::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:2854
openvdb::v10_0::tree::ValueAccessor3::operator=
ValueAccessor3 & operator=(const ValueAccessor3 &other)
Assignment operator.
Definition ValueAccessor.h:2669
openvdb::v10_0::tree::ValueAccessor3::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition ValueAccessor.h:2733
openvdb::v10_0::tree::ValueAccessor3::LeafNodeT
typename TreeType::LeafNodeType LeafNodeT
Definition ValueAccessor.h:2638
openvdb::v10_0::tree::ValueAccessor3::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:2797
openvdb::v10_0::tree::ValueAccessor3::~ValueAccessor3
~ValueAccessor3() override=default
Virtual destructor.
openvdb::v10_0::tree::ValueAccessor3::eraseNode
void eraseNode()
Definition ValueAccessor.h:2975
openvdb::v10_0::tree::ValueAccessor3::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
Definition ValueAccessor.h:2955
openvdb::v10_0::tree::ValueAccessor3::getNode
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition ValueAccessor.h:2959
openvdb::v10_0::tree::ValueAccessor3::InvTreeT
typename RootNodeT::NodeChainType InvTreeT
Definition ValueAccessor.h:2640
openvdb::v10_0::tree::ValueAccessor3::Tree
friend class Tree
Definition ValueAccessor.h:3154
openvdb::v10_0::tree::ValueAccessor3::modifyValue
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.
Definition ValueAccessor.h:2876
openvdb::v10_0::tree::ValueAccessor3::LeafNode
friend class LeafNode
Definition ValueAccessor.h:3152
openvdb::v10_0::tree::ValueAccessor3< TreeType, IsSafe >::ValueAccessor3
ValueAccessor3(TreeType &tree)
Definition ValueAccessor.h:2655
openvdb::v10_0::tree::ValueAccessor3::probeLeaf
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition ValueAccessor.h:3132
openvdb::v10_0::tree::ValueAccessor3::insertNode
void insertNode(const Coord &xyz, NodeT &node)
Definition ValueAccessor.h:2969
openvdb::v10_0::tree::ValueAccessor3::probeConstNode
const NodeT * probeConstNode(const Coord &xyz) const
Definition ValueAccessor.h:3086
openvdb::v10_0::tree::ValueAccessor3::isCached
bool isCached(const Coord &xyz) const
Definition ValueAccessor.h:2686
openvdb::v10_0::tree::ValueAccessor3::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
Definition ValueAccessor.h:2953
openvdb::v10_0::tree::ValueAccessor3::NodeT0
typename InvTreeT::template Get< L0 > NodeT0
Definition ValueAccessor.h:2641
openvdb::v10_0::tree::ValueAccessor3::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:2823
openvdb::v10_0::tree::ValueAccessor3::TreeType
_TreeType TreeType
Definition ValueAccessor.h:2635
openvdb::v10_0::tree::ValueAccessor3::BaseT
ValueAccessorBase< TreeType, IsSafe > BaseT
Definition ValueAccessor.h:2639
openvdb::v10_0::tree::ValueAccessor3::clear
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition ValueAccessor.h:3135
openvdb::v10_0::tree::ValueAccessor3::probeNode
NodeT * probeNode(const Coord &xyz)
Definition ValueAccessor.h:3038
openvdb::v10_0::tree::ValueAccessor3::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:2693
openvdb::v10_0::tree::ValueAccessor3::RootNode
friend class RootNode
Definition ValueAccessor.h:3150
openvdb::v10_0::tree::ValueAccessorBase::getTree
TreeType * getTree() const
Return a pointer to the tree associated with this accessor.
Definition ValueAccessor.h:116
openvdb::v10_0::tree::ValueAccessorBase::ValueAccessorBase
ValueAccessorBase(const ValueAccessorBase &other)
Definition ValueAccessor.h:120
openvdb::v10_0::tree::ValueAccessorBase::operator=
ValueAccessorBase & operator=(const ValueAccessorBase &other)
Definition ValueAccessor.h:125
openvdb::v10_0::tree::ValueAccessorBase::mTree
TreeType * mTree
Definition ValueAccessor.h:143
openvdb::v10_0::tree::ValueAccessorBase::~ValueAccessorBase
virtual ~ValueAccessorBase()
Definition ValueAccessor.h:110
openvdb::v10_0::tree::ValueAccessorBase::clear
virtual void clear()=0
openvdb::v10_0::tree::ValueAccessorBase::ValueAccessorBase
ValueAccessorBase(TreeType &tree)
Definition ValueAccessor.h:105
openvdb::v10_0::tree::ValueAccessorBase::Tree
friend class Tree
Definition ValueAccessor.h:139
openvdb::v10_0::tree::ValueAccessorBase::tree
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition ValueAccessor.h:118
openvdb::v10_0::tree::ValueAccessorBase::IsConstTree
static const bool IsConstTree
Definition ValueAccessor.h:95
openvdb::v10_0::tree::ValueAccessorBase::isSafe
static bool isSafe()
Return true if this accessor is safe, i.e. registered by the tree from which it is constructed....
Definition ValueAccessor.h:103
openvdb::v10_0::tree::ValueAccessorBase::release
virtual void release()
Definition ValueAccessor.h:141
openvdb::v10_0::tree::ValueAccessorRW::ValueAccessorRW
ValueAccessorRW(TreeType &tree)
Definition ValueAccessor.h:520
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 0, tbb::null_mutex >::~ValueAccessor
~ValueAccessor() override=default
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 0, tbb::null_mutex >::ValueAccessor
ValueAccessor(TreeType &tree)
Definition ValueAccessor.h:463
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 0, tbb::null_mutex >::ValueAccessor
ValueAccessor(const ValueAccessor &other)
Definition ValueAccessor.h:464
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 1, tbb::null_mutex >::~ValueAccessor
~ValueAccessor() override=default
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 1, tbb::null_mutex >::ValueAccessor
ValueAccessor(TreeType &tree)
Definition ValueAccessor.h:475
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 1, tbb::null_mutex >::ValueAccessor
ValueAccessor(const ValueAccessor &other)
Definition ValueAccessor.h:476
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 2, tbb::null_mutex >::~ValueAccessor
~ValueAccessor() override=default
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 2, tbb::null_mutex >::ValueAccessor
ValueAccessor(TreeType &tree)
Definition ValueAccessor.h:487
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 2, tbb::null_mutex >::ValueAccessor
ValueAccessor(const ValueAccessor &other)
Definition ValueAccessor.h:488
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 3, tbb::null_mutex >::~ValueAccessor
~ValueAccessor() override=default
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 3, tbb::null_mutex >::ValueAccessor
ValueAccessor(TreeType &tree)
Definition ValueAccessor.h:498
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 3, tbb::null_mutex >::ValueAccessor
ValueAccessor(const ValueAccessor &)=default
openvdb::v10_0::tree::ValueAccessor< TreeType, IsSafe, 3, tbb::null_mutex >::operator=
ValueAccessor & operator=(const ValueAccessor &)=default
openvdb::v10_0::tree::ValueAccessor::getValueDepth
int getValueDepth(const Coord &xyz) const
Definition ValueAccessor.h:254
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::BypassLeafAPI
static constexpr bool BypassLeafAPI
Definition ValueAccessor.h:207
openvdb::v10_0::tree::ValueAccessor::~ValueAccessor
~ValueAccessor() override=default
openvdb::v10_0::tree::ValueAccessor::ValueAccessor
ValueAccessor(TreeType &tree)
Definition ValueAccessor.h:211
openvdb::v10_0::tree::ValueAccessor::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:242
openvdb::v10_0::tree::ValueAccessor::setActiveState
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition ValueAccessor.h:308
openvdb::v10_0::tree::ValueAccessor::isVoxel
bool isVoxel(const Coord &xyz) const
Definition ValueAccessor.h:262
openvdb::v10_0::tree::ValueAccessor::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition ValueAccessor.h:364
openvdb::v10_0::tree::ValueAccessor::operator=
ValueAccessor & operator=(const ValueAccessor &other)
Definition ValueAccessor.h:218
openvdb::v10_0::tree::ValueAccessor::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition ValueAccessor.h:345
openvdb::v10_0::tree::ValueAccessor::numCacheLevels
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
Definition ValueAccessor.h:229
openvdb::v10_0::tree::ValueAccessor::probeLeaf
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists.
Definition ValueAccessor.h:395
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::ValueType
typename RootNodeT::ValueType ValueType
Definition ValueAccessor.h:198
openvdb::v10_0::tree::ValueAccessor::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
Definition ValueAccessor.h:353
openvdb::v10_0::tree::ValueAccessor::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition ValueAccessor.h:400
openvdb::v10_0::tree::ValueAccessor::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition ValueAccessor.h:301
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::InternalNode
friend class InternalNode
Definition ValueAccessor.h:419
openvdb::v10_0::tree::ValueAccessor::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don't change its active state.
Definition ValueAccessor.h:275
openvdb::v10_0::tree::ValueAccessor::insertNode
void insertNode(const Coord &xyz, NodeType &node)
Definition ValueAccessor.h:331
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition ValueAccessor.h:196
openvdb::v10_0::tree::ValueAccessor::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition ValueAccessor.h:282
openvdb::v10_0::tree::ValueAccessor::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition ValueAccessor.h:245
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::LeafNodeT
typename TreeType::LeafNodeType LeafNodeT
Definition ValueAccessor.h:197
openvdb::v10_0::tree::ValueAccessor::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition ValueAccessor.h:266
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::LockT
typename tbb::null_mutex::scoped_lock LockT
Definition ValueAccessor.h:200
openvdb::v10_0::tree::ValueAccessor::eraseNode
void eraseNode()
Definition ValueAccessor.h:341
openvdb::v10_0::tree::ValueAccessor::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition ValueAccessor.h:316
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::Tree
friend class Tree
Definition ValueAccessor.h:422
openvdb::v10_0::tree::ValueAccessor::modifyValue
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.
Definition ValueAccessor.h:292
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::LeafNode
friend class LeafNode
Definition ValueAccessor.h:420
openvdb::v10_0::tree::ValueAccessor::probeNode
const NodeT * probeNode(const Coord &xyz) const
Definition ValueAccessor.h:386
openvdb::v10_0::tree::ValueAccessor::probeLeaf
const LeafNodeT * probeLeaf(const Coord &xyz) const
Definition ValueAccessor.h:405
openvdb::v10_0::tree::ValueAccessor::probeConstNode
const NodeT * probeConstNode(const Coord &xyz) const
Definition ValueAccessor.h:380
openvdb::v10_0::tree::ValueAccessor::isCached
bool isCached(const Coord &xyz) const
Return true if nodes along the path to the given voxel have been cached.
Definition ValueAccessor.h:232
openvdb::v10_0::tree::ValueAccessor::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition ValueAccessor.h:314
openvdb::v10_0::tree::ValueAccessor::getNode
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition ValueAccessor.h:320
openvdb::v10_0::tree::ValueAccessor::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:271
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::TreeType
const TreeType TreeType
Definition ValueAccessor.h:195
openvdb::v10_0::tree::ValueAccessor::ValueAccessor
ValueAccessor(const ValueAccessor &other)
Definition ValueAccessor.h:216
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::BaseT
ValueAccessorBase< TreeType, IsSafe > BaseT
Definition ValueAccessor.h:199
openvdb::v10_0::tree::ValueAccessor::clear
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition ValueAccessor.h:409
openvdb::v10_0::tree::ValueAccessor::probeNode
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
Definition ValueAccessor.h:374
openvdb::v10_0::tree::ValueAccessor::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:235
openvdb::v10_0::tree::ValueAccessor< const TreeType, IsSafe >::RootNode
friend class RootNode
Definition ValueAccessor.h:418
openvdb::v10_0::Index
Index32 Index
Definition Types.h:54
openvdb
Definition Exceptions.h:13
Types.h
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212