45 #ifndef OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
46 #define OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
51 #include <tbb/spin_mutex.h>
55 #include <type_traits>
64 template<
typename TreeType,
66 typename MutexT =
void,
84 template<
typename TreeType,
bool IsSafe =
true,
85 size_t CacheLevels =
std::max(
Index(1),TreeType::DEPTH)-1,
typename MutexType =
void>
88 openvdb::make_index_sequence<CacheLevels>>;
92 template <
typename TreeType,
bool IsSafe>
98 template <
typename TreeType,
bool IsSafe,
size_t L0 = 0>
106 template <
typename TreeType,
bool IsSafe,
size_t L0 = 0,
size_t L1 = 1>
114 template <
typename TreeType,
bool IsSafe,
size_t L0 = 0,
size_t L1 = 1,
size_t L2 = 2>
119 template<
typename TreeType,
bool IsSafe =
true,
123 openvdb::make_index_sequence<CacheLevels>>;
150 template<
typename TreeType,
bool IsSafe>
163 static constexpr
bool isSafe() {
return IsSafe; }
171 if (IsSafe) tree.attachAccessor(*
this);
181 if (IsSafe &&
mTree)
mTree->attachAccessor(*
this);
186 if (&other !=
this) {
187 if (IsSafe &&
mTree)
mTree->releaseAccessor(*
this);
189 if (IsSafe &&
mTree)
mTree->attachAccessor(*
this);
204 virtual void clear() = 0;
208 template<
typename>
friend class Tree;
217 namespace value_accessor_internal
220 template<
typename ListT,
size_t... Ts>
struct NodeListBuilderImpl;
222 template <
typename NodeChainT>
223 struct NodeListBuilderImpl<NodeChainT>
228 template <
typename NodeChainT,
size_t Idx>
229 struct NodeListBuilderImpl<NodeChainT, Idx>
231 using NodeT =
typename NodeChainT::template Get<Idx>;
235 template <
typename NodeChainT,
size_t ThisIdx,
size_t NextIdx,
size_t... Idxs>
236 struct NodeListBuilderImpl<NodeChainT, ThisIdx, NextIdx, Idxs...>
238 static_assert(ThisIdx < NextIdx,
239 "Invalid cache level - Cache levels must be in increasing ascending order");
240 static_assert(ThisIdx < NodeChainT::Size,
241 "Invalid cache level - Cache level is larger than the number of tree nodes");
242 static_assert(ThisIdx < NodeChainT::Back::LEVEL,
243 "Invalid cache level - Cache level is larger than the number of tree nodes");
245 using NodeT =
typename NodeChainT::template Get<ThisIdx>;
246 using ListT =
typename TypeList<NodeT>::template
Append<
247 typename NodeListBuilderImpl<NodeChainT, NextIdx, Idxs...>::ListT>;
250 template<
typename NodeChainT,
size_t RootLevel,
typename IntegerSequence>
251 struct NodeListBuilder;
253 template<
typename NodeChainT,
size_t RootLevel,
size_t... Is>
254 struct NodeListBuilder<NodeChainT, RootLevel, std::integer_sequence<size_t, Is...>>
256 using ListT =
typename NodeListBuilderImpl<NodeChainT, Is..., RootLevel>::ListT;
259 template<
typename NodeChainT,
size_t RootLevel,
size_t... Is>
260 struct NodeListBuilder<NodeChainT, RootLevel, openvdb::
index_sequence<Is...>>
262 using ListT =
typename NodeListBuilderImpl<NodeChainT, Is..., RootLevel>::ListT;
266 template<
typename TreeTypeT,
typename NodeT>
267 struct EnableLeafBuffer
269 using LeafNodeT =
typename TreeTypeT::LeafNodeType;
270 static constexpr
bool value =
272 std::is_same<
typename LeafNodeT::Buffer::StorageType,
276 template<
typename TreeTypeT,
size_t... Is>
277 struct EnableLeafBuffer<TreeTypeT, openvdb::
index_sequence<Is...>>
280 static constexpr
bool value =
false;
283 template<
typename TreeTypeT,
size_t First,
size_t... Is>
284 struct EnableLeafBuffer<TreeTypeT, openvdb::
index_sequence<First, Is...>>
287 using NodeChainT =
typename TreeTypeT::RootNodeType::NodeChainType;
288 using FirstNodeT =
typename NodeChainT::template Get<First>;
310 template <
typename MutexT>
313 inline auto lock()
const {
return std::scoped_lock(m); }
322 inline constexpr
auto lock()
const {
return 0; }
331 template<
typename TreeTypeT,
typename IntegerSequence,
typename Enable =
void>
334 template <
typename NodeT>
346 template<
typename TreeTypeT,
typename IntegerSequence>
348 typename std::enable_if<
349 !value_accessor_internal::EnableLeafBuffer<TreeTypeT, IntegerSequence>::value
362 template<
typename _TreeType,
bool IsSafe,
typename MutexT,
typename IntegerSequence>
363 class ValueAccessorImpl final :
364 public ValueAccessorBase<_TreeType, IsSafe>,
365 public ValueAccessorLeafBuffer<_TreeType, IntegerSequence>,
366 public ValueAccessorLock<MutexT>
385 typename value_accessor_internal::NodeListBuilder
387 using NodePtrList =
typename NodeLevelList::template Transform<std::add_pointer_t>;
401 template <
size_t Level>
409 template <
typename NodeT>
411 LeafCacheT::template BypassLeafAPI<NodeT>;
416 IsLeafAndBypassLeafAPI<NodeTypeAtLevel<0>>;
421 static_assert(TreeType::DEPTH >= NodeLevelList::Size-1,
"cache size exceeds tree depth");
422 static_assert(NodeLevelList::Size > 0,
"unexpected cache size");
443 return this->evalFirstIndex([&](
const auto Idx) ->
bool
445 using NodeType =
typename NodeLevelList::template Get<Idx>;
448 if constexpr(IsRoot)
return false;
449 else return (this->isHashed<NodeType>(xyz));
459 return *this->evalFirstIndex([&](
const auto Idx) ->
const ValueType*
461 using NodeType =
typename NodeLevelList::template Get<Idx>;
465 if (!this->isHashed<NodeType>(xyz))
return nullptr;
467 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
471 auto node = mNodes.template get<Idx>();
473 return &(node->getValueAndCache(xyz, *
this));
482 return this->evalFirstCached(xyz, [&](
const auto node) ->
bool {
484 return node->isValueOnAndCache(xyz, *
this);
494 return this->evalFirstCached(xyz, [&](
const auto node) ->
bool
496 using NodeType = std::remove_pointer_t<decltype(node)>;
499 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
500 const auto offset = LeafNodeT::coordToOffset(xyz);
502 return node->isValueOn(
offset);
505 return node->probeValueAndCache(xyz, value, *
this);
518 return this->evalFirstCached(xyz, [&](
const auto node) ->
int
520 using NodeType = std::remove_pointer_t<decltype(node)>;
524 return node->getValueDepthAndCache(xyz, *
this);
527 return int(RootNodeT::LEVEL - node->getValueLevelAndCache(xyz, *
this));
539 static_cast<int>(RootNodeT::LEVEL);
553 this->evalFirstCached(xyz, [&](
const auto node) ->
void
555 using NodeType = std::remove_pointer_t<decltype(node)>;
558 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
559 const auto offset = LeafNodeT::coordToOffset(xyz);
564 const_cast<NodeType*
>(node)->setValueAndCache(xyz, value, *
this);
583 this->evalFirstIndex([&](
const auto Idx) ->
bool
585 using NodeType =
typename NodeLevelList::template Get<Idx>;
586 if (!this->isHashed<NodeType>(xyz))
return false;
588 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
592 auto node = mNodes.template get<Idx>();
594 const_cast<NodeType*
>(node)->setValueOnlyAndCache(xyz, value, *
this);
610 this->evalFirstCached(xyz, [&](
const auto node) ->
void
612 using NodeType = std::remove_pointer_t<decltype(node)>;
615 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
616 const auto offset = LeafNodeT::coordToOffset(xyz);
621 const_cast<NodeType*
>(node)->setValueOffAndCache(xyz, value, *
this);
631 template<
typename ModifyOp>
635 this->evalFirstCached(xyz, [&](
const auto node) ->
void
637 using NodeType = std::remove_pointer_t<decltype(node)>;
640 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
641 const auto offset = LeafNodeT::coordToOffset(xyz);
646 const_cast<NodeType*
>(node)->modifyValueAndCache(xyz, op, *
this);
655 template<
typename ModifyOp>
659 this->evalFirstCached(xyz, [&](
const auto node) ->
void
661 using NodeType = std::remove_pointer_t<decltype(node)>;
664 if constexpr(IsLeafAndBypassLeafAPI<NodeType>) {
665 const auto offset = LeafNodeT::coordToOffset(xyz);
666 bool state = node->isValueOn(
offset);
671 const_cast<NodeType*
>(node)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
686 this->evalFirstCached(xyz, [&](
const auto node) ->
void
688 using NodeType = std::remove_pointer_t<decltype(node)>;
690 const_cast<NodeType*
>(node)->setActiveStateAndCache(xyz, on, *
this);
718 return this->evalFirstCached(xyz, [&](
const auto node) ->
LeafNodeT*
720 using NodeType = std::remove_pointer_t<decltype(node)>;
722 return const_cast<NodeType*
>(node)->touchLeafAndCache(xyz, *
this);
733 static_assert(Start >= 0);
735 this->evalFirstCached<Start>(leaf->origin(), [&](
const auto node) ->
void
737 using NodeType = std::remove_pointer_t<decltype(node)>;
739 const_cast<NodeType*
>(node)->addLeafAndCache(leaf, *
this);
758 static_assert(Start >= 0);
759 this->evalFirstCached<Start>(xyz, [&](
const auto node) ->
void
761 using NodeType = std::remove_pointer_t<decltype(node)>;
763 const_cast<NodeType*
>(node)->addTileAndCache(level, xyz, value, state, *
this);
776 template<
typename NodeT>
780 return this->evalFirstPred([&](
const auto Idx) ->
bool
782 using NodeType =
typename NodeLevelList::template Get<Idx>;
784 constexpr
bool NodeMayBeCached =
787 if constexpr(NodeMayBeCached)
return this->isHashed<NodeType>(xyz);
790 [&](
const auto node) -> NodeT*
792 using NodeType = std::remove_pointer_t<decltype(node)>;
795 return const_cast<NodeT*
>(node);
798 assert(NodeT::LEVEL < NodeType::LEVEL);
799 return const_cast<NodeType*
>(node)->
template probeNodeAndCache<NodeT>(xyz, *
this);
804 template<
typename NodeT>
807 return this->evalFirstPred([&](
const auto Idx) ->
bool
809 using NodeType =
typename NodeLevelList::template Get<Idx>;
811 constexpr
bool NodeMayBeCached =
814 if constexpr(NodeMayBeCached)
return this->isHashed<NodeType>(xyz);
817 [&](
const auto node) ->
const NodeT*
819 using NodeType = std::remove_pointer_t<decltype(node)>;
825 assert(NodeT::LEVEL < NodeType::LEVEL);
826 return const_cast<NodeType*
>(node)->
template probeConstNodeAndCache<NodeT>(xyz, *
this);
840 return this->
template probeConstNode<LeafNodeT>(xyz);
847 template<
typename NodeT>
851 static constexpr int64_t Idx = NodeLevelList::template
Index<NodeType>;
852 if constexpr (Idx >= 0)
return mNodes.template get<Idx>();
859 template<
typename NodeT>
868 template<
typename NodeT>
871 static constexpr int64_t Idx = NodeLevelList::template
Index<NodeT>;
872 if constexpr (Idx >= 0) {
874 mNodes.template get<Idx>() =
nullptr;
883 mNodes.foreach([](
auto& node) { node =
nullptr; });
889 mNodes.template get<Idx>() = const_cast<RootNodeT*>(&(
BaseT::mTree->root()));
911 template<
typename>
friend class Tree;
929 template<
typename NodeT>
931 [[maybe_unused]]
const Coord& xyz,
932 [[maybe_unused]]
const NodeT* node)
const
935 if constexpr(!NodeLevelList::template Contains<NodeT>)
return;
937 constexpr uint64_t Idx = uint64_t(NodeLevelList::template
Index<NodeT>);
938 static_assert(NodeLevelList::template Contains<NodeT>);
940 mKeys[Idx] = xyz & ~(NodeT::DIM-1);
941 mNodes.template get<Idx>() = const_cast<NodeT*>(node);
942 if constexpr(IsLeafAndBypassLeafAPI<NodeT>) {
948 template<
typename NodeT>
951 if constexpr(!NodeLevelList::template Contains<NodeT>)
return false;
956 constexpr uint64_t Idx = uint64_t(NodeLevelList::template
Index<NodeT>);
957 static_assert(NodeLevelList::template Contains<NodeT>);
960 && (xyz[1] & ~Coord
::ValueType(NodeT::DIM-1)) == mKeys[Idx][1]
969 template <
typename OpT>
974 [[maybe_unused]]
const auto lock = this->
lock();
976 using IndexT = std::integral_constant<std::size_t, 0>;
978 return openvdb::evalFirstIndex<0, NumCacheLevels+1>(op, RetT(NULL));
986 template <
typename PredT,
typename OpT>
991 [[maybe_unused]]
const auto lock = this->
lock();
994 return mNodes.evalFirstPred(pred, op, RetT(
false));
997 return mNodes.evalFirstPred(pred, op);
1006 template <
size_t Start = 0,
typename OpT =
void>
1009 return this->evalFirstPred([&](
const auto Idx) ->
bool
1011 if constexpr(Idx < Start) return false;
1027 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
void release() overridefinal
Release this accessor from the tree, set the tree to null and clear the accessor cache. After calling this method the accessor will be completely invalid.
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value at the given coordinate and mark mark the coordinate as active...
const NodeT * probeConstNode(const Coord &xyz) const
Return a pointer to the node of the specified type that contains the value located at xyz...
constexpr void setBuffer(const typename TreeTypeT::ValueType *) const
virtual void clear()=0
Pure virtual method, clears the derived accessor.
GLsizei const GLfloat * value
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
ValueAccessorBase & operator=(const ValueAccessorBase &other)
typename NodeLevelList::template Get< Level > NodeTypeAtLevel
Return a node type at a particular cache level in the Value accessor. The node type at a given cache ...
#define OPENVDB_USE_VERSION_NAMESPACE
**But if you need a or simply need to know when the task has note that the like this
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
ValueAccessorBase(const ValueAccessorBase &other)
Copy constructor - if IsSafe, then the copy also registers itself against the tree it is accessing...
A small class that contains a Mutex which is derived from by the internal Value Accessor Implementati...
Specialization for the case where no Mutex is in use. See above.
void setValue(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as active. ...
std::decay_t< decltype(make_index_sequence_impl< N >())> make_index_sequence
ValueAccessorBase(TreeType &tree)
Construct from a tree. Should rarely be invoked directly, the drived implementation class calls this...
constexpr TreeTypeT::ValueType * buffer()
typename RootNodeT::NodeChainType NodeChainT
OPENVDB_FORCE_INLINE void insert([[maybe_unused]] const Coord &xyz, [[maybe_unused]] const NodeT *node) const
Insert a node into this ValueAccessor's cache.
typename TreeType::ValueType ValueType
OPENVDB_FORCE_INLINE bool isHashed([[maybe_unused]] const Coord &xyz) const
const TreeTypeT::ValueType * buffer() const
typename value_accessor_internal::NodeListBuilder< NodeChainT, RootNodeT::LEVEL, IntegerSequence >::ListT NodeLevelList
A resolved, flattened TypeList of node types which this accessor is caching. The nodes index in this ...
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the value at a given coordinate as well as its value.
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides, or -1 if (x...
constexpr TreeTypeT::ValueType * buffer() const
void setValueOn(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as active. ...
static constexpr bool isSafe()
Return true if this accessor is safe, i.e. registered by the tree from which it is constructed...
typename NodeLevelList::template Transform< std::add_pointer_t > NodePtrList
ValueAccessorImpl(TreeType &tree)
Constructor from a tree.
NodeT * getNode()
Return the node of type NodeT that has been cached on this accessor. If this accessor does not cache ...
bool isVoxel(const Coord &xyz) const
Return 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.
A small class that contains a cached pointer to a LeafNode data buffer which is derived from by the i...
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists...
~ValueAccessorImpl() overridefinal=default
integer_sequence< std::size_t, Ints...> index_sequence
GLboolean GLboolean GLboolean b
const LeafNodeT * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists...
static constexpr bool IsConstTree
Returns true if this accessor is operating on a const tree type.
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
TreeType * getTree() const
Return a pointer to the tree associated with this accessor.
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
static constexpr bool BypassLeafAPI
void setBuffer(const typename TreeTypeT::ValueType *b) const
LeafNodeT * touchLeaf(const Coord &xyz)
Returns the leaf node that contains voxel (x, y, z) and if it doesn't exist, create it...
Library and file format version numbers.
constexpr auto lock() const
static constexpr Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
typename TreeType::LeafNodeType LeafNodeT
static constexpr bool IsLeafAndBypassLeafAPI
Given a node type, return whether this Accessor can perform optimized value buffer accesses...
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists...
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const TreeTypeT::ValueType * buffer()
void insertNode(const Coord &xyz, NodeT &node)
Explicitly insert a node of the type NodeT into this Value Accessors cache.
void eraseNode()
Explicitly remove this Value Accessors cached node of the given NodeT. If this Value Accessor does no...
static constexpr size_t NumCacheLevels
The number of node levels that this accessor can cache, excluding the RootNode.
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node of the specified type that contains the value located at xyz...
void setValueOff(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as inactive.
static constexpr bool BypassLeafAPI
Helper alias which is true if the lowest cached node level is a LeafNode type and has a compatible va...
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
bool isCached(const Coord &xyz) const
Return true if any of the nodes along the path to the given coordinate have been cached.
typename TreeType::RootNodeType RootNodeT
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
A list of types (not necessarily unique)
void setValueOnly(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate but preserve its active state.
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains the coordinate xyz, possibly deleting existing n...
TreeType & tree() const
Return a reference to the tree associated with this accessor.
virtual ~ValueAccessorBase()
friend class InternalNode
void clear() overridefinal
Remove all the cached nodes and invalidate the corresponding hash-keys.