HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointsToMask.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 /// @author Ken Museth
32 ///
33 /// @file tools/PointsToMask.h
34 ///
35 /// @brief This tool produces a grid where every voxel that contains a
36 /// point is active. It employes thread-local storage for best performance.
37 ///
38 /// The @c PointListT template argument below refers to any class
39 /// with the following interface (see unittest/TestPointsToMask.cc
40 /// and SOP_OpenVDB_From_Particles.cc for practical examples):
41 /// @code
42 ///
43 /// class PointList {
44 /// ...
45 /// public:
46 ///
47 /// // Return the total number of particles in list.
48 /// size_t size() const;
49 ///
50 /// // Get the world space position of the nth particle.
51 /// void getPos(size_t n, Vec3R& xyz) const;
52 /// };
53 /// @endcode
54 ///
55 /// @note See unittest/TestPointsToMask.cc for an example.
56 ///
57 /// The @c InterruptT template argument below refers to any class
58 /// with the following interface:
59 /// @code
60 /// class Interrupter {
61 /// ...
62 /// public:
63 /// void start(const char* name = nullptr) // called when computations begin
64 /// void end() // called when computations end
65 /// bool wasInterrupted(int percent = -1) // return true to break computation
66 /// };
67 /// @endcode
68 ///
69 /// @note If no template argument is provided for this InterruptT
70 /// the util::NullInterrupter is used which implies that all
71 /// interrupter calls are no-ops (i.e. incurs no computational overhead).
72 
73 #ifndef OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
74 #define OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
75 
76 #include <tbb/enumerable_thread_specific.h>
77 #include <tbb/parallel_for.h>
78 #include <tbb/parallel_reduce.h>
79 #include <tbb/blocked_range.h>
80 #include <openvdb/openvdb.h> // for MaskGrid
81 #include <openvdb/Grid.h>
82 #include <openvdb/Types.h>
84 #include <vector>
85 
86 
87 namespace openvdb {
89 namespace OPENVDB_VERSION_NAME {
90 namespace tools {
91 
92 // Forward declaration of main class
93 template<typename GridT = MaskGrid, typename InterrupterT = util::NullInterrupter>
95 
96 /// @brief Makes every voxel of the @c grid active if it contains a point.
97 ///
98 /// @param points points that active the voxels of @c grid
99 /// @param grid on out its voxels with points are active
100 template<typename PointListT, typename GridT>
101 inline void
102 maskPoints(const PointListT& points, GridT& grid)
103 {
105  tmp.addPoints(points);
106 }
107 
108 /// @brief Return a MaskGrid where each binary voxel value
109 /// is on if the voxel contains one (or more) points (i.e.
110 /// the 3D position of a point is closer to this voxel than
111 /// any other voxels).
112 ///
113 /// @param points points that active the voxels in the returned grid.
114 /// @param xform transform from world space to voxels in grid space.
115 template<typename PointListT>
116 inline MaskGrid::Ptr
117 createPointMask(const PointListT& points, const math::Transform& xform)
118 {
119  MaskGrid::Ptr grid = createGrid<MaskGrid>( false );
120  grid->setTransform( xform.copy() );
121  maskPoints( points, *grid );
122  return grid;
123 }
124 
125 ////////////////////////////////////////
126 
127 /// @brief Makes every voxel of a grid active if it contains a point.
128 template<typename GridT, typename InterrupterT>
129 class PointsToMask
130 {
131 public:
132  using ValueT = typename GridT::ValueType;
133 
134  /// @brief Constructor from a grid and optional interrupter
135  ///
136  /// @param grid Grid whoes voxels will have their state activated by points.
137  /// @param interrupter Optional interrupter to prematurely terminate execution.
138  explicit PointsToMask(GridT& grid, InterrupterT* interrupter = nullptr)
139  : mGrid(&grid)
140  , mInterrupter(interrupter)
141  {
142  }
143 
144  /// @brief Activates the state of any voxel in the input grid that contains a point.
145  ///
146  /// @param points List of points that active the voxels in the input grid.
147  /// @param grainSize Set the grain-size used for multi-threading. A value of 0
148  /// disables multi-threading!
149  template<typename PointListT>
150  void addPoints(const PointListT& points, size_t grainSize = 1024)
151  {
152  if (mInterrupter) mInterrupter->start("PointsToMask: adding points");
153  if (grainSize > 0) {
154 #if OPENVDB_ABI_VERSION_NUMBER <= 3
155  typename GridT::Ptr examplar = mGrid->copy(CP_NEW);
156 #else
157  typename GridT::Ptr examplar = mGrid->copyWithNewTree();
158 #endif
159  PoolType pool( *examplar );//thread local storage pool of grids
160  AddPoints<PointListT> tmp(points, pool, grainSize, *this );
161  if ( this->interrupt() ) return;
162  ReducePool reducePool(pool, mGrid, size_t(0));
163  } else {
164  const math::Transform& xform = mGrid->transform();
165  typename GridT::Accessor acc = mGrid->getAccessor();
166  Vec3R wPos;
167  for (size_t i = 0, n = points.size(); i < n; ++i) {
168  if ( this->interrupt() ) break;
169  points.getPos(i, wPos);
170  acc.setValueOn( xform.worldToIndexCellCentered( wPos ) );
171  }
172  }
173  if (mInterrupter) mInterrupter->end();
174  }
175 
176 private:
177  // Disallow copy construction and copy by assignment!
178  PointsToMask(const PointsToMask&);// not implemented
179  PointsToMask& operator=(const PointsToMask&);// not implemented
180 
181  bool interrupt() const
182  {
183  if (mInterrupter && util::wasInterrupted(mInterrupter)) {
184  tbb::task::self().cancel_group_execution();
185  return true;
186  }
187  return false;
188  }
189 
190  // Private struct that implements concurrent thread-local
191  // insersion of points into a grid
192  using PoolType = tbb::enumerable_thread_specific<GridT>;
193  template<typename PointListT> struct AddPoints;
194 
195  // Private class that implements concurrent reduction of a thread-local pool
196  struct ReducePool;
197 
198  GridT* mGrid;
199  InterrupterT* mInterrupter;
200 };// PointsToMask
201 
202 // Private member class that implements concurrent thread-local
203 // insersion of points into a grid
204 template<typename GridT, typename InterrupterT>
205 template<typename PointListT>
206 struct PointsToMask<GridT, InterrupterT>::AddPoints
207 {
208  AddPoints(const PointListT& points,
209  PoolType& pool,
210  size_t grainSize,
211  const PointsToMask& parent)
212  : mPoints(&points)
213  , mParent(&parent)
214  , mPool(&pool)
215  {
216  tbb::parallel_for(tbb::blocked_range<size_t>(0, mPoints->size(), grainSize), *this);
217  }
218  void operator()(const tbb::blocked_range<size_t>& range) const
219  {
220  if (mParent->interrupt()) return;
221  GridT& grid = mPool->local();
222  const math::Transform& xform = grid.transform();
223  typename GridT::Accessor acc = grid.getAccessor();
224  Vec3R wPos;
225  for (size_t i=range.begin(), n=range.end(); i!=n; ++i) {
226  mPoints->getPos(i, wPos);
227  acc.setValueOn( xform.worldToIndexCellCentered( wPos ) );
228  }
229  }
230  const PointListT* mPoints;
231  const PointsToMask* mParent;
232  PoolType* mPool;
233 
234 };// end of private member class AddPoints
235 
236 // Private member class that implements concurrent reduction of a thread-local pool
237 template<typename GridT, typename InterrupterT>
238 struct PointsToMask<GridT, InterrupterT>::ReducePool
239 {
240  using VecT = std::vector<GridT*>;
241  using IterT = typename VecT::iterator;
242  using RangeT = tbb::blocked_range<IterT>;
243 
244  ReducePool(PoolType& pool, GridT* grid, size_t grainSize = 1)
245  : mOwnsGrid(false)
246  , mGrid(grid)
247  {
248  if ( grainSize == 0 ) {
249  using IterT = typename PoolType::const_iterator;
250  for (IterT i=pool.begin(); i!=pool.end(); ++i) mGrid->topologyUnion( *i );
251  } else {
252  VecT grids( pool.size() );
253  typename PoolType::iterator i = pool.begin();
254  for (size_t j=0; j != pool.size(); ++i, ++j) grids[j] = &(*i);
255  tbb::parallel_reduce( RangeT( grids.begin(), grids.end(), grainSize ), *this );
256  }
257  }
258 
259  ReducePool(const ReducePool&, tbb::split)
260  : mOwnsGrid(true)
261  , mGrid(new GridT())
262  {
263  }
264 
265  ~ReducePool() { if (mOwnsGrid) delete mGrid; }
266 
267  void operator()(const RangeT& r)
268  {
269  for (IterT i=r.begin(); i!=r.end(); ++i) mGrid->topologyUnion( *(*i) );
270  }
271 
272  void join(ReducePool& other) { mGrid->topologyUnion(*other.mGrid); }
273 
274  const bool mOwnsGrid;
275  GridT* mGrid;
276 };// end of private member class ReducePool
277 
278 } // namespace tools
279 } // namespace OPENVDB_VERSION_NAME
280 } // namespace openvdb
281 
282 #endif // OPENVDB_TOOLS_POINTSTOMASK_HAS_BEEN_INCLUDED
283 
284 // Copyright (c) 2012-2018 DreamWorks Animation LLC
285 // All rights reserved. This software is distributed under the
286 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
GLenum GLint * range
Definition: glcorearb.h:1924
math::Vec3< Real > Vec3R
Definition: Types.h:79
PointsToMask(GridT &grid, InterrupterT *interrupter=nullptr)
Constructor from a grid and optional interrupter.
Definition: PointsToMask.h:138
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
void maskPoints(const PointListT &points, GridT &grid)
Makes every voxel of the grid active if it contains a point.
Definition: PointsToMask.h:102
Makes every voxel of a grid active if it contains a point.
Definition: PointsToMask.h:94
png_uint_32 i
Definition: png.h:2877
ReducePool(PoolType &pool, GridT *grid, size_t grainSize=1)
Definition: PointsToMask.h:244
GLdouble n
Definition: glcorearb.h:2007
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
Coord worldToIndexCellCentered(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:138
GLboolean r
Definition: glcorearb.h:1221
bool wasInterrupted(T *i, int percent=-1)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
void addPoints(const PointListT &points, size_t grainSize=1024)
Activates the state of any voxel in the input grid that contains a point.
Definition: PointsToMask.h:150