OpenVDB  9.0.1
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 
28 class GEO_PrimVDB;
29 class GU_Detail;
30 class UT_String;
31 
32 namespace openvdb_houdini {
33 
38 using GridCRef = const openvdb::GridBase&;
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 {
49 public:
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 
65  VdbPrimCIterator& operator=(const VdbPrimCIterator&);
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 
106 protected:
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 {
124 public:
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 
152  VdbPrimIterator& operator=(const VdbPrimIterator&);
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
174 class HoudiniInterrupter final: public openvdb::util::NullInterrupter
175 {
176 public:
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 
182  HoudiniInterrupter(const HoudiniInterrupter&) = default;
183  HoudiniInterrupter& operator=(const HoudiniInterrupter&) = default;
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 
198 private:
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 {
210 public:
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 
229 private:
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.
247 GU_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.
261 GU_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.
268 bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel = false);
269 
270 
271 /// Construct an index-space CoordBBox from a UT_BoundingBox.
273 openvdb::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()
288 void 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()
301 void 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()
307 bool 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 
332  openvdb::DoubleGrid>;
333 
338 
341 
343 
344 using 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
350 template<typename GridTypeListT, typename OpT>
351 inline bool
352 GEOvdbApply(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.
365 template<typename GridTypeListT, typename OpT>
366 inline bool
367 GEOvdbApply(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
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition: TypeList.h:440
VdbPrimIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:155
std::function< bool(const GU_PrimVDB &)> FilterFunc
Definition: Utils.h:50
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:81
Grid< PointDataTree > PointDataGrid
Point data grid.
Definition: PointDataGrid.h:194
GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:159
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< BoolTree > BoolGrid
Common grid types.
Definition: openvdb.h:42
Abstract base class for typed grids.
Definition: Grid.h:77
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
OPENVDB_HOUDINI_API void startLogForwarding(OP_OpTypeId)
Start forwarding OpenVDB log messages to the Houdini error manager for all operators of the given typ...
Grid< Vec3DTree > Vec3DGrid
Definition: openvdb.h:48
#define OPENVDB_HOUDINI_API
Definition: Platform.h:262
HoudiniInterrupter(const char *title=nullptr)
Definition: Utils.h:177
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
~HoudiniInterrupter() override final
Definition: Utils.h:180
Grid< FloatTree > FloatGrid
Definition: openvdb.h:44
GU_PrimVDB * operator*() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:162
GA_Offset getOffset() const
Definition: Utils.h:81
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:35
const GU_PrimVDB * operator->() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:77
void end()
Signal the end of an interruptible operation.
Definition: Utils.h:219
OPENVDB_HOUDINI_API openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox &, const openvdb::math::Transform &)
Construct an index-space CoordBBox from a UT_BoundingBox.
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
VdbPrimCIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:70
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:122
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
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).
Grid< Int32Tree > Int32Grid
Definition: openvdb.h:45
bool wasInterrupted(int percent=-1)
Check if an interruptible operation should be aborted.
Definition: Utils.h:224
ScalarGridTypes::Append< Vec3GridTypes > VolumeGridTypes
Definition: Utils.h:342
Iterator over const VDB primitives on a geometry detail.
Definition: Utils.h:47
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.
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:352
VolumeGridTypes::Append< PointGridTypes > AllGridTypes
Definition: Utils.h:344
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
Deprecated wrapper class with the same interface as HoudiniInterrupter, however it does not derive fr...
Definition: Utils.h:208
Definition: AttributeTransferUtil.h:34
Grid< Vec3STree > Vec3SGrid
Definition: openvdb.h:50
Grid< DoubleTree > DoubleGrid
Definition: openvdb.h:43
FilterFunc mFilter
Definition: Utils.h:112
openvdb::GridBase::ConstPtr GridCPtr
Definition: Utils.h:36
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:187
UT_SharedPtr< GA_GBPrimitiveIterator > mIter
Definition: Utils.h:111
VdbPrimIterator(GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
Definition: Utils.h:134
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:196
A list of types (not necessarily unique)
Definition: TypeList.h:365
void end() override final
Signal the end of an interruptible operation.
Definition: Utils.h:191
const GU_PrimVDB * operator*() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:76
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:123
GU_PrimVDB * operator->() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:163
Wrapper class that adapts a Houdini UT_Interrupt object for use with OpenVDB library routines...
Definition: Utils.h:174