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 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 //
31 /// @file GU_VDBPointTools.h
32 /// @author FX R&D OpenVDB team
33 ///
34 /// @brief Collection of PointIndexGrid helpers for Houdini
35 
36 #ifndef __GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED__
37 #define __GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED__
38 
39 #if 1
40  #include "GU_Detail.h"
41  #include "GU_DetailHandle.h"
42  #include "GU_PackedContext.h"
43  #include "GU_PackedFragment.h"
44  #include "GU_PackedGeometry.h"
45  #include "GU_PrimPacked.h"
46 #else
47  #include <GU/GU_Detail.h>
48  #include <GU/GU_DetailHandle.h>
49  #include <GU/GU_PackedContext.h>
50  #include <GU/GU_PackedFragment.h>
51  #include <GU/GU_PackedGeometry.h>
52  #include <GU/GU_PrimPacked.h>
53 #endif
54 #include <GA/GA_ElementGroup.h>
55 #include <UT/UT_SharedPtr.h>
56 #include <UT/UT_VectorTypes.h>
57 #include <UT/UT_Version.h>
58 
59 #include <openvdb/Platform.h>
63 
64 #include <vector>
65 
66 
67 /// @brief Houdini point attribute wrapper
68 template<typename VectorType>
70 {
73 
74  using PosType = VectorType;
75  using ScalarType = typename PosType::value_type;
76 
77  GU_VDBPointList(const GU_Detail& detail, const GA_PointGroup* group = nullptr)
78  : mPositionHandle(detail.getP())
79  , mVelocityHandle()
80  , mRadiusHandle()
81  , mIndexMap(&detail.getP()->getIndexMap())
82  , mOffsets()
83  , mSize(mIndexMap->indexSize())
84  {
85  if (group) {
86  mSize = group->entries();
87  mOffsets.reserve(mSize);
88 
90  GA_Range range(*group);
91  for (GA_Iterator it = range.begin(); it.blockAdvance(start, end); ) {
92  for (GA_Offset off = start; off < end; ++off) {
93  mOffsets.push_back(off);
94  }
95  }
96 
97  getOffset = &GU_VDBPointList::offsetFromGroupMap;
98  } else if (mIndexMap->isTrivialMap()) {
99  getOffset = &GU_VDBPointList::offsetFromIndexCast;
100  } else {
101  getOffset = &GU_VDBPointList::offsetFromGeoMap;
102  }
103 
104  // Bind optional attributes
105 
107  if (velRef.isValid()) {
108  mVelocityHandle.bind(velRef.getAttribute());
109  }
110 
112  if (radRef.isValid()) {
113  mRadiusHandle.bind(radRef.getAttribute());
114  }
115  }
116 
117  static Ptr create(const GU_Detail& detail, const GA_PointGroup* group = nullptr)
118  {
119  return Ptr(new GU_VDBPointList(detail, group));
120  }
121 
122  size_t size() const { return mSize; }
123 
124  bool hasVelocity() const { return mVelocityHandle.isValid(); }
125  bool hasRadius() const { return mRadiusHandle.isValid(); }
126 
127  // Index access methods
128 
129  void getPos(size_t n, PosType& xyz) const {
130  getPosFromOffset((this->*getOffset)(n), xyz);
131  }
132 
133  void getVelocity(size_t n, PosType& v) const {
134  getVelocityFromOffset((this->*getOffset)(n), v);
135  }
136 
137  void getRadius(size_t n, ScalarType& r) const {
138  getRadiusFromOffset((this->*getOffset)(n), r);
139  }
140 
141  // Offset access methods
142 
143  GA_Offset offsetFromIndex(size_t n) const {
144  return (this->*getOffset)(n);
145  }
146 
147  void getPosFromOffset(const GA_Offset offset, PosType& xyz) const {
148  const UT_Vector3 data = mPositionHandle.get(offset);
149  xyz[0] = ScalarType(data[0]);
150  xyz[1] = ScalarType(data[1]);
151  xyz[2] = ScalarType(data[2]);
152  }
153 
155  const UT_Vector3 data = mVelocityHandle.get(offset);
156  v[0] = ScalarType(data[0]);
157  v[1] = ScalarType(data[1]);
158  v[2] = ScalarType(data[2]);
159  }
160 
162  r = ScalarType(mRadiusHandle.get(offset));
163  }
164 
165 private:
166  // Disallow copying
168  GU_VDBPointList& operator=(const GU_VDBPointList&);
169 
170  GA_Offset (GU_VDBPointList::* getOffset)(const size_t) const;
171 
172  GA_Offset offsetFromGeoMap(const size_t n) const {
173  return mIndexMap->offsetFromIndex(GA_Index(n));
174  }
175 
176  GA_Offset offsetFromGroupMap(const size_t n) const {
177  return mOffsets[n];
178  }
179 
180  GA_Offset offsetFromIndexCast(const size_t n) const {
181  return GA_Offset(n);
182  }
183 
184  GA_ROHandleV3 mPositionHandle, mVelocityHandle;
185  GA_ROHandleF mRadiusHandle;
186  GA_IndexMap const * const mIndexMap;
187  std::vector<GA_Offset> mOffsets;
188  size_t mSize;
189 }; // GU_VDBPointList
190 
191 
192 ////////////////////////////////////////
193 
194 
195 // PointIndexGrid utility methods
196 
197 
198 namespace GU_VDBPointToolsInternal {
199 
200 template<typename PointArrayType>
202  IndexToOffsetOp(const PointArrayType& points): mPointList(&points) {}
203 
204  template <typename LeafT>
205  void operator()(LeafT &leaf, size_t /*leafIndex*/) const {
206  typename LeafT::IndexArray& indices = leaf.indices();
207  for (size_t n = 0, N = indices.size(); n < N; ++n) {
208  indices[n] = static_cast<typename LeafT::ValueType::IntType>(
209  mPointList->offsetFromIndex(GA_Index{indices[n]}));
210  }
211  }
212  PointArrayType const * const mPointList;
213 };
214 
215 
217 {
218  PackedMaskConstructor(const std::vector<const GA_Primitive*>& prims,
219  const openvdb::math::Transform& xform)
220  : mPrims(prims.empty() ? nullptr : &prims.front())
221  , mXForm(xform)
222  , mMaskGrid(new openvdb::MaskGrid(false))
223  {
224  mMaskGrid->setTransform(mXForm.copy());
225  }
226 
228  : mPrims(rhs.mPrims)
229  , mXForm(rhs.mXForm)
230  , mMaskGrid(new openvdb::MaskGrid(false))
231  {
232  mMaskGrid->setTransform(mXForm.copy());
233  }
234 
235  openvdb::MaskGrid::Ptr getMaskGrid() { return mMaskGrid; }
236 
237  void join(PackedMaskConstructor& rhs) { mMaskGrid->tree().topologyUnion(rhs.mMaskGrid->tree()); }
238 
239  void operator()(const tbb::blocked_range<size_t>& range)
240  {
241  GU_PackedContext packedcontext;
242 
243  for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
244  const GA_Primitive *prim = mPrims[n];
245  if (!prim || !GU_PrimPacked::isPackedPrimitive(*prim)) continue;
246 
247  const GU_PrimPacked * pprim = static_cast<const GU_PrimPacked*>(prim);
248 
249  GU_Detail tmpdetail;
250  const GU_Detail *detailtouse;
251 
252  GU_DetailHandleAutoReadLock readlock(pprim->getPackedDetail(packedcontext));
253 
254  UT_Matrix4D mat;
255  pprim->getFullTransform4(mat);
256  if (mat.isIdentity() && readlock.isValid() && readlock.getGdp()) {
257  detailtouse = readlock.getGdp();
258  } else {
259  pprim->unpackWithContext(tmpdetail, packedcontext);
260  detailtouse = &tmpdetail;
261  }
262 
263  GU_VDBPointList<openvdb::Vec3R> points(*detailtouse);
264  openvdb::MaskGrid::Ptr grid = openvdb::tools::createPointMask(points, mXForm);
265  mMaskGrid->tree().topologyUnion(grid->tree());
266  }
267  }
268 
269 private:
270  GA_Primitive const * const * const mPrims;
271  openvdb::math::Transform mXForm;
272  openvdb::MaskGrid::Ptr mMaskGrid;
273 }; // struct PackedMaskConstructor
274 
275 
276 inline void
277 getPackedPrimitiveOffsets(const GU_Detail& detail, std::vector<const GA_Primitive*>& primitives)
278 {
279  const GA_Size numPacked = GU_PrimPacked::countPackedPrimitives(detail);
280 
281  primitives.clear();
282  primitives.reserve(size_t(numPacked));
283 
284  if (numPacked != GA_Size(0)) {
286  GA_Range range = detail.getPrimitiveRange();
287  const GA_PrimitiveList& primList = detail.getPrimitiveList();
288 
289  for (GA_Iterator it = range.begin(); it.blockAdvance(start, end); ) {
290  for (GA_Offset off = start; off < end; ++off) {
291 
292  const GA_Primitive *prim = primList.get(off);
293 
294  if (prim && GU_PrimPacked::isPackedPrimitive(*prim)) {
295  primitives.push_back(prim);
296  }
297  }
298  }
299  }
300 }
301 
302 } // namespace GU_VDBPointToolsInternal
303 
304 
305 ////////////////////////////////////////
306 
307 
308 /// @brief Utility method to construct a GU_VDBPointList.
309 /// @details The GU_VDBPointList is compatible with the PointIndexGrid and ParticleAtals structures.
311 GUvdbCreatePointList(const GU_Detail& detail, const GA_PointGroup* pointGroup = nullptr)
312 {
313  return GU_VDBPointList<openvdb::Vec3s>::create(detail, pointGroup);
314 }
315 
316 
317 /// @brief Utility method to change point indices into Houdini geometry offsets.
318 /// @note PointIndexGrid's that store Houdini geometry offsets are not
319 /// safe to write to disk, offsets are not guaranteed to be immutable
320 /// under defragmentation operations or I/O.
321 template<typename PointIndexTreeType, typename PointArrayType>
322 inline void
323 GUvdbConvertIndexToOffset(PointIndexTreeType& tree, const PointArrayType& points)
324 {
325  openvdb::tree::LeafManager<PointIndexTreeType> leafnodes(tree);
327 }
328 
329 
330 /// @brief Utility method to construct a PointIndexGrid.
331 /// @details The PointIndexGrid supports fast spatial queries for points.
332 inline openvdb::tools::PointIndexGrid::Ptr
334  const openvdb::math::Transform& xform,
335  const GU_Detail& detail,
336  const GA_PointGroup* pointGroup = nullptr)
337 {
338  GU_VDBPointList<openvdb::Vec3s> points(detail, pointGroup);
339  return openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
340 }
341 
342 
343 /// @brief Utility method to construct a PointIndexGrid.
344 /// @details The PointIndexGrid supports fast spatial queries for points.
345 template<typename PointArrayType>
346 inline openvdb::tools::PointIndexGrid::Ptr
347 GUvdbCreatePointIndexGrid(const openvdb::math::Transform& xform, const PointArrayType& points)
348 {
349  return openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
350 }
351 
352 
353 /// @brief Utility method to construct a ParticleAtals.
354 /// @details The ParticleAtals supports fast spatial queries for particles.
355 template<typename ParticleArrayType>
356 inline openvdb::tools::ParticleIndexAtlas::Ptr
357 GUvdbCreateParticleAtlas(const double minVoxelSize, const ParticleArrayType& particles)
358 {
360  ParticleIndexAtlas::Ptr atlas(new ParticleIndexAtlas());
361 
362  if (particles.hasRadius()) {
363  atlas->construct(particles, minVoxelSize);
364  }
365 
366  return atlas;
367 }
368 
369 
370 /// @brief Utility method to construct a boolean PointMaskGrid
371 /// @details This method supports packed points.
372 inline openvdb::MaskGrid::Ptr
374  const openvdb::math::Transform& xform,
375  const GU_Detail& detail,
376  const GA_PointGroup* pointGroup = nullptr)
377 {
378  std::vector<const GA_Primitive*> packed;
380 
381  if (!packed.empty()) {
383  tbb::parallel_reduce(tbb::blocked_range<size_t>(0, packed.size()), op);
384  return op.getMaskGrid();
385  }
386 
387  GU_VDBPointList<openvdb::Vec3R> points(detail, pointGroup);
388  return openvdb::tools::createPointMask(points, xform);
389 }
390 
391 
392 /// @brief Utility method to construct a PointIndexGrid that stores
393 /// Houdini geometry offsets.
394 ///
395 /// @note PointIndexGrid's that store Houdini geometry offsets are not
396 /// safe to write to disk, offsets are not guaranteed to be immutable
397 /// under defragmentation operations or I/O.
398 inline openvdb::tools::PointIndexGrid::Ptr
400  const openvdb::math::Transform& xform,
401  const GU_Detail& detail,
402  const GA_PointGroup* pointGroup = nullptr)
403 {
404  GU_VDBPointList<openvdb::Vec3s> points(detail, pointGroup);
405 
406  openvdb::tools::PointIndexGrid::Ptr grid =
407  openvdb::tools::createPointIndexGrid<openvdb::tools::PointIndexGrid>(points, xform);
408 
409  GUvdbConvertIndexToOffset(grid->tree(), points);
410 
411  return grid;
412 }
413 
414 
415 #endif // GU_VDBPOINTTOOLS_H_HAS_BEEN_INCLUDED
416 
417 // Copyright (c) 2012-2018 DreamWorks Animation LLC
418 // All rights reserved. This software is distributed under the
419 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
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 employes thread-local...
ParticleAtlas< PointIndexGrid > ParticleIndexAtlas
void operator()(const tbb::blocked_range< size_t > &range)
GLsizei GLenum const void * indices
Definition: glcorearb.h:405
PointArrayType const *const mPointList
GLenum GLint * range
Definition: glcorearb.h:1924
Iteration over a range of elements.
Definition: GA_Iterator.h:28
void getRadiusFromOffset(const GA_Offset offset, ScalarType &r) const
void getVelocity(size_t n, PosType &v) const
const GLdouble * v
Definition: glcorearb.h:836
bool blockAdvance(GA_Offset &start, GA_Offset &end)
GLuint start
Definition: glcorearb.h:474
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:211
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:83
GA_Size GA_Offset
Definition: GA_Types.h:617
SYS_FORCE_INLINE const_iterator end() const
UT_SharedPtr< GU_VDBPointList > Ptr
GLdouble n
Definition: glcorearb.h:2007
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:117
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:28
This class provides a way to manage a reference to an attribute permitting Read-Only access...
Grid< MaskTree > MaskGrid
Definition: openvdb.h:75
GLuint GLuint end
Definition: glcorearb.h:474
void getPackedPrimitiveOffsets(const GU_Detail &detail, std::vector< const GA_Primitive * > &primitives)
GLintptr offset
Definition: glcorearb.h:664
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:191
GLboolean * data
Definition: glcorearb.h:130
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:611
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:182
void getPos(size_t n, PosType &xyz) const
SYS_FORCE_INLINE bool isTrivialMap() const
Definition: GA_IndexMap.h:288
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:728
size_t size() const
GU_ConstDetailHandle getPackedDetail() const
#define GEO_STD_ATTRIB_PSCALE
Definition: GEO_Detail.h:103
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:1221
GA_Range getPrimitiveRange(const GA_PrimitiveGroup *group=0) const
Get a range of all primitives in the detail.
Definition: GA_Detail.h:1632
virtual void getFullTransform4(UT_Matrix4D &xform) const
static bool isPackedPrimitive(const GA_PrimitiveDefinition &pdef)
IndexToOffsetOp(const PointArrayType &points)
bool hasRadius() const
const GA_Attribute * getAttribute() const