HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_VDBPointTools.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 GU_VDBPointTools.h
5 /// @author FX R&D OpenVDB team
6 ///
7 /// @brief Collection of PointIndexGrid helpers for Houdini
8 
9 #ifndef __GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED__
10 #define __GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED__
11 
12 #if 1
13  #include "GU_Detail.h"
14  #include "GU_DetailHandle.h"
15  #include "GU_PackedContext.h"
16  #include "GU_PackedFragment.h"
17  #include "GU_PackedGeometry.h"
18  #include "GU_PrimPacked.h"
19 #else
20  #include <GU/GU_Detail.h>
21  #include <GU/GU_DetailHandle.h>
22  #include <GU/GU_PackedContext.h>
23  #include <GU/GU_PackedFragment.h>
24  #include <GU/GU_PackedGeometry.h>
25  #include <GU/GU_PrimPacked.h>
26 #endif
27 #include <GA/GA_ElementGroup.h>
28 #include <UT/UT_SharedPtr.h>
29 #include <UT/UT_VectorTypes.h>
30 
31 #include <openvdb/Platform.h>
35 
36 #include <vector>
37 
38 
39 /// @brief Houdini point attribute wrapper
40 template<typename VectorType>
42 {
45 
46  using PosType = VectorType;
47  using ScalarType = typename PosType::value_type;
48 
49  GU_VDBPointList(const GU_Detail& detail, const GA_PointGroup* group = nullptr)
50  : mPositionHandle(detail.getP())
51  , mVelocityHandle()
52  , mRadiusHandle()
53  , mIndexMap(&detail.getP()->getIndexMap())
54  , mOffsets()
55  , mSize(mIndexMap->indexSize())
56  {
57  if (group) {
58  mSize = group->entries();
59  mOffsets.reserve(mSize);
60 
62  GA_Range range(*group);
63  for (GA_Iterator it = range.begin(); it.blockAdvance(start, end); ) {
64  for (GA_Offset off = start; off < end; ++off) {
65  mOffsets.push_back(off);
66  }
67  }
68 
69  getOffset = &GU_VDBPointList::offsetFromGroupMap;
70  } else if (mIndexMap->isTrivialMap()) {
71  getOffset = &GU_VDBPointList::offsetFromIndexCast;
72  } else {
73  getOffset = &GU_VDBPointList::offsetFromGeoMap;
74  }
75 
76  // Bind optional attributes
77 
79  if (velRef.isValid()) {
80  mVelocityHandle.bind(velRef.getAttribute());
81  }
82 
84  if (radRef.isValid()) {
85  mRadiusHandle.bind(radRef.getAttribute());
86  }
87  }
88 
89  static Ptr create(const GU_Detail& detail, const GA_PointGroup* group = nullptr)
90  {
91  return Ptr(new GU_VDBPointList(detail, group));
92  }
93 
94  size_t size() const { return mSize; }
95 
96  bool hasVelocity() const { return mVelocityHandle.isValid(); }
97  bool hasRadius() const { return mRadiusHandle.isValid(); }
98 
99  // Index access methods
100 
101  void getPos(size_t n, PosType& xyz) const {
102  getPosFromOffset((this->*getOffset)(n), xyz);
103  }
104 
105  void getVelocity(size_t n, PosType& v) const {
106  getVelocityFromOffset((this->*getOffset)(n), v);
107  }
108 
109  void getRadius(size_t n, ScalarType& r) const {
110  getRadiusFromOffset((this->*getOffset)(n), r);
111  }
112 
113  // Offset access methods
114 
115  GA_Offset offsetFromIndex(size_t n) const {
116  return (this->*getOffset)(n);
117  }
118 
119  void getPosFromOffset(const GA_Offset offset, PosType& xyz) const {
120  const UT_Vector3 data = mPositionHandle.get(offset);
121  xyz[0] = ScalarType(data[0]);
122  xyz[1] = ScalarType(data[1]);
123  xyz[2] = ScalarType(data[2]);
124  }
125 
127  const UT_Vector3 data = mVelocityHandle.get(offset);
128  v[0] = ScalarType(data[0]);
129  v[1] = ScalarType(data[1]);
130  v[2] = ScalarType(data[2]);
131  }
132 
134  r = ScalarType(mRadiusHandle.get(offset));
135  }
136 
137 private:
138  // Disallow copying
140  GU_VDBPointList& operator=(const GU_VDBPointList&);
141 
142  GA_Offset (GU_VDBPointList::* getOffset)(const size_t) const;
143 
144  GA_Offset offsetFromGeoMap(const size_t n) const {
145  return mIndexMap->offsetFromIndex(GA_Index(n));
146  }
147 
148  GA_Offset offsetFromGroupMap(const size_t n) const {
149  return mOffsets[n];
150  }
151 
152  GA_Offset offsetFromIndexCast(const size_t n) const {
153  return GA_Offset(n);
154  }
155 
156  GA_ROHandleV3 mPositionHandle, mVelocityHandle;
157  GA_ROHandleF mRadiusHandle;
158  GA_IndexMap const * const mIndexMap;
159  std::vector<GA_Offset> mOffsets;
160  size_t mSize;
161 }; // GU_VDBPointList
162 
163 
164 ////////////////////////////////////////
165 
166 
167 // PointIndexGrid utility methods
168 
169 
170 namespace GU_VDBPointToolsInternal {
171 
172 template<typename PointArrayType>
174  IndexToOffsetOp(const PointArrayType& points): mPointList(&points) {}
175 
176  template <typename LeafT>
177  void operator()(LeafT &leaf, size_t /*leafIndex*/) const {
178  typename LeafT::IndexArray& indices = leaf.indices();
179  for (size_t n = 0, N = indices.size(); n < N; ++n) {
180  indices[n] = static_cast<typename LeafT::ValueType::IntType>(
181  mPointList->offsetFromIndex(GA_Index{indices[n]}));
182  }
183  }
184  PointArrayType const * const mPointList;
185 };
186 
187 
189 {
190  PackedMaskConstructor(const std::vector<const GA_Primitive*>& prims,
191  const openvdb::math::Transform& xform)
192  : mPrims(prims.empty() ? nullptr : &prims.front())
193  , mXForm(xform)
194  , mMaskGrid(new openvdb::MaskGrid(false))
195  {
196  mMaskGrid->setTransform(mXForm.copy());
197  }
198 
200  : mPrims(rhs.mPrims)
201  , mXForm(rhs.mXForm)
202  , mMaskGrid(new openvdb::MaskGrid(false))
203  {
204  mMaskGrid->setTransform(mXForm.copy());
205  }
206 
207  openvdb::MaskGrid::Ptr getMaskGrid() { return mMaskGrid; }
208 
209  void join(PackedMaskConstructor& rhs) { mMaskGrid->tree().topologyUnion(rhs.mMaskGrid->tree()); }
210 
211  void operator()(const tbb::blocked_range<size_t>& range)
212  {
213  GU_PackedContext packedcontext;
214 
215  for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
216  const GA_Primitive *prim = mPrims[n];
217  if (!prim || !GU_PrimPacked::isPackedPrimitive(*prim)) continue;
218 
219  const GU_PrimPacked * pprim = static_cast<const GU_PrimPacked*>(prim);
220 
221  GU_Detail tmpdetail;
222  const GU_Detail *detailtouse;
223 
224  GU_DetailHandleAutoReadLock readlock(pprim->getPackedDetail(packedcontext));
225 
226  UT_Matrix4D mat;
227  pprim->getFullTransform4(mat);
228  if (mat.isIdentity() && readlock.isValid() && readlock.getGdp()) {
229  detailtouse = readlock.getGdp();
230  } else {
231  pprim->unpackWithContext(tmpdetail, packedcontext);
232  detailtouse = &tmpdetail;
233  }
234 
236  openvdb::MaskGrid::Ptr grid = openvdb::tools::createPointMask(points, mXForm);
237  mMaskGrid->tree().topologyUnion(grid->tree());
238  }
239  }
240 
241 private:
242  GA_Primitive const * const * const mPrims;
243  openvdb::math::Transform mXForm;
244  openvdb::MaskGrid::Ptr mMaskGrid;
245 }; // struct PackedMaskConstructor
246 
247 
248 inline void
249 getPackedPrimitiveOffsets(const GU_Detail& detail, std::vector<const GA_Primitive*>& primitives)
250 {
251  const GA_Size numPacked = GU_PrimPacked::countPackedPrimitives(detail);
252 
253  primitives.clear();
254  primitives.reserve(size_t(numPacked));
255 
256  if (numPacked != GA_Size(0)) {
258  GA_Range range = detail.getPrimitiveRange();
259  const GA_PrimitiveList& primList = detail.getPrimitiveList();
260 
261  for (GA_Iterator it = range.begin(); it.blockAdvance(start, end); ) {
262  for (GA_Offset off = start; off < end; ++off) {
263 
264  const GA_Primitive *prim = primList.get(off);
265 
266  if (prim && GU_PrimPacked::isPackedPrimitive(*prim)) {
267  primitives.push_back(prim);
268  }
269  }
270  }
271  }
272 }
273 
274 } // namespace GU_VDBPointToolsInternal
275 
276 
277 ////////////////////////////////////////
278 
279 
280 /// @brief Utility method to construct a GU_VDBPointList.
281 /// @details The GU_VDBPointList is compatible with the PointIndexGrid and ParticleAtals structures.
283 GUvdbCreatePointList(const GU_Detail& detail, const GA_PointGroup* pointGroup = nullptr)
284 {
285  return GU_VDBPointList<openvdb::Vec3s>::create(detail, pointGroup);
286 }
287 
288 
289 /// @brief Utility method to change point indices into Houdini geometry offsets.
290 /// @note PointIndexGrid's that store Houdini geometry offsets are not
291 /// safe to write to disk, offsets are not guaranteed to be immutable
292 /// under defragmentation operations or I/O.
293 template<typename PointIndexTreeType, typename PointArrayType>
294 inline void
295 GUvdbConvertIndexToOffset(PointIndexTreeType& tree, const PointArrayType& points)
296 {
297  openvdb::tree::LeafManager<PointIndexTreeType> leafnodes(tree);
299 }
300 
301 
302 /// @brief Utility method to construct a PointIndexGrid.
303 /// @details The PointIndexGrid supports fast spatial queries for points.
304 inline openvdb::tools::PointIndexGrid::Ptr
306  const openvdb::math::Transform& xform,
307  const GU_Detail& detail,
308  const GA_PointGroup* pointGroup = nullptr)
309 {
310  GU_VDBPointList<openvdb::Vec3s> points(detail, pointGroup);
311  return openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
312 }
313 
314 
315 /// @brief Utility method to construct a PointIndexGrid.
316 /// @details The PointIndexGrid supports fast spatial queries for points.
317 template<typename PointArrayType>
318 inline openvdb::tools::PointIndexGrid::Ptr
319 GUvdbCreatePointIndexGrid(const openvdb::math::Transform& xform, const PointArrayType& points)
320 {
321  return openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
322 }
323 
324 
325 /// @brief Utility method to construct a ParticleAtals.
326 /// @details The ParticleAtals supports fast spatial queries for particles.
327 template<typename ParticleArrayType>
328 inline openvdb::tools::ParticleIndexAtlas::Ptr
329 GUvdbCreateParticleAtlas(const double minVoxelSize, const ParticleArrayType& particles)
330 {
332  ParticleIndexAtlas::Ptr atlas(new ParticleIndexAtlas());
333 
334  if (particles.hasRadius()) {
335  atlas->construct(particles, minVoxelSize);
336  }
337 
338  return atlas;
339 }
340 
341 
342 /// @brief Utility method to construct a boolean PointMaskGrid
343 /// @details This method supports packed points.
344 inline openvdb::MaskGrid::Ptr
346  const openvdb::math::Transform& xform,
347  const GU_Detail& detail,
348  const GA_PointGroup* pointGroup = nullptr)
349 {
350  std::vector<const GA_Primitive*> packed;
352 
353  if (!packed.empty()) {
355  tbb::parallel_reduce(tbb::blocked_range<size_t>(0, packed.size()), op);
356  return op.getMaskGrid();
357  }
358 
359  GU_VDBPointList<openvdb::Vec3R> points(detail, pointGroup);
360  return openvdb::tools::createPointMask(points, xform);
361 }
362 
363 
364 /// @brief Utility method to construct a PointIndexGrid that stores
365 /// Houdini geometry offsets.
366 ///
367 /// @note PointIndexGrid's that store Houdini geometry offsets are not
368 /// safe to write to disk, offsets are not guaranteed to be immutable
369 /// under defragmentation operations or I/O.
370 inline openvdb::tools::PointIndexGrid::Ptr
372  const openvdb::math::Transform& xform,
373  const GU_Detail& detail,
374  const GA_PointGroup* pointGroup = nullptr)
375 {
376  GU_VDBPointList<openvdb::Vec3s> points(detail, pointGroup);
377 
378  openvdb::tools::PointIndexGrid::Ptr grid =
379  openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
380 
381  GUvdbConvertIndexToOffset(grid->tree(), points);
382 
383  return grid;
384 }
385 
386 
387 #endif // GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED
A class to manage an ordered array which has fixed offset handles.
Definition: GA_IndexMap.h:63
static GA_Size countPackedPrimitives(const GA_Detail &gdp)
Convenience method to return the number of packed primitives.
Space-partitioning acceleration structure for particles, points with radius. Partitions particle indi...
PackedMaskConstructor(const std::vector< const GA_Primitive * > &prims, const openvdb::math::Transform &xform)
This tool produces a grid where every voxel that contains a point is active. It employs thread-local ...
ParticleAtlas< PointIndexGrid > ParticleIndexAtlas
void operator()(const tbb::blocked_range< size_t > &range)
GLsizei GLenum const void * indices
Definition: glcorearb.h:406
PointArrayType const *const mPointList
GLenum GLint * range
Definition: glcorearb.h:1925
GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glad.h:2676
Iteration over a range of elements.
Definition: GA_Iterator.h:29
void getRadiusFromOffset(const GA_Offset offset, ScalarType &r) const
void getVelocity(size_t n, PosType &v) const
const GLdouble * v
Definition: glcorearb.h:837
void getFullTransform4(UT_Matrix4D &xform) const override
bool blockAdvance(GA_Offset &start, GA_Offset &end)
GLuint start
Definition: glcorearb.h:475
GA_Offset offsetFromIndex(size_t n) const
void getRadius(size_t n, ScalarType &r) const
openvdb::MaskGrid::Ptr GUvdbCreatePointMaskGrid(const openvdb::math::Transform &xform, const GU_Detail &detail, const GA_PointGroup *pointGroup=nullptr)
Utility method to construct a boolean PointMaskGrid.
void operator()(LeafT &leaf, size_t) const
UT_SharedPtr< const GU_VDBPointList > ConstPtr
uint64 value_type
Definition: GA_PrimCompat.h:29
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:235
void getPosFromOffset(const GA_Offset offset, PosType &xyz) const
openvdb::tools::PointIndexGrid::Ptr GUvdbCreatePointIndexGrid(const openvdb::math::Transform &xform, const GU_Detail &detail, const GA_PointGroup *pointGroup=nullptr)
Utility method to construct a PointIndexGrid.
bool isValid() const
Test to see if the attribute reference refers to a valid attribute.
A range of elements in an index-map.
Definition: GA_Range.h:42
#define GEO_STD_ATTRIB_VELOCITY
Definition: GEO_Detail.h:96
GA_Size GA_Offset
Definition: GA_Types.h:641
SYS_FORCE_INLINE const_iterator end() const
UT_SharedPtr< GU_VDBPointList > Ptr
GLdouble n
Definition: glcorearb.h:2008
GLintptr offset
Definition: glcorearb.h:665
bool hasVelocity() const
VectorType PosType
void bind(const GA_Detail *gdp, GA_AttributeOwner owner, const UT_StringRef &name, int minsize=1)
GA_Iterator begin() const
MaskGrid::Ptr createPointMask(const PointListT &points, const math::Transform &xform)
Return a MaskGrid where each binary voxel value is on if the voxel contains one (or more) points (i...
Definition: PointsToMask.h:94
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
This class provides a way to manage a reference to an attribute permitting Read-Only access...
Grid< MaskTree > MaskGrid
Definition: openvdb.h:78
GLuint GLuint end
Definition: glcorearb.h:475
void getPackedPrimitiveOffsets(const GU_Detail &detail, std::vector< const GA_Primitive * > &primitives)
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:203
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR_14 uint8_t packed(VULKAN_HPP_NAMESPACE::Format format)
bool unpackWithContext(GU_Detail &dest, GU_PackedContext &context) const
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:635
void GUvdbConvertIndexToOffset(PointIndexTreeType &tree, const PointArrayType &points)
Utility method to change point indices into Houdini geometry offsets.
A list of primitives.
PackedMaskConstructor(PackedMaskConstructor &rhs, tbb::split)
SYS_FORCE_INLINE bool isValid() const
Definition: GA_Handle.h:187
void getPos(size_t n, PosType &xyz) const
SYS_FORCE_INLINE bool isTrivialMap() const
Definition: GA_IndexMap.h:290
const GA_Attribute * findFloatTuple(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
SYS_FORCE_INLINE const GA_Primitive * get(GA_Offset off) const
Houdini point attribute wrapper.
openvdb::tools::ParticleIndexAtlas::Ptr GUvdbCreateParticleAtlas(const double minVoxelSize, const ParticleArrayType &particles)
Utility method to construct a ParticleAtals.
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
openvdb::tools::PointIndexGrid::Ptr GUvdbCreatePointOffsetGrid(const openvdb::math::Transform &xform, const GU_Detail &detail, const GA_PointGroup *pointGroup=nullptr)
Utility method to construct a PointIndexGrid that stores Houdini geometry offsets.
SYS_FORCE_INLINE GA_Offset offsetFromIndex(GA_Index ordered_index) const
Definition: GA_IndexMap.h:117
void getVelocityFromOffset(const GA_Offset offset, PosType &v) const
GA_API const UT_StringHolder N
const GA_PrimitiveList & getPrimitiveList() const
Definition: GA_Detail.h:792
size_t size() const
GU_ConstDetailHandle getPackedDetail() const
#define GEO_STD_ATTRIB_PSCALE
Definition: GEO_Detail.h:116
GU_VDBPointList< openvdb::Vec3s >::Ptr GUvdbCreatePointList(const GU_Detail &detail, const GA_PointGroup *pointGroup=nullptr)
Utility method to construct a GU_VDBPointList.
static Ptr create(const GU_Detail &detail, const GA_PointGroup *group=nullptr)
GU_VDBPointList(const GU_Detail &detail, const GA_PointGroup *group=nullptr)
typename PosType::value_type ScalarType
GLboolean r
Definition: glcorearb.h:1222
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
GA_Range getPrimitiveRange(const GA_PrimitiveGroup *group=0) const
Get a range of all primitives in the detail.
Definition: GA_Detail.h:1733
Definition: format.h:895
static bool isPackedPrimitive(const GA_PrimitiveDefinition &pdef)
IndexToOffsetOp(const PointArrayType &points)
bool hasRadius() const
const GA_Attribute * getAttribute() const