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