Skip to content

Commit 5528666

Browse files
authored
Merge pull request #1008 from Idclip/point_transfer
OpenVDB Points -> Volume transfer framework & kernels
2 parents ec3e907 + 75a4a87 commit 5528666

File tree

10 files changed

+4456
-57
lines changed

10 files changed

+4456
-57
lines changed

openvdb/openvdb/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,12 @@ set(OPENVDB_LIBRARY_POINTS_INCLUDE_FILES
449449
points/PointGroup.h
450450
points/PointMask.h
451451
points/PointMove.h
452+
points/PointRasterizeSDF.h
453+
points/PointRasterizeTrilinear.h
452454
points/PointSample.h
453455
points/PointScatter.h
454456
points/PointStatistics.h
457+
points/PointTransfer.h
455458
points/StreamCompression.h
456459
)
457460

openvdb/openvdb/points/PointCount.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,20 @@ typename GridT::Ptr
165165
pointCountGrid( const PointDataGridT& points,
166166
const FilterT& filter)
167167
{
168-
static_assert( std::is_integral<typename GridT::ValueType>::value ||
169-
std::is_floating_point<typename GridT::ValueType>::value,
168+
static_assert(std::is_integral<typename GridT::ValueType>::value ||
169+
std::is_floating_point<typename GridT::ValueType>::value,
170170
"openvdb::points::pointCountGrid must return an integer or floating-point scalar grid");
171171

172-
// This is safe because the PointDataGrid can only be modified by the deformer
173-
using AdapterT = TreeAdapter<typename PointDataGridT::TreeType>;
174-
auto& nonConstPoints = const_cast<typename AdapterT::NonConstGridType&>(points);
172+
using PointDataTreeT = typename PointDataGridT::TreeType;
173+
using TreeT = typename GridT::TreeType;
175174

176-
return point_mask_internal::convertPointsToScalar<GridT>(
177-
nonConstPoints, filter);
175+
typename TreeT::Ptr tree =
176+
point_mask_internal::convertPointsToScalar<TreeT, PointDataTreeT, FilterT>
177+
(points.tree(), filter);
178+
179+
typename GridT::Ptr grid(new GridT(tree));
180+
grid->setTransform(points.transform().copy());
181+
return grid;
178182
}
179183

180184

openvdb/openvdb/points/PointMask.h

Lines changed: 84 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,33 @@ OPENVDB_USE_VERSION_NAMESPACE
2727
namespace OPENVDB_VERSION_NAME {
2828
namespace points {
2929

30+
/// @brief Extract a Mask Tree from a Point Data Tree
31+
/// @param grid the PointDataGrid to extract the mask from.
32+
/// @param filter an optional index filter
33+
/// @param threaded enable or disable threading (threading is enabled by default)
34+
template <typename PointDataTreeT,
35+
typename MaskTreeT = typename PointDataTreeT::template ValueConverter<bool>::Type,
36+
typename FilterT = NullFilter>
37+
inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
38+
std::is_same<typename MaskTreeT::ValueType, bool>::value, typename MaskTreeT::Ptr>::type
39+
convertPointsToMask(const PointDataTreeT& tree,
40+
const FilterT& filter = NullFilter(),
41+
bool threaded = true);
3042

3143
/// @brief Extract a Mask Grid from a Point Data Grid
3244
/// @param grid the PointDataGrid to extract the mask from.
3345
/// @param filter an optional index filter
3446
/// @param threaded enable or disable threading (threading is enabled by default)
3547
/// @note this method is only available for Bool Grids and Mask Grids
3648
template <typename PointDataGridT,
37-
typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
49+
typename MaskGridT = typename PointDataGridT::template ValueConverter<bool>::Type,
3850
typename FilterT = NullFilter>
39-
inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
40-
typename MaskT::Ptr>::type
51+
inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT>::value &&
52+
std::is_same<typename MaskGridT::ValueType, bool>::value, typename MaskGridT::Ptr>::type
4153
convertPointsToMask(const PointDataGridT& grid,
4254
const FilterT& filter = NullFilter(),
4355
bool threaded = true);
4456

45-
4657
/// @brief Extract a Mask Grid from a Point Data Grid using a new transform
4758
/// @param grid the PointDataGrid to extract the mask from.
4859
/// @param transform target transform for the mask.
@@ -59,7 +70,6 @@ convertPointsToMask(const PointDataGridT& grid,
5970
const FilterT& filter = NullFilter(),
6071
bool threaded = true);
6172

62-
6373
/// @brief No-op deformer (adheres to the deformer interface documented in PointMove.h)
6474
struct NullDeformer
6575
{
@@ -142,39 +152,42 @@ struct GridCombinerOp
142152

143153

144154
/// @brief Compute scalar grid from PointDataGrid while evaluating the point filter
145-
template <typename GridT, typename PointDataGridT, typename FilterT>
155+
template <typename TreeT, typename PointDataTreeT, typename FilterT>
146156
struct PointsToScalarOp
147157
{
148-
using LeafT = typename GridT::TreeType::LeafNodeType;
158+
using LeafT = typename TreeT::LeafNodeType;
149159
using ValueT = typename LeafT::ValueType;
160+
// This method is also used by PointCount so ValueT may not be bool
161+
static constexpr bool IsBool =
162+
std::is_same<ValueT, bool>::value;
150163

151-
PointsToScalarOp( const PointDataGridT& grid,
152-
const FilterT& filter)
153-
: mPointDataAccessor(grid.getConstAccessor())
154-
, mFilter(filter) { }
155-
156-
void operator()(LeafT& leaf, size_t /*idx*/) const {
164+
PointsToScalarOp(const PointDataTreeT& tree,
165+
const FilterT& filter)
166+
: mPointDataAccessor(tree)
167+
, mFilter(filter) {}
157168

169+
void operator()(LeafT& leaf, size_t /*idx*/) const
170+
{
171+
// assumes matching topology
158172
const auto* const pointLeaf =
159173
mPointDataAccessor.probeConstLeaf(leaf.origin());
160-
161-
// assumes matching topology
162174
assert(pointLeaf);
163175

164176
for (auto value = leaf.beginValueOn(); value; ++value) {
165-
const Index64 count = points::iterCount(
166-
pointLeaf->beginIndexVoxel(value.getCoord(), mFilter));
167-
if (count > Index64(0)) {
168-
value.setValue(ValueT(count));
169-
} else {
170-
// disable any empty voxels
171-
value.setValueOn(false);
177+
const auto iter = pointLeaf->beginIndexVoxel(value.getCoord(), mFilter);
178+
if (IsBool) {
179+
if (!iter) value.setValueOn(false);
180+
}
181+
else {
182+
const Index64 count = points::iterCount(iter);
183+
if (count > Index64(0)) value.setValue(ValueT(count));
184+
else value.setValueOn(false);
172185
}
173186
}
174187
}
175188

176189
private:
177-
const typename PointDataGridT::ConstAccessor mPointDataAccessor;
190+
const tree::ValueAccessor<const PointDataTreeT> mPointDataAccessor;
178191
const FilterT& mFilter;
179192
}; // struct PointsToScalarOp
180193

@@ -251,56 +264,53 @@ struct PointsToTransformedScalarOp
251264
}; // struct PointsToTransformedScalarOp
252265

253266

254-
template<typename GridT, typename PointDataGridT, typename FilterT>
255-
inline typename GridT::Ptr convertPointsToScalar(
256-
const PointDataGridT& points,
267+
template<typename TreeT, typename PointDataTreeT, typename FilterT>
268+
inline typename TreeT::Ptr convertPointsToScalar(
269+
const PointDataTreeT& points,
257270
const FilterT& filter,
258271
bool threaded = true)
259272
{
260273
using point_mask_internal::PointsToScalarOp;
261274

262-
using GridTreeT = typename GridT::TreeType;
263-
using ValueT = typename GridTreeT::ValueType;
275+
using ValueT = typename TreeT::ValueType;
264276

265-
// copy the topology from the points grid
277+
// copy the topology from the points tree
266278

267-
typename GridTreeT::Ptr tree(new GridTreeT(points.constTree(),
268-
false, openvdb::TopologyCopy()));
269-
typename GridT::Ptr grid = GridT::create(tree);
270-
grid->setTransform(points.transform().copy());
279+
typename TreeT::Ptr tree(new TreeT(/*background=*/false));
280+
tree->topologyUnion(points);
271281

272282
// early exit if no leaves
273283

274-
if (points.constTree().leafCount() == 0) return grid;
284+
if (points.leafCount() == 0) return tree;
275285

276286
// early exit if mask and no group logic
277287

278-
if (std::is_same<ValueT, bool>::value && filter.state() == index::ALL) return grid;
288+
if (std::is_same<ValueT, bool>::value && filter.state() == index::ALL) return tree;
279289

280290
// evaluate point group filters to produce a subset of the generated mask
281291

282-
tree::LeafManager<GridTreeT> leafManager(*tree);
292+
tree::LeafManager<TreeT> leafManager(*tree);
283293

284294
if (filter.state() == index::ALL) {
285295
NullFilter nullFilter;
286-
PointsToScalarOp<GridT, PointDataGridT, NullFilter> pointsToScalarOp(
296+
PointsToScalarOp<TreeT, PointDataTreeT, NullFilter> pointsToScalarOp(
287297
points, nullFilter);
288298
leafManager.foreach(pointsToScalarOp, threaded);
289299
} else {
290300
// build mask from points in parallel only where filter evaluates to true
291-
PointsToScalarOp<GridT, PointDataGridT, FilterT> pointsToScalarOp(
301+
PointsToScalarOp<TreeT, PointDataTreeT, FilterT> pointsToScalarOp(
292302
points, filter);
293303
leafManager.foreach(pointsToScalarOp, threaded);
294304
}
295305

296-
return grid;
306+
return tree;
297307
}
298308

299309

300310
template<typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
301311
inline typename GridT::Ptr convertPointsToScalar(
302312
PointDataGridT& points,
303-
const openvdb::math::Transform& transform,
313+
const math::Transform& transform,
304314
const FilterT& filter,
305315
const DeformerT& deformer,
306316
bool threaded = true)
@@ -311,17 +321,21 @@ inline typename GridT::Ptr convertPointsToScalar(
311321
using CombinerOpT = GridCombinerOp<GridT>;
312322
using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
313323

324+
typename GridT::Ptr grid = GridT::create();
325+
grid->setTransform(transform.copy());
326+
314327
// use the simpler method if the requested transform matches the existing one
315328

316-
const openvdb::math::Transform& pointsTransform = points.constTransform();
329+
const math::Transform& pointsTransform = points.constTransform();
317330

318331
if (transform == pointsTransform && std::is_same<NullDeformer, DeformerT>()) {
319-
return convertPointsToScalar<GridT>(points, filter, threaded);
332+
using TreeT = typename GridT::TreeType;
333+
typename TreeT::Ptr tree =
334+
convertPointsToScalar<TreeT>(points.tree(), filter, threaded);
335+
grid->setTree(tree);
336+
return grid;
320337
}
321338

322-
typename GridT::Ptr grid = GridT::create();
323-
grid->setTransform(transform.copy());
324-
325339
// early exit if no leaves
326340

327341
if (points.constTree().leafCount() == 0) return grid;
@@ -359,16 +373,36 @@ inline typename GridT::Ptr convertPointsToScalar(
359373
////////////////////////////////////////
360374

361375

362-
template<typename PointDataGridT, typename MaskT, typename FilterT>
363-
inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
364-
typename MaskT::Ptr>::type
376+
template <typename PointDataTreeT, typename MaskTreeT, typename FilterT>
377+
inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
378+
std::is_same<typename MaskTreeT::ValueType, bool>::value, typename MaskTreeT::Ptr>::type
379+
convertPointsToMask(const PointDataTreeT& tree,
380+
const FilterT& filter,
381+
bool threaded)
382+
{
383+
return point_mask_internal::convertPointsToScalar<MaskTreeT>(
384+
tree, filter, threaded);
385+
}
386+
387+
388+
template<typename PointDataGridT, typename MaskGridT, typename FilterT>
389+
inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT>::value &&
390+
std::is_same<typename MaskGridT::ValueType, bool>::value, typename MaskGridT::Ptr>::type
365391
convertPointsToMask(
366392
const PointDataGridT& points,
367393
const FilterT& filter,
368394
bool threaded)
369395
{
370-
return point_mask_internal::convertPointsToScalar<MaskT>(
371-
points, filter, threaded);
396+
using PointDataTreeT = typename PointDataGridT::TreeType;
397+
using MaskTreeT = typename MaskGridT::TreeType;
398+
399+
typename MaskTreeT::Ptr tree =
400+
convertPointsToMask<PointDataTreeT, MaskTreeT, FilterT>
401+
(points.tree(), filter, threaded);
402+
403+
typename MaskGridT::Ptr grid(new MaskGridT(tree));
404+
grid->setTransform(points.transform().copy());
405+
return grid;
372406
}
373407

374408

0 commit comments

Comments
 (0)