OpenVDB  8.2.0
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>
16 #include <functional>
17 #include <type_traits>
18 
19 
20 #ifdef SESI_OPENVDB
21 #ifdef OPENVDB_HOUDINI_API
22  #undef OPENVDB_HOUDINI_API
23  #define OPENVDB_HOUDINI_API
24 #endif
25 #endif
26 
27 class GEO_PrimVDB;
28 class GU_Detail;
29 class UT_String;
30 
31 namespace openvdb_houdini {
32 
37 using GridCRef = const openvdb::GridBase&;
38 
39 
40 /// @brief Iterator over const VDB primitives on a geometry detail
41 ///
42 /// @details At least until @c GEO_PrimVDB becomes a built-in primitive type
43 /// (that can be used as the mask for a @c GA_GBPrimitiveIterator), use this
44 /// iterator to iterate over all VDB grids belonging to a gdp and, optionally,
45 /// belonging to a particular group.
47 {
48 public:
49  using FilterFunc = std::function<bool (const GU_PrimVDB&)>;
50 
51  /// @param gdp
52  /// the geometry detail over which to iterate
53  /// @param group
54  /// a group in the detail over which to iterate (if @c nullptr,
55  /// iterate over all VDB primitives)
56  /// @param filter
57  /// an optional function or functor that takes a const reference
58  /// to a GU_PrimVDB and returns a boolean specifying whether
59  /// that primitive should be visited (@c true) or not (@c false)
60  explicit VdbPrimCIterator(const GEO_Detail* gdp, const GA_PrimitiveGroup* group = nullptr,
61  FilterFunc filter = FilterFunc());
62 
65 
66  //@{
67  /// Advance to the next VDB primitive.
68  void advance();
69  VdbPrimCIterator& operator++() { advance(); return *this; }
70  //@}
71 
72  //@{
73  /// Return a pointer to the current VDB primitive (@c nullptr if at end).
74  const GU_PrimVDB* getPrimitive() const;
75  const GU_PrimVDB* operator*() const { return getPrimitive(); }
76  const GU_PrimVDB* operator->() const { return getPrimitive(); }
77  //@}
78 
79  //@{
80  GA_Offset getOffset() const { return getPrimitive()->getMapOffset(); }
81  GA_Index getIndex() const { return getPrimitive()->getMapIndex(); }
82  //@}
83 
84  /// Return @c false if there are no more VDB primitives.
85  operator bool() const { return getPrimitive() != nullptr; }
86 
87  /// @brief Return the value of the current VDB primitive's @c name attribute.
88  /// @param defaultName
89  /// if the current primitive has no @c name attribute
90  /// or its name is empty, return this name instead
91  UT_String getPrimitiveName(const UT_String& defaultName = "") const;
92 
93  /// @brief Return the value of the current VDB primitive's @c name attribute
94  /// or, if the name is empty, the primitive's index (as a UT_String).
95  UT_String getPrimitiveNameOrIndex() const;
96 
97  /// @brief Return a string of the form "N (NAME)", where @e N is
98  /// the current VDB primitive's index and @e NAME is the value
99  /// of the primitive's @c name attribute.
100  /// @param keepEmptyName if the current primitive has no @c name attribute
101  /// or its name is empty, then if this flag is @c true, return a string
102  /// "N ()", otherwise return a string "N" omitting the empty name
103  UT_String getPrimitiveIndexAndName(bool keepEmptyName = true) const;
104 
105 protected:
106  /// Allow primitives to be deleted during iteration.
107  VdbPrimCIterator(const GEO_Detail*, GA_Range::safedeletions,
108  const GA_PrimitiveGroup* = nullptr, FilterFunc = FilterFunc());
109 
110  UT_SharedPtr<GA_GBPrimitiveIterator> mIter;
112 }; // class VdbPrimCIterator
113 
114 
115 /// @brief Iterator over non-const VDB primitives on a geometry detail
116 ///
117 /// @details At least until @c GEO_PrimVDB becomes a built-in primitive type
118 /// (that can be used as the mask for a @c GA_GBPrimitiveIterator), use this
119 /// iterator to iterate over all VDB grids belonging to a gdp and, optionally,
120 /// belonging to a particular group.
122 {
123 public:
124  /// @param gdp
125  /// the geometry detail over which to iterate
126  /// @param group
127  /// a group in the detail over which to iterate (if @c nullptr,
128  /// iterate over all VDB primitives)
129  /// @param filter
130  /// an optional function or functor that takes a @c const reference
131  /// to a GU_PrimVDB and returns a boolean specifying whether
132  /// that primitive should be visited (@c true) or not (@c false)
133  explicit VdbPrimIterator(GEO_Detail* gdp, const GA_PrimitiveGroup* group = nullptr,
134  FilterFunc filter = FilterFunc()):
135  VdbPrimCIterator(gdp, group, filter) {}
136  /// @brief Allow primitives to be deleted during iteration.
137  /// @param gdp
138  /// the geometry detail over which to iterate
139  /// @param group
140  /// a group in the detail over which to iterate (if @c nullptr,
141  /// iterate over all VDB primitives)
142  /// @param filter
143  /// an optional function or functor that takes a @c const reference
144  /// to a GU_PrimVDB and returns a boolean specifying whether
145  /// that primitive should be visited (@c true) or not (@c false)
146  VdbPrimIterator(GEO_Detail* gdp, GA_Range::safedeletions,
147  const GA_PrimitiveGroup* group = nullptr, FilterFunc filter = FilterFunc()):
148  VdbPrimCIterator(gdp, GA_Range::safedeletions(), group, filter) {}
149 
152 
153  /// Advance to the next VDB primitive.
154  VdbPrimIterator& operator++() { advance(); return *this; }
155 
156  //@{
157  /// Return a pointer to the current VDB primitive (@c nullptr if at end).
158  GU_PrimVDB* getPrimitive() const {
159  return const_cast<GU_PrimVDB*>(VdbPrimCIterator::getPrimitive());
160  }
161  GU_PrimVDB* operator*() const { return getPrimitive(); }
162  GU_PrimVDB* operator->() const { return getPrimitive(); }
163  //@}
164 }; // class VdbPrimIterator
165 
166 
167 ////////////////////////////////////////
168 
169 
170 /// @brief Wrapper class that adapts a Houdini @c UT_Interrupt object
171 /// for use with OpenVDB library routines
172 /// @sa openvdb/util/NullInterrupter.h
174 {
175 public:
176  explicit Interrupter(const char* title = nullptr):
177  mUTI{UTgetInterrupt()}, mRunning{false}, mTitle{title ? title : ""}
178  {}
179  ~Interrupter() { if (mRunning) this->end(); }
180 
181  Interrupter(const Interrupter&) = default;
182  Interrupter& operator=(const Interrupter&) = default;
183 
184  /// @brief Signal the start of an interruptible operation.
185  /// @param name an optional descriptive name for the operation
186  void start(const char* name = nullptr) {
187  if (!mRunning) { mRunning = true; mUTI->opStart(name ? name : mTitle.c_str()); }
188  }
189  /// Signal the end of an interruptible operation.
190  void end() { if (mRunning) { mUTI->opEnd(); mRunning = false; } }
191 
192  /// @brief Check if an interruptible operation should be aborted.
193  /// @param percent an optional (when >= 0) percentage indicating
194  /// the fraction of the operation that has been completed
195  bool wasInterrupted(int percent=-1) { return mUTI->opInterrupt(percent); }
196 
197 private:
198  UT_Interrupt* mUTI;
199  bool mRunning;
200  std::string mTitle;
201 };
202 
203 
204 ////////////////////////////////////////
205 
206 
207 // Utility methods
208 
209 /// @brief Store a VDB grid in a new VDB primitive and add the primitive
210 /// to a geometry detail.
211 /// @return the newly-created VDB primitive.
212 /// @param gdp the detail to which to add the primitive
213 /// @param grid the VDB grid to be added
214 /// @param name if non-null, set the new primitive's @c name attribute to this string
215 /// @note This operation clears the input grid's metadata.
217 GU_PrimVDB* createVdbPrimitive(GU_Detail& gdp, GridPtr grid, const char* name = nullptr);
218 
219 
220 /// @brief Replace an existing VDB primitive with a new primitive that contains
221 /// the given grid.
222 /// @return the newly-created VDB primitive.
223 /// @param gdp the detail to which to add the primitive
224 /// @param grid the VDB grid to be added
225 /// @param src replace this primitive with the newly-created primitive
226 /// @param copyAttrs if @c true, copy attributes and group membership from the @a src primitive
227 /// @param name if non-null, set the new primitive's @c name attribute to this string;
228 /// otherwise, if @a copyAttrs is @c true, copy the name from @a src
229 /// @note This operation clears the input grid's metadata.
231 GU_PrimVDB* replaceVdbPrimitive(GU_Detail& gdp, GridPtr grid, GEO_PrimVDB& src,
232  const bool copyAttrs = true, const char* name = nullptr);
233 
234 
235 /// @brief Return in @a corners the corners of the given grid's active voxel bounding box.
236 /// @return @c false if the grid has no active voxels.
238 bool evalGridBBox(GridCRef grid, UT_Vector3 corners[8], bool expandHalfVoxel = false);
239 
240 
241 /// Construct an index-space CoordBBox from a UT_BoundingBox.
243 openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox&, const openvdb::math::Transform&);
244 
245 
246 /// @{
247 /// @brief Start forwarding OpenVDB log messages to the Houdini error manager
248 /// for all operators of the given type.
249 /// @details Typically, log forwarding is enabled for specific operator types
250 /// during initialization of the openvdb_houdini library, and there's no need
251 /// for client code to call this function.
252 /// @details This function has no effect unless OpenVDB was built with
253 /// <A HREF="http://log4cplus.sourceforge.net/">log4cplus</A>.
254 /// @note OpenVDB messages are typically logged to the console as well.
255 /// This function has no effect on console logging.
256 /// @sa stopLogForwarding(), isLogForwarding()
258 void startLogForwarding(OP_OpTypeId);
259 
260 /// @brief Stop forwarding OpenVDB log messages to the Houdini error manager
261 /// for all operators of the given type.
262 /// @details Typically, log forwarding is enabled for specific operator types
263 /// during initialization of the openvdb_houdini library, and there's no need
264 /// for client code to disable it.
265 /// @details This function has no effect unless OpenVDB was built with
266 /// <A HREF="http://log4cplus.sourceforge.net/">log4cplus</A>.
267 /// @note OpenVDB messages are typically logged to the console as well.
268 /// This function has no effect on console logging.
269 /// @sa startLogForwarding(), isLogForwarding()
271 void stopLogForwarding(OP_OpTypeId);
272 
273 /// @brief Return @c true if OpenVDB messages logged by operators
274 /// of the given type are forwarded to the Houdini error manager.
275 /// @sa startLogForwarding(), stopLogForwarding()
277 bool isLogForwarding(OP_OpTypeId);
278 /// @}
279 
280 
281 ////////////////////////////////////////
282 
283 
284 // Grid type lists, for use with GEO_PrimVDB::apply(), GEOvdbApply(),
285 // or openvdb::GridBase::apply()
286 
293 
299 
303 
308 
311 
313 
314 using AllGridTypes = VolumeGridTypes::Append<PointGridTypes>;
315 
316 
317 /// @brief If the given primitive's grid resolves to one of the listed grid types,
318 /// invoke the functor @a op on the resolved grid.
319 /// @return @c true if the functor was invoked, @c false otherwise
320 template<typename GridTypeListT, typename OpT>
321 inline bool
322 GEOvdbApply(const GEO_PrimVDB& vdb, OpT& op)
323 {
324  if (auto gridPtr = vdb.getConstGridPtr()) {
325  return gridPtr->apply<GridTypeListT>(op);
326  }
327  return false;
328 }
329 
330 /// @brief If the given primitive's grid resolves to one of the listed grid types,
331 /// invoke the functor @a op on the resolved grid.
332 /// @return @c true if the functor was invoked, @c false otherwise
333 /// @details If @a makeUnique is true, deep copy the grid's tree before
334 /// invoking the functor if the tree is shared with other grids.
335 template<typename GridTypeListT, typename OpT>
336 inline bool
337 GEOvdbApply(GEO_PrimVDB& vdb, OpT& op, bool makeUnique = true)
338 {
339  if (vdb.hasGrid()) {
340  auto gridPtr = vdb.getGridPtr();
341  if (makeUnique) {
342  auto treePtr = gridPtr->baseTreePtr();
343  if (treePtr.use_count() > 2) { // grid + treePtr = 2
344  // If the grid resolves to one of the listed types and its tree
345  // is shared with other grids, replace the tree with a deep copy.
346  gridPtr->apply<GridTypeListT>(
347  [](Grid& baseGrid) { baseGrid.setTree(baseGrid.constBaseTree().copy()); });
348  }
349  }
350  return gridPtr->apply<GridTypeListT>(op);
351  }
352  return false;
353 }
354 
355 } // namespace openvdb_houdini
356 
357 #endif // OPENVDB_HOUDINI_UTILS_HAS_BEEN_INCLUDED
#define OPENVDB_HOUDINI_API
Definition: Platform.h:248
Abstract base class for typed grids.
Definition: Grid.h:78
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:81
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
Wrapper class that adapts a Houdini UT_Interrupt object for use with OpenVDB library routines.
Definition: Utils.h:174
Interrupter(const char *title=nullptr)
Definition: Utils.h:176
bool wasInterrupted(int percent=-1)
Check if an interruptible operation should be aborted.
Definition: Utils.h:195
void end()
Signal the end of an interruptible operation.
Definition: Utils.h:190
Interrupter & operator=(const Interrupter &)=default
~Interrupter()
Definition: Utils.h:179
Interrupter(const Interrupter &)=default
void start(const char *name=nullptr)
Signal the start of an interruptible operation.
Definition: Utils.h:186
Iterator over const VDB primitives on a geometry detail.
Definition: Utils.h:47
std::function< bool(const GU_PrimVDB &)> FilterFunc
Definition: Utils.h:49
UT_SharedPtr< GA_GBPrimitiveIterator > mIter
Definition: Utils.h:110
GA_Index getIndex() const
Definition: Utils.h:81
const GU_PrimVDB * operator->() const
Definition: Utils.h:76
VdbPrimCIterator & operator=(const VdbPrimCIterator &)
const GU_PrimVDB * operator*() const
Definition: Utils.h:75
VdbPrimCIterator(const GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
FilterFunc mFilter
Definition: Utils.h:111
const GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
void advance()
Advance to the next VDB primitive.
VdbPrimCIterator & operator++()
Definition: Utils.h:69
VdbPrimCIterator(const GEO_Detail *, GA_Range::safedeletions, const GA_PrimitiveGroup *=nullptr, FilterFunc=FilterFunc())
Allow primitives to be deleted during iteration.
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:80
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:122
VdbPrimIterator(const VdbPrimIterator &)
GU_PrimVDB * getPrimitive() const
Return a pointer to the current VDB primitive (nullptr if at end).
Definition: Utils.h:158
VdbPrimIterator & operator++()
Advance to the next VDB primitive.
Definition: Utils.h:154
VdbPrimIterator & operator=(const VdbPrimIterator &)
GU_PrimVDB * operator*() const
Definition: Utils.h:161
VdbPrimIterator(GEO_Detail *gdp, const GA_PrimitiveGroup *group=nullptr, FilterFunc filter=FilterFunc())
Definition: Utils.h:133
GU_PrimVDB * operator->() const
Definition: Utils.h:162
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:146
Grid< PointDataTree > PointDataGrid
Point data grid.
Definition: PointDataGrid.h:194
Grid< FloatTree > FloatGrid
Definition: openvdb.h:45
Grid< Vec3DTree > Vec3DGrid
Definition: openvdb.h:50
Grid< BoolTree > BoolGrid
Common grid types.
Definition: openvdb.h:43
Grid< Vec3STree > Vec3SGrid
Definition: openvdb.h:52
Grid< Int32Tree > Int32Grid
Definition: openvdb.h:46
Grid< DoubleTree > DoubleGrid
Definition: openvdb.h:44
Definition: AttributeTransferUtil.h:33
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:322
OPENVDB_HOUDINI_API openvdb::CoordBBox makeCoordBBox(const UT_BoundingBox &, const openvdb::math::Transform &)
Construct an index-space CoordBBox from a UT_BoundingBox.
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:34
VolumeGridTypes::Append< PointGridTypes > AllGridTypes
Definition: Utils.h:314
OPENVDB_HOUDINI_API void stopLogForwarding(OP_OpTypeId)
Stop forwarding OpenVDB log messages to the Houdini error manager for all operators of the given type...
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.
ScalarGridTypes::Append< Vec3GridTypes > VolumeGridTypes
Definition: Utils.h:312
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_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.
openvdb::GridBase::ConstPtr GridCPtr
Definition: Utils.h:35
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.
A list of types (not necessarily unique)
Definition: TypeList.h:366
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition: TypeList.h:440