OpenVDB  12.1.0
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 
29 class GEO_PrimVDB;
30 class GU_Detail;
31 class 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 
41 namespace openvdb_houdini {
42 
47 using GridCRef = const openvdb::GridBase&;
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 {
58 public:
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 
74  VdbPrimCIterator& operator=(const VdbPrimCIterator&);
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 
115 protected:
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 {
133 public:
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 
161  VdbPrimIterator& operator=(const VdbPrimIterator&);
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
183 class HoudiniInterrupter final: public openvdb::util::NullInterrupter
184 {
185 public:
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 
191  HoudiniInterrupter(const HoudiniInterrupter&) = default;
192  HoudiniInterrupter& operator=(const HoudiniInterrupter&) = default;
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 
207 private:
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 {
219 public:
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 
238 private:
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.
256 GU_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.
270 GU_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.
277 bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel = false);
278 
279 
280 /// Construct an index-space CoordBBox from a UT_BoundingBox.
282 openvdb::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()
297 void 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()
310 void 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()
316 bool 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 
341  openvdb::DoubleGrid>;
342 
347 
350 
352 
353 using 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
359 template<typename GridTypeListT, typename OpT>
360 inline bool
361 GEOvdbApply(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.
374 template<typename GridTypeListT, typename OpT>
375 inline bool
376 GEOvdbApply(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
VdbPrimIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:164
std::function< bool(const GU_PrimVDB &)> FilterFunc
Definition: Utils.h:59
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:81
GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:168
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.
Grid< Vec3DTree > Vec3DGrid
Definition: openvdb.h:79
OPENVDB_HOUDINI_API void startLogForwarding(OP_OpTypeId)
Start forwarding OpenVDB log messages to the Houdini error manager for all operators of the given typ...
#define OPENVDB_HOUDINI_API
Definition: Platform.h:299
HoudiniInterrupter(const char *title=nullptr)
Definition: Utils.h:186
openvdb::util::NullInterrupter & interrupter()
Return a reference to the base class of the stored interrupter.
Definition: Utils.h:236
Grid< FloatTree > FloatGrid
Definition: openvdb.h:75
void start(const char *name=nullptr)
Signal the start of an interruptible operation.
Definition: Utils.h:226
OutGridT XformOp & op
Definition: ValueTransformer.h:139
A list of types (not necessarily unique)
Definition: TypeList.h:577
~HoudiniInterrupter() override final
Definition: Utils.h:189
GU_PrimVDB * operator*() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:171
GA_Offset getOffset() const
Definition: Utils.h:90
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:44
Grid< Int32Tree > Int32Grid
Definition: openvdb.h:76
const GU_PrimVDB * operator->() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:86
void end()
Signal the end of an interruptible operation.
Definition: Utils.h:228
OPENVDB_HOUDINI_API openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox &, const openvdb::math::Transform &)
Construct an index-space CoordBBox from a UT_BoundingBox.
VdbPrimCIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:79
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...
Iterator over non-const VDB primitives on a geometry detail.
Definition: Utils.h:131
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
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).
Grid< DoubleTree > DoubleGrid
Definition: openvdb.h:74
bool wasInterrupted(int percent=-1)
Check if an interruptible operation should be aborted.
Definition: Utils.h:233
ScalarGridTypes::Append< Vec3GridTypes > VolumeGridTypes
Definition: Utils.h:351
Iterator over const VDB primitives on a geometry detail.
Definition: Utils.h:56
OPENVDB_HOUDINI_API bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel=false)
Return in corners the corners of the given grid&#39;s active voxel bounding box.
OutGridT const XformOp bool bool
Definition: ValueTransformer.h:609
bool GEOvdbApply(const GEO_PrimVDB &vdb, OpT &op)
If the given primitive&#39;s grid resolves to one of the listed grid types, invoke the functor op on the ...
Definition: Utils.h:361
VolumeGridTypes::Append< PointGridTypes > AllGridTypes
Definition: Utils.h:353
Abstract base class for typed grids.
Definition: Grid.h:77
Deprecated wrapper class with the same interface as HoudiniInterrupter, however it does not derive fr...
Definition: Utils.h:217
unsigned OP_OutputIdx
Definition: Utils.h:38
Definition: AttributeTransferUtil.h:34
FilterFunc mFilter
Definition: Utils.h:121
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition: TypeList.h:656
openvdb::GridBase::ConstPtr GridCPtr
Definition: Utils.h:45
unsigned OP_InputIdx
Definition: Utils.h:37
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
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.
void start(const char *name=nullptr) override final
Signal the start of an interruptible operation.
Definition: Utils.h:196
Grid< Vec3STree > Vec3SGrid
Definition: openvdb.h:81
UT_SharedPtr< GA_GBPrimitiveIterator > mIter
Definition: Utils.h:120
VdbPrimIterator(GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
Definition: Utils.h:143
OPENVDB_HOUDINI_API void stopLogForwarding(OP_OpTypeId)
Stop forwarding OpenVDB log messages to the Houdini error manager for all operators of the given type...
bool wasInterrupted(int percent=-1) override final
Check if an interruptible operation should be aborted.
Definition: Utils.h:205
void end() override final
Signal the end of an interruptible operation.
Definition: Utils.h:200
const GU_PrimVDB * operator*() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:85
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:171
GU_PrimVDB * operator->() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:172
Wrapper class that adapts a Houdini UT_Interrupt object for use with OpenVDB library routines...
Definition: Utils.h:183
Grid< BoolTree > BoolGrid
Common grid types.
Definition: openvdb.h:73
Grid< PointDataTree > PointDataGrid
Point data grid.
Definition: PointDataGrid.h:195