10 #ifndef OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED 11 #define OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED 14 #include "openvdb/thread/Threading.h" 21 #include <type_traits> 38 template<
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);
56 template<
typename PointDataGridT,
typename SourceGridT,
57 typename FilterT = NullFilter,
typename InterrupterT = util::NullInterrupter>
58 inline void boxSample( PointDataGridT& points,
59 const SourceGridT& sourceGrid,
60 const Name& targetAttribute =
"",
61 const FilterT& filter = NullFilter(),
62 InterrupterT*
const interrupter =
nullptr);
74 template<
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;
112 template<
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);
129 namespace point_sample_internal {
132 template<
typename FromType,
typename ToType>
136 template<
typename T>
struct CompatibleTypes<
137 T, T> {
enum {
value =
true }; };
138 template<
typename T>
struct CompatibleTypes<
139 T, math::Vec2<T>> {
enum {
value =
true }; };
140 template<
typename T>
struct CompatibleTypes<
141 T, math::Vec3<T>> {
enum {
value =
true }; };
142 template<
typename T>
struct CompatibleTypes<
143 T, math::Vec4<T>> {
enum {
value =
true }; };
144 template<
typename T>
struct CompatibleTypes<
146 template<
typename T>
struct CompatibleTypes<
148 template<
typename T>
struct CompatibleTypes<
150 template<
typename T0,
typename T1>
struct CompatibleTypes<
152 template<
typename T0,
typename T1>
struct CompatibleTypes<
154 template<
typename T0,
typename T1>
struct CompatibleTypes<
156 template<
typename T>
struct CompatibleTypes<
161 template <
typename T>
struct SamplerTraits {
162 static const size_t Order = 0;
163 static const bool Staggered =
false;
165 template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
166 static const size_t Order = T0;
167 static const bool Staggered = T1;
172 template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
173 struct 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";
184 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
185 struct 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)));
193 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
194 struct 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));
203 template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
204 class 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
232 , mTarget(target) { }
234 inline Vec3d transform(
const Vec3d& position)
const 236 return mSource.worldToIndex(mTarget.indexToWorld(position));
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;
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 {
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;
294 const auto& filter(mFilter);
295 const auto& interrupter(mInterrupter);
297 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &interrupter](
298 LeafT& leaf,
size_t )
303 thread::cancelGroupExecution();
307 SamplerWrapperT newSampleWrapper(sampleWrapper);
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;
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;
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;
385 template <
typename Po
intDataGr
idT,
typename ValueT>
386 struct AppendAttributeOp
388 static void append(PointDataGridT& points,
const Name& attribute)
390 appendAttribute<ValueT>(points.tree(), attribute);
394 template <
typename Po
intDataGr
idT>
395 struct AppendAttributeOp<PointDataGridT, DummySampleType>
397 static void append(PointDataGridT&,
const Name&) { }
407 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
408 ValueT 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 &&
418 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
419 value, accessor, position);
427 template<
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;
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);
476 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
478 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
480 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
482 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
484 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
486 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
488 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
490 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
492 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
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));
526 template<
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);
537 template<
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);
548 template<
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);
567 #endif // OPENVDB_POINTS_POINT_SAMPLE_HAS_BEEN_INCLUDED bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
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
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:50
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Base class for interrupters.
Definition: NullInterrupter.h:25
const char * typeNameAsString< int64_t >()
Definition: Types.h:489
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:822
Definition: PointSample.h:96
Point attribute manipulation in a VDB Point Grid.
const char * typeNameAsString< int8_t >()
Definition: Types.h:483
const char * typeNameAsString< Vec3d >()
Definition: Types.h:497
const char * typeNameAsString< Vec3f >()
Definition: Types.h:496
const char * typeNameAsString< float >()
Definition: Types.h:481
std::string Name
Definition: Name.h:17
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
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Definition: Exceptions.h:63
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Index32 Index
Definition: Types.h:54
const char * typeNameAsString< bool >()
Definition: Types.h:478
Write-able version of AttributeHandle.
Definition: AttributeArray.h:881
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 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
const char * typeNameAsString< double >()
Definition: Types.h:482
Definition: AttributeArray.h:810
Definition: Exceptions.h:64
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition: PointSample.h:87
const char * typeNameAsString< int32_t >()
Definition: Types.h:487
const char * typeNameAsString< int16_t >()
Definition: Types.h:485
const char * typeNameAsString< Vec3i >()
Definition: Types.h:495
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202