OpenVDB 10.0.1
Loading...
Searching...
No Matches
Utils.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3//
4/// @file openvdb_houdini/Utils.h
5/// @author FX R&D Simulation team
6/// @brief Utility classes and functions for OpenVDB plugins
7
8#ifndef OPENVDB_HOUDINI_UTILS_HAS_BEEN_INCLUDED
9#define OPENVDB_HOUDINI_UTILS_HAS_BEEN_INCLUDED
10
11#include "GU_PrimVDB.h"
12#include <OP/OP_Node.h> // for OP_OpTypeId
13#include <UT/UT_SharedPtr.h>
14#include <UT/UT_Interrupt.h>
15#include <openvdb/openvdb.h>
17#include <functional>
18#include <type_traits>
19
20
21#ifdef SESI_OPENVDB
22#ifdef OPENVDB_HOUDINI_API
23 #undef OPENVDB_HOUDINI_API
24 #define OPENVDB_HOUDINI_API
25#endif
26#endif
27
28class GEO_PrimVDB;
29class GU_Detail;
30class UT_String;
31
32namespace openvdb_houdini {
33
35using GridPtr = openvdb::GridBase::Ptr;
36using GridCPtr = openvdb::GridBase::ConstPtr;
39
40
41/// @brief Iterator over const VDB primitives on a geometry detail
42///
43/// @details At least until @c GEO_PrimVDB becomes a built-in primitive type
44/// (that can be used as the mask for a @c GA_GBPrimitiveIterator), use this
45/// iterator to iterate over all VDB grids belonging to a gdp and, optionally,
46/// belonging to a particular group.
48{
49public:
50 using FilterFunc = std::function<bool (const GU_PrimVDB&)>;
51
52 /// @param gdp
53 /// the geometry detail over which to iterate
54 /// @param group
55 /// a group in the detail over which to iterate (if @c nullptr,
56 /// iterate over all VDB primitives)
57 /// @param filter
58 /// an optional function or functor that takes a const reference
59 /// to a GU_PrimVDB and returns a boolean specifying whether
60 /// that primitive should be visited (@c true) or not (@c false)
61 explicit VdbPrimCIterator(const GEO_Detail* gdp, const GA_PrimitiveGroup* group = nullptr,
62 FilterFunc filter = FilterFunc());
63
66
67 //@{
68 /// Advance to the next VDB primitive.
69 void advance();
70 VdbPrimCIterator& operator++() { advance(); return *this; }
71 //@}
72
73 //@{
74 /// Return a pointer to the current VDB primitive (@c nullptr if at end).
75 const GU_PrimVDB* getPrimitive() const;
76 const GU_PrimVDB* operator*() const { return getPrimitive(); }
77 const GU_PrimVDB* operator->() const { return getPrimitive(); }
78 //@}
79
80 //@{
81 GA_Offset getOffset() const { return getPrimitive()->getMapOffset(); }
82 GA_Index getIndex() const { return getPrimitive()->getMapIndex(); }
83 //@}
84
85 /// Return @c false if there are no more VDB primitives.
86 operator bool() const { return getPrimitive() != nullptr; }
87
88 /// @brief Return the value of the current VDB primitive's @c name attribute.
89 /// @param defaultName
90 /// if the current primitive has no @c name attribute
91 /// or its name is empty, return this name instead
92 UT_String getPrimitiveName(const UT_String& defaultName = "") const;
93
94 /// @brief Return the value of the current VDB primitive's @c name attribute
95 /// or, if the name is empty, the primitive's index (as a UT_String).
96 UT_String getPrimitiveNameOrIndex() const;
97
98 /// @brief Return a string of the form "N (NAME)", where @e N is
99 /// the current VDB primitive's index and @e NAME is the value
100 /// of the primitive's @c name attribute.
101 /// @param keepEmptyName if the current primitive has no @c name attribute
102 /// or its name is empty, then if this flag is @c true, return a string
103 /// "N ()", otherwise return a string "N" omitting the empty name
104 UT_String getPrimitiveIndexAndName(bool keepEmptyName = true) const;
105
106protected:
107 /// Allow primitives to be deleted during iteration.
108 VdbPrimCIterator(const GEO_Detail*, GA_Range::safedeletions,
109 const GA_PrimitiveGroup* = nullptr, FilterFunc = FilterFunc());
110
111 UT_SharedPtr<GA_GBPrimitiveIterator> mIter;
113}; // class VdbPrimCIterator
114
115
116/// @brief Iterator over non-const VDB primitives on a geometry detail
117///
118/// @details At least until @c GEO_PrimVDB becomes a built-in primitive type
119/// (that can be used as the mask for a @c GA_GBPrimitiveIterator), use this
120/// iterator to iterate over all VDB grids belonging to a gdp and, optionally,
121/// belonging to a particular group.
123{
124public:
125 /// @param gdp
126 /// the geometry detail over which to iterate
127 /// @param group
128 /// a group in the detail over which to iterate (if @c nullptr,
129 /// iterate over all VDB primitives)
130 /// @param filter
131 /// an optional function or functor that takes a @c const reference
132 /// to a GU_PrimVDB and returns a boolean specifying whether
133 /// that primitive should be visited (@c true) or not (@c false)
134 explicit VdbPrimIterator(GEO_Detail* gdp, const GA_PrimitiveGroup* group = nullptr,
135 FilterFunc filter = FilterFunc()):
136 VdbPrimCIterator(gdp, group, filter) {}
137 /// @brief Allow primitives to be deleted during iteration.
138 /// @param gdp
139 /// the geometry detail over which to iterate
140 /// @param group
141 /// a group in the detail over which to iterate (if @c nullptr,
142 /// iterate over all VDB primitives)
143 /// @param filter
144 /// an optional function or functor that takes a @c const reference
145 /// to a GU_PrimVDB and returns a boolean specifying whether
146 /// that primitive should be visited (@c true) or not (@c false)
147 VdbPrimIterator(GEO_Detail* gdp, GA_Range::safedeletions,
148 const GA_PrimitiveGroup* group = nullptr, FilterFunc filter = FilterFunc()):
149 VdbPrimCIterator(gdp, GA_Range::safedeletions(), group, filter) {}
150
153
154 /// Advance to the next VDB primitive.
155 VdbPrimIterator& operator++() { advance(); return *this; }
156
157 //@{
158 /// Return a pointer to the current VDB primitive (@c nullptr if at end).
159 GU_PrimVDB* getPrimitive() const {
160 return const_cast<GU_PrimVDB*>(VdbPrimCIterator::getPrimitive());
161 }
162 GU_PrimVDB* operator*() const { return getPrimitive(); }
163 GU_PrimVDB* operator->() const { return getPrimitive(); }
164 //@}
165}; // class VdbPrimIterator
166
167
168////////////////////////////////////////
169
170
171/// @brief Wrapper class that adapts a Houdini @c UT_Interrupt object
172/// for use with OpenVDB library routines
173/// @sa openvdb/util/NullInterrupter.h
174class HoudiniInterrupter final: public openvdb::util::NullInterrupter
175{
176public:
177 explicit HoudiniInterrupter(const char* title = nullptr):
178 mUTI{UTgetInterrupt()}, mRunning{false}, mTitle{title ? title : ""}
179 {}
180 ~HoudiniInterrupter() override final { if (mRunning) this->end(); }
181
184
185 /// @brief Signal the start of an interruptible operation.
186 /// @param name an optional descriptive name for the operation
187 void start(const char* name = nullptr) override final {
188 if (!mRunning) { mRunning = true; mUTI->opStart(name ? name : mTitle.c_str()); }
189 }
190 /// Signal the end of an interruptible operation.
191 void end() override final { if (mRunning) { mUTI->opEnd(); mRunning = false; } }
192
193 /// @brief Check if an interruptible operation should be aborted.
194 /// @param percent an optional (when >= 0) percentage indicating
195 /// the fraction of the operation that has been completed
196 bool wasInterrupted(int percent=-1) override final { return mUTI->opInterrupt(percent); }
197
198private:
199 UT_Interrupt* mUTI;
200 bool mRunning;
201 std::string mTitle;
202};
203
204
205/// @brief Deprecated wrapper class with the same interface as HoudiniInterrupter,
206/// however it does not derive from openvdb::util::NullInterrupter.
207/// Intended for backwards-compatibility only.
209{
210public:
211 OPENVDB_DEPRECATED_MESSAGE("openvdb_houdini::Interrupter has been deprecated, use openvdb_houdini::HoudiniInterrupter")
212 explicit Interrupter(const char* title = nullptr):
213 mInterrupt(title) { }
214
215 /// @brief Signal the start of an interruptible operation.
216 /// @param name an optional descriptive name for the operation
217 void start(const char* name = nullptr) { mInterrupt.start(name); }
218 /// Signal the end of an interruptible operation.
219 void end() { mInterrupt.end(); }
220
221 /// @brief Check if an interruptible operation should be aborted.
222 /// @param percent an optional (when >= 0) percentage indicating
223 /// the fraction of the operation that has been completed
224 bool wasInterrupted(int percent=-1) { return mInterrupt.wasInterrupted(percent); }
225
226 /// @brief Return a reference to the base class of the stored interrupter
227 openvdb::util::NullInterrupter& interrupter() { return mInterrupt.interrupter(); }
228
229private:
230 HoudiniInterrupter mInterrupt;
231};
232
233
234////////////////////////////////////////
235
236
237// Utility methods
238
239/// @brief Store a VDB grid in a new VDB primitive and add the primitive
240/// to a geometry detail.
241/// @return the newly-created VDB primitive.
242/// @param gdp the detail to which to add the primitive
243/// @param grid the VDB grid to be added
244/// @param name if non-null, set the new primitive's @c name attribute to this string
245/// @note This operation clears the input grid's metadata.
247GU_PrimVDB* createVdbPrimitive(GU_Detail& gdp, GridPtr grid, const char* name = nullptr);
248
249
250/// @brief Replace an existing VDB primitive with a new primitive that contains
251/// the given grid.
252/// @return the newly-created VDB primitive.
253/// @param gdp the detail to which to add the primitive
254/// @param grid the VDB grid to be added
255/// @param src replace this primitive with the newly-created primitive
256/// @param copyAttrs if @c true, copy attributes and group membership from the @a src primitive
257/// @param name if non-null, set the new primitive's @c name attribute to this string;
258/// otherwise, if @a copyAttrs is @c true, copy the name from @a src
259/// @note This operation clears the input grid's metadata.
261GU_PrimVDB* replaceVdbPrimitive(GU_Detail& gdp, GridPtr grid, GEO_PrimVDB& src,
262 const bool copyAttrs = true, const char* name = nullptr);
263
264
265/// @brief Return in @a corners the corners of the given grid's active voxel bounding box.
266/// @return @c false if the grid has no active voxels.
268bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel = false);
269
270
271/// Construct an index-space CoordBBox from a UT_BoundingBox.
273openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox&, const openvdb::math::Transform&);
274
275
276/// @{
277/// @brief Start forwarding OpenVDB log messages to the Houdini error manager
278/// for all operators of the given type.
279/// @details Typically, log forwarding is enabled for specific operator types
280/// during initialization of the openvdb_houdini library, and there's no need
281/// for client code to call this function.
282/// @details This function has no effect unless OpenVDB was built with
283/// <A HREF="http://log4cplus.sourceforge.net/">log4cplus</A>.
284/// @note OpenVDB messages are typically logged to the console as well.
285/// This function has no effect on console logging.
286/// @sa stopLogForwarding(), isLogForwarding()
288void startLogForwarding(OP_OpTypeId);
289
290/// @brief Stop forwarding OpenVDB log messages to the Houdini error manager
291/// for all operators of the given type.
292/// @details Typically, log forwarding is enabled for specific operator types
293/// during initialization of the openvdb_houdini library, and there's no need
294/// for client code to disable it.
295/// @details This function has no effect unless OpenVDB was built with
296/// <A HREF="http://log4cplus.sourceforge.net/">log4cplus</A>.
297/// @note OpenVDB messages are typically logged to the console as well.
298/// This function has no effect on console logging.
299/// @sa startLogForwarding(), isLogForwarding()
301void stopLogForwarding(OP_OpTypeId);
302
303/// @brief Return @c true if OpenVDB messages logged by operators
304/// of the given type are forwarded to the Houdini error manager.
305/// @sa startLogForwarding(), stopLogForwarding()
307bool isLogForwarding(OP_OpTypeId);
308/// @}
309
310
311////////////////////////////////////////
312
313
314// Grid type lists, for use with GEO_PrimVDB::apply(), GEOvdbApply(),
315// or openvdb::GridBase::apply()
316
323
329
333
338
340 openvdb::points::PointDataGrid>;
341
343
344using AllGridTypes = VolumeGridTypes::Append<PointGridTypes>;
345
346
347/// @brief If the given primitive's grid resolves to one of the listed grid types,
348/// invoke the functor @a op on the resolved grid.
349/// @return @c true if the functor was invoked, @c false otherwise
350template<typename GridTypeListT, typename OpT>
351inline bool
352GEOvdbApply(const GEO_PrimVDB& vdb, OpT& op)
353{
354 if (auto gridPtr = vdb.getConstGridPtr()) {
355 return gridPtr->apply<GridTypeListT>(op);
356 }
357 return false;
358}
359
360/// @brief If the given primitive's grid resolves to one of the listed grid types,
361/// invoke the functor @a op on the resolved grid.
362/// @return @c true if the functor was invoked, @c false otherwise
363/// @details If @a makeUnique is true, deep copy the grid's tree before
364/// invoking the functor if the tree is shared with other grids.
365template<typename GridTypeListT, typename OpT>
366inline bool
367GEOvdbApply(GEO_PrimVDB& vdb, OpT& op, bool makeUnique = true)
368{
369 if (vdb.hasGrid()) {
370 auto gridPtr = vdb.getGridPtr();
371 if (makeUnique) {
372 auto treePtr = gridPtr->baseTreePtr();
373 if (treePtr.use_count() > 2) { // grid + treePtr = 2
374 // If the grid resolves to one of the listed types and its tree
375 // is shared with other grids, replace the tree with a deep copy.
376 gridPtr->apply<GridTypeListT>(
377 [](Grid& baseGrid) { baseGrid.setTree(baseGrid.constBaseTree().copy()); });
378 }
379 }
380 return gridPtr->apply<GridTypeListT>(op);
381 }
382 return false;
383}
384
385} // namespace openvdb_houdini
386
387#endif // OPENVDB_HOUDINI_UTILS_HAS_BEEN_INCLUDED
#define OPENVDB_HOUDINI_API
Definition: Platform.h:259
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:125
Abstract base class for typed grids.
Definition: Grid.h:78
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:571
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
Wrapper class that adapts a Houdini UT_Interrupt object for use with OpenVDB library routines.
Definition: Utils.h:175
void end() override final
Signal the end of an interruptible operation.
Definition: Utils.h:191
HoudiniInterrupter & operator=(const HoudiniInterrupter &)=default
void start(const char *name=nullptr) override final
Signal the start of an interruptible operation.
Definition: Utils.h:187
~HoudiniInterrupter() override final
Definition: Utils.h:180
HoudiniInterrupter(const HoudiniInterrupter &)=default
HoudiniInterrupter(const char *title=nullptr)
Definition: Utils.h:177
bool wasInterrupted(int percent=-1) override final
Check if an interruptible operation should be aborted.
Definition: Utils.h:196
Deprecated wrapper class with the same interface as HoudiniInterrupter, however it does not derive fr...
Definition: Utils.h:209
bool wasInterrupted(int percent=-1)
Check if an interruptible operation should be aborted.
Definition: Utils.h:224
void end()
Signal the end of an interruptible operation.
Definition: Utils.h:219
openvdb::util::NullInterrupter & interrupter()
Return a reference to the base class of the stored interrupter.
Definition: Utils.h:227
void start(const char *name=nullptr)
Signal the start of an interruptible operation.
Definition: Utils.h:217
Iterator over const VDB primitives on a geometry detail.
Definition: Utils.h:48
const GU_PrimVDB * operator*() const
Definition: Utils.h:76
std::function< bool(const GU_PrimVDB &)> FilterFunc
Definition: Utils.h:50
UT_SharedPtr< GA_GBPrimitiveIterator > mIter
Definition: Utils.h:111
GA_Index getIndex() const
Definition: Utils.h:82
const GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
const GU_PrimVDB * operator->() const
Definition: Utils.h:77
VdbPrimCIterator(const GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
FilterFunc mFilter
Definition: Utils.h:112
void advance()
Advance to the next VDB primitive.
VdbPrimCIterator & operator=(const VdbPrimCIterator &)
VdbPrimCIterator(const GEO_Detail *, GA_Range::safedeletions, const GA_PrimitiveGroup *=nullptr, FilterFunc=FilterFunc())
Allow primitives to be deleted during iteration.
VdbPrimCIterator & operator++()
Definition: Utils.h:70
UT_String getPrimitiveIndexAndName(bool keepEmptyName=true) const
Return a string of the form "N (NAME)", where N is the current VDB primitive's index and NAME is the ...
GA_Offset getOffset() const
Definition: Utils.h:81
UT_String getPrimitiveName(const UT_String &defaultName="") const
Return the value of the current VDB primitive's name attribute.
VdbPrimCIterator(const VdbPrimCIterator &)
UT_String getPrimitiveNameOrIndex() const
Return the value of the current VDB primitive's name attribute or, if the name is empty,...
Iterator over non-const VDB primitives on a geometry detail.
Definition: Utils.h:123
VdbPrimIterator & operator=(const VdbPrimIterator &)
GU_PrimVDB * operator->() const
Definition: Utils.h:163
VdbPrimIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:155
VdbPrimIterator(const VdbPrimIterator &)
GU_PrimVDB * operator*() const
Definition: Utils.h:162
VdbPrimIterator(GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
Definition: Utils.h:134
GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:159
VdbPrimIterator(GEO_Detail *gdp, GA_Range::safedeletions, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
Allow primitives to be deleted during iteration.
Definition: Utils.h:147
Grid< FloatTree > FloatGrid
Definition: openvdb.h:75
Grid< Vec3DTree > Vec3DGrid
Definition: openvdb.h:79
Grid< BoolTree > BoolGrid
Common grid types.
Definition: openvdb.h:73
Grid< Vec3STree > Vec3SGrid
Definition: openvdb.h:81
Grid< Int32Tree > Int32Grid
Definition: openvdb.h:76
Grid< DoubleTree > DoubleGrid
Definition: openvdb.h:74
Definition: AttributeTransferUtil.h:34
OPENVDB_HOUDINI_API bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel=false)
Return in corners the corners of the given grid's active voxel bounding box.
OPENVDB_HOUDINI_API bool isLogForwarding(OP_OpTypeId)
Return true if OpenVDB messages logged by operators of the given type are forwarded to the Houdini er...
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:35
OPENVDB_HOUDINI_API void stopLogForwarding(OP_OpTypeId)
Stop forwarding OpenVDB log messages to the Houdini error manager for all operators of the given type...
VolumeGridTypes::Append< PointGridTypes > AllGridTypes
Definition: Utils.h:344
OPENVDB_HOUDINI_API void startLogForwarding(OP_OpTypeId)
Start forwarding OpenVDB log messages to the Houdini error manager for all operators of the given typ...
OPENVDB_HOUDINI_API GU_PrimVDB * createVdbPrimitive(GU_Detail &gdp, GridPtr grid, const char *name=nullptr)
Store a VDB grid in a new VDB primitive and add the primitive to a geometry detail.
ScalarGridTypes::Append< Vec3GridTypes > VolumeGridTypes
Definition: Utils.h:342
bool GEOvdbApply(const GEO_PrimVDB &vdb, OpT &op)
If the given primitive's grid resolves to one of the listed grid types, invoke the functor op on the ...
Definition: Utils.h:352
OPENVDB_HOUDINI_API GU_PrimVDB * replaceVdbPrimitive(GU_Detail &gdp, GridPtr grid, GEO_PrimVDB &src, const bool copyAttrs=true, const char *name=nullptr)
Replace an existing VDB primitive with a new primitive that contains the given grid.
OPENVDB_HOUDINI_API openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox &, const openvdb::math::Transform &)
Construct an index-space CoordBBox from a UT_BoundingBox.
openvdb::GridBase::ConstPtr GridCPtr
Definition: Utils.h:36
A list of types (not necessarily unique)
Definition: TypeList.h:484
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition: TypeList.h:560