10#ifndef OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
11#define OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED
14#include <openvdb/thread/Threading.h>
38template<
typename PointDataGridT,
typename SourceGridT,
39 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
41 const SourceGridT& sourceGrid,
42 const Name& targetAttribute =
"",
43 const FilterT& filter = NullFilter(),
44 InterrupterT*
const interrupter =
nullptr);
56template<
typename PointDataGridT,
typename SourceGridT,
57 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
58inline void boxSample( PointDataGridT& points,
59 const SourceGridT& sourceGrid,
60 const Name& targetAttribute =
"",
61 const FilterT& filter = NullFilter(),
62 InterrupterT*
const interrupter =
nullptr);
74template<
typename PointDataGridT,
typename SourceGridT,
75 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
77 const SourceGridT& sourceGrid,
78 const Name& targetAttribute =
"",
79 const FilterT& filter = NullFilter(),
80 InterrupterT*
const interrupter =
nullptr);
89 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
90 inline ValueT sample(
const AccessorT& accessor,
const Vec3d& position)
const;
112template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT =
DummySampleType,
116 PointDataGridT& points,
117 const SourceGridT& sourceGrid,
118 const Name& targetAttribute,
121 InterrupterT*
const interrupter =
nullptr,
122 const bool threaded =
true);
129namespace point_sample_internal {
132template<
typename FromType,
typename ToType>
133struct CompatibleTypes {
enum {
value = std::is_constructible<ToType, FromType>::value }; };
136template<
typename T>
struct CompatibleTypes<
137 T, T> {
enum {
value =
true }; };
138template<
typename T>
struct CompatibleTypes<
139 T, math::Vec2<T>> {
enum {
value =
true }; };
140template<
typename T>
struct CompatibleTypes<
141 T, math::Vec3<T>> {
enum {
value =
true }; };
142template<
typename T>
struct CompatibleTypes<
143 T, math::Vec4<T>> {
enum {
value =
true }; };
144template<
typename T>
struct CompatibleTypes<
145 math::Vec2<T>, math::Vec2<T>> {
enum {
value =
true }; };
146template<
typename T>
struct CompatibleTypes<
147 math::Vec3<T>, math::Vec3<T>> {
enum {
value =
true }; };
148template<
typename T>
struct CompatibleTypes<
149 math::Vec4<T>, math::Vec4<T>> {
enum {
value =
true }; };
150template<
typename T0,
typename T1>
struct CompatibleTypes<
151 math::Vec2<T0>, math::Vec2<T1>> {
enum {
value = CompatibleTypes<T0, T1>::value }; };
152template<
typename T0,
typename T1>
struct CompatibleTypes<
153 math::Vec3<T0>, math::Vec3<T1>> {
enum {
value = CompatibleTypes<T0, T1>::value }; };
154template<
typename T0,
typename T1>
struct CompatibleTypes<
155 math::Vec4<T0>, math::Vec4<T1>> {
enum {
value = CompatibleTypes<T0, T1>::value }; };
156template<
typename T>
struct CompatibleTypes<
157 ValueMask, T> {
enum {
value = CompatibleTypes<bool, T>::value }; };
161template <
typename T>
struct SamplerTraits {
162 static const size_t Order = 0;
165template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
166 static const size_t Order = T0;
172template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
173struct SampleWithRoundingOp
175 static inline void sample(ValueT&,
const AccessorT&,
const Vec3d&)
177 std::ostringstream ostr;
178 ostr <<
"Cannot sample a " << typeNameAsString<typename AccessorT::ValueType>()
179 <<
" grid on to a " << typeNameAsString<ValueT>() <<
" attribute";
184template <
typename ValueT,
typename SamplerT,
typename AccessorT>
185struct SampleWithRoundingOp<ValueT, SamplerT, AccessorT, true, true>
187 static inline void sample(ValueT&
value,
const AccessorT& accessor,
const Vec3d& position)
189 value = ValueT(math::Round(SamplerT::sample(accessor, position)));
193template <
typename ValueT,
typename SamplerT,
typename AccessorT>
194struct SampleWithRoundingOp<ValueT, SamplerT, AccessorT, false, true>
196 static inline void sample(ValueT&
value,
const AccessorT& accessor,
const Vec3d& position)
198 value = ValueT(SamplerT::sample(accessor, position));
203template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
204class PointDataSampler
207 PointDataSampler(
size_t order,
208 PointDataGridT& points,
209 const SamplerT& sampler,
210 const FilterT& filter,
211 InterrupterT*
const interrupter,
217 , mInterrupter(interrupter)
218 , mThreaded(threaded) { }
222 struct AlignedTransform
224 inline Vec3d transform(
const Vec3d& position)
const {
return position; }
228 struct NonAlignedTransform
230 NonAlignedTransform(
const math::Transform& source,
const math::Transform& target)
232 , mTarget(target) { }
234 inline Vec3d transform(
const Vec3d& position)
const
236 return mSource.worldToIndex(mTarget.indexToWorld(position));
240 const math::Transform& mSource;
241 const math::Transform& mTarget;
245 template <
typename ValueT,
typename SourceGr
idT,
typename Gr
idSamplerT>
246 struct SamplerWrapper
248 using ValueType = ValueT;
249 using SourceValueType =
typename SourceGridT::ValueType;
250 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
253 static const bool SourceIsBool = std::is_same<SourceValueType, bool>::value ||
254 std::is_same<SourceValueType, ValueMask>::value;
255 static const bool OrderIsZero = SamplerTraits<GridSamplerT>::Order == 0;
256 static const bool IsValid = !SourceIsBool || OrderIsZero;
258 SamplerWrapper(
const SourceGridT& sourceGrid,
const SamplerT& sampler)
259 : mAccessor(sourceGrid.getConstAccessor())
260 , mSampler(sampler) { }
264 SamplerWrapper(
const SamplerWrapper& other)
265 : mAccessor(other.mAccessor.tree())
266 , mSampler(other.mSampler) { }
268 template <
bool IsVal
idT = IsVal
id>
269 inline typename std::enable_if<IsValidT, ValueT>::type
270 sample(
const Vec3d& position)
const {
271 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
272 mAccessor, position);
275 template <
bool IsVal
idT = IsVal
id>
276 inline typename std::enable_if<!IsValidT, ValueT>::type
277 sample(
const Vec3d& )
const {
278 OPENVDB_THROW(RuntimeError,
"Cannot sample bool grid with BoxSampler or QuadraticSampler.");
282 SourceAccessorT mAccessor;
283 const SamplerT& mSampler;
286 template <
typename SamplerWrapperT,
typename TransformerT>
287 inline void doSample(
const SamplerWrapperT& sampleWrapper,
const Index targetIndex,
288 const TransformerT& transformer)
290 using PointDataTreeT =
typename PointDataGridT::TreeType;
291 using LeafT =
typename PointDataTreeT::LeafNodeType;
292 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
294 const auto& filter(mFilter);
295 const auto& interrupter(mInterrupter);
297 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &interrupter](
298 LeafT& leaf,
size_t )
300 using TargetHandleT = AttributeWriteHandle<typename SamplerWrapperT::ValueType>;
302 if (util::wasInterrupted(interrupter)) {
303 thread::cancelGroupExecution();
307 SamplerWrapperT newSampleWrapper(sampleWrapper);
308 auto positionHandle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray(
"P"));
309 auto targetHandle = TargetHandleT::create(leaf.attributeArray(targetIndex));
310 for (
auto iter = leaf.beginIndexOn(filter); iter; ++iter) {
311 const Vec3d position = transformer.transform(
312 positionHandle->get(*iter) + iter.getCoord().asVec3d());
313 targetHandle->set(*iter, newSampleWrapper.sample(position));
317 LeafManagerT leafManager(mPoints.tree());
319 if (mInterrupter) mInterrupter->start();
321 leafManager.foreach(sampleLambda, mThreaded);
323 if (mInterrupter) mInterrupter->end();
326 template <
typename SourceGr
idT,
typename SamplerWrapperT>
327 inline void resolveTransform(
const SourceGridT& sourceGrid,
const SamplerWrapperT& sampleWrapper,
328 const Index targetIndex)
330 const auto& sourceTransform = sourceGrid.constTransform();
331 const auto& pointsTransform = mPoints.constTransform();
333 if (sourceTransform == pointsTransform) {
334 AlignedTransform transformer;
335 doSample(sampleWrapper, targetIndex, transformer);
337 NonAlignedTransform transformer(sourceTransform, pointsTransform);
338 doSample(sampleWrapper, targetIndex, transformer);
342 template <
typename SourceGr
idT,
typename TargetValueT,
size_t Order>
343 inline void resolveStaggered(
const SourceGridT& sourceGrid,
const Index targetIndex)
345 using SamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, false>>;
346 using StaggeredSamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, true>>;
348 using SourceValueType =
typename SourceGridT::ValueType;
349 if (VecTraits<SourceValueType>::Size == 3 && sourceGrid.getGridClass() == GRID_STAGGERED) {
350 StaggeredSamplerWrapperT sampleWrapper(sourceGrid, mSampler);
351 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
353 SamplerWrapperT sampleWrapper(sourceGrid, mSampler);
354 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
359 template <
typename SourceGr
idT,
typename TargetValueT =
typename SourceGr
idT::ValueType>
360 inline void sample(
const SourceGridT& sourceGrid, Index targetIndex)
362 using SourceValueType =
typename SourceGridT::ValueType;
363 static const bool SourceIsMask = std::is_same<SourceValueType, bool>::value ||
364 std::is_same<SourceValueType, ValueMask>::value;
366 if (SourceIsMask || mOrder == 0) {
367 resolveStaggered<SourceGridT, TargetValueT, 0>(sourceGrid, targetIndex);
368 }
else if (mOrder == 1) {
369 resolveStaggered<SourceGridT, TargetValueT, 1>(sourceGrid, targetIndex);
370 }
else if (mOrder == 2) {
371 resolveStaggered<SourceGridT, TargetValueT, 2>(sourceGrid, targetIndex);
377 PointDataGridT& mPoints;
378 const SamplerT& mSampler;
379 const FilterT& mFilter;
380 InterrupterT*
const mInterrupter;
381 const bool mThreaded;
385template <
typename Po
intDataGr
idT,
typename ValueT>
386struct AppendAttributeOp
388 static void append(PointDataGridT& points,
const Name& attribute)
390 appendAttribute<ValueT>(points.tree(), attribute);
394template <
typename Po
intDataGr
idT>
395struct AppendAttributeOp<PointDataGridT, DummySampleType>
397 static void append(PointDataGridT&,
const Name&) { }
407template<
typename ValueT,
typename SamplerT,
typename AccessorT>
408ValueT SampleWithRounding::sample(
const AccessorT& accessor,
const Vec3d& position)
const
410 using namespace point_sample_internal;
411 using SourceValueT =
typename AccessorT::ValueType;
412 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
413 static const bool compatible = CompatibleTypes<SourceValueT, ValueT>
::value &&
415 static const bool round = std::is_floating_point<SourceValueT>::value &&
416 std::is_integral<ValueT>::value;
418 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
419 value, accessor, position);
427template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT,
428 typename SamplerT,
typename FilterT,
typename InterrupterT>
430 PointDataGridT& points,
431 const SourceGridT& sourceGrid,
432 const Name& targetAttribute,
433 const FilterT& filter,
434 const SamplerT& sampler,
435 InterrupterT*
const interrupter,
438 using point_sample_internal::AppendAttributeOp;
439 using point_sample_internal::PointDataSampler;
442 Name attribute(targetAttribute);
443 if (targetAttribute.empty()) {
444 attribute = sourceGrid.getName();
448 if (attribute ==
"P") {
452 auto leaf = points.tree().cbeginLeaf();
455 PointDataSampler<PointDataGridT, SamplerT, FilterT, InterrupterT> pointDataSampler(
456 order, points, sampler, filter, interrupter, threaded);
458 const auto& descriptor = leaf->attributeSet().descriptor();
459 size_t targetIndex = descriptor.find(attribute);
460 const bool attributeExists = targetIndex != AttributeSet::INVALID_POS;
462 if (std::is_same<TargetValueT, DummySampleType>::value) {
463 if (!attributeExists) {
465 appendAttribute<typename SourceGridT::ValueType>(points.tree(), attribute);
466 targetIndex = leaf->attributeSet().descriptor().find(attribute);
467 assert(targetIndex != AttributeSet::INVALID_POS);
470 pointDataSampler.template sample<SourceGridT>(sourceGrid,
Index(targetIndex));
472 auto targetIdx =
static_cast<Index>(targetIndex);
474 const Name& targetType = descriptor.valueType(targetIndex);
475 if (targetType == typeNameAsString<Vec3f>()) {
476 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
477 }
else if (targetType == typeNameAsString<Vec3d>()) {
478 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
479 }
else if (targetType == typeNameAsString<Vec3i>()) {
480 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
481 }
else if (targetType == typeNameAsString<int8_t>()) {
482 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
483 }
else if (targetType == typeNameAsString<int16_t>()) {
484 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
485 }
else if (targetType == typeNameAsString<int32_t>()) {
486 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
487 }
else if (targetType == typeNameAsString<int64_t>()) {
488 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
489 }
else if (targetType == typeNameAsString<float>()) {
490 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
491 }
else if (targetType == typeNameAsString<double>()) {
492 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
493 }
else if (targetType == typeNameAsString<bool>()) {
494 pointDataSampler.template sample<SourceGridT, bool>(sourceGrid, targetIdx);
496 std::ostringstream ostr;
497 ostr <<
"Cannot sample attribute of type - " << targetType;
502 if (!attributeExists) {
505 AppendAttributeOp<PointDataGridT, TargetValueT>::append(points, attribute);
506 targetIndex = leaf->attributeSet().descriptor().find(attribute);
507 assert(targetIndex != AttributeSet::INVALID_POS);
510 const Name targetType = typeNameAsString<TargetValueT>();
511 const Name attributeType = descriptor.valueType(targetIndex);
512 if (targetType != attributeType) {
513 std::ostringstream ostr;
514 ostr <<
"Requested attribute type " << targetType <<
" for sampling "
515 <<
" does not match existing attribute type " << attributeType;
521 pointDataSampler.template sample<SourceGridT, TargetValueT>(
522 sourceGrid,
static_cast<Index>(targetIndex));
526template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
528 const SourceGridT& sourceGrid,
529 const Name& targetAttribute,
530 const FilterT& filter,
531 InterrupterT*
const interrupter)
534 sampleGrid(0, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
537template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
539 const SourceGridT& sourceGrid,
540 const Name& targetAttribute,
541 const FilterT& filter,
542 InterrupterT*
const interrupter)
545 sampleGrid(1, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
548template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
550 const SourceGridT& sourceGrid,
551 const Name& targetAttribute,
552 const FilterT& filter,
553 InterrupterT*
const interrupter)
556 sampleGrid(2, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
ValueT value
Definition: GridBuilder.h:1290
Point attribute manipulation in a VDB Point Grid.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition: Exceptions.h:63
Definition: Exceptions.h:64
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
Vec3< double > Vec3d
Definition: Vec3.h:664
void sampleGrid(size_t order, PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute, const FilterT &filter=NullFilter(), const SamplerT &sampler=SampleWithRounding(), InterrupterT *const interrupter=nullptr, const bool threaded=true)
Performs sampling and conversion from a VDB grid onto a VDB Points attribute.
Definition: PointSample.h:429
void boxSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute="", const FilterT &filter=NullFilter(), InterrupterT *const interrupter=nullptr)
Performs tri-linear sampling from a VDB grid onto a VDB Points attribute.
Definition: PointSample.h:538
void quadraticSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute="", const FilterT &filter=NullFilter(), InterrupterT *const interrupter=nullptr)
Performs tri-quadratic sampling from a VDB grid onto a VDB Points attribute.
Definition: PointSample.h:549
void pointSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute="", const FilterT &filter=NullFilter(), InterrupterT *const interrupter=nullptr)
Performs closest point sampling from a VDB grid onto a VDB Points attribute.
Definition: PointSample.h:527
std::string Name
Definition: Name.h:17
Index32 Index
Definition: Types.h:54
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: PointSample.h:96
Definition: PointSample.h:88
Base class for interrupters.
Definition: NullInterrupter.h:26
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212