9 #ifndef OPENVDB_POINTS_POINT_SAMPLE_IMPL_HAS_BEEN_INCLUDED 10 #define OPENVDB_POINTS_POINT_SAMPLE_IMPL_HAS_BEEN_INCLUDED 19 namespace point_sample_internal {
22 template<
typename FromType,
typename ToType>
23 struct CompatibleTypes {
enum { value = std::is_constructible<ToType, FromType>::value }; };
26 template<
typename T>
struct CompatibleTypes<
27 T, T> {
enum { value =
true }; };
28 template<
typename T>
struct CompatibleTypes<
29 T, math::Vec2<T>> {
enum { value =
true }; };
30 template<
typename T>
struct CompatibleTypes<
31 T, math::Vec3<T>> {
enum { value =
true }; };
32 template<
typename T>
struct CompatibleTypes<
33 T, math::Vec4<T>> {
enum { value =
true }; };
34 template<
typename T>
struct CompatibleTypes<
35 math::Vec2<T>, math::Vec2<T>> {
enum { value =
true }; };
36 template<
typename T>
struct CompatibleTypes<
37 math::Vec3<T>, math::Vec3<T>> {
enum { value =
true }; };
38 template<
typename T>
struct CompatibleTypes<
39 math::Vec4<T>, math::Vec4<T>> {
enum { value =
true }; };
40 template<
typename T0,
typename T1>
struct CompatibleTypes<
41 math::Vec2<T0>, math::Vec2<T1>> {
enum { value = CompatibleTypes<T0, T1>::value }; };
42 template<
typename T0,
typename T1>
struct CompatibleTypes<
43 math::Vec3<T0>, math::Vec3<T1>> {
enum { value = CompatibleTypes<T0, T1>::value }; };
44 template<
typename T0,
typename T1>
struct CompatibleTypes<
45 math::Vec4<T0>, math::Vec4<T1>> {
enum { value = CompatibleTypes<T0, T1>::value }; };
46 template<
typename T>
struct CompatibleTypes<
47 ValueMask, T> {
enum { value = CompatibleTypes<bool, T>::value }; };
51 template <
typename T>
struct SamplerTraits {
52 static const size_t Order = 0;
55 template <
size_t T0,
bool T1>
struct SamplerTraits<tools::Sampler<T0, T1>> {
56 static const size_t Order = T0;
62 template <
typename ValueT,
typename SamplerT,
typename AccessorT,
bool Round,
bool Compatible = false>
63 struct SampleWithRoundingOp
65 static inline void sample(ValueT&,
const AccessorT&,
const Vec3d&)
67 std::ostringstream ostr;
68 ostr <<
"Cannot sample a " << typeNameAsString<typename AccessorT::ValueType>()
69 <<
" grid on to a " << typeNameAsString<ValueT>() <<
" attribute";
74 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
75 struct SampleWithRoundingOp<ValueT, SamplerT, AccessorT, true, true>
77 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
79 value = ValueT(
math::Round(SamplerT::sample(accessor, position)));
83 template <
typename ValueT,
typename SamplerT,
typename AccessorT>
84 struct SampleWithRoundingOp<ValueT, SamplerT, AccessorT, false, true>
86 static inline void sample(ValueT& value,
const AccessorT& accessor,
const Vec3d& position)
88 value = ValueT(SamplerT::sample(accessor, position));
93 template <
typename Po
intDataGr
idT,
typename SamplerT,
typename FilterT,
typename InterrupterT>
94 class PointDataSampler
97 PointDataSampler(
size_t order,
98 PointDataGridT& points,
99 const SamplerT& sampler,
100 const FilterT& filter,
101 InterrupterT*
const interrupter,
107 , mInterrupter(interrupter)
108 , mThreaded(threaded) { }
112 struct AlignedTransform
114 inline Vec3d transform(
const Vec3d& position)
const {
return position; }
118 struct NonAlignedTransform
120 NonAlignedTransform(
const math::Transform& source,
const math::Transform& target)
122 , mTarget(target) { }
124 inline Vec3d transform(
const Vec3d& position)
const 126 return mSource.worldToIndex(mTarget.indexToWorld(position));
130 const math::Transform& mSource;
131 const math::Transform& mTarget;
135 template <
typename ValueT,
typename SourceGr
idT,
typename Gr
idSamplerT>
136 struct SamplerWrapper
138 using ValueType = ValueT;
139 using SourceValueType =
typename SourceGridT::ValueType;
140 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
143 static const bool SourceIsBool = std::is_same<SourceValueType, bool>::value ||
144 std::is_same<SourceValueType, ValueMask>::value;
145 static const bool OrderIsZero = SamplerTraits<GridSamplerT>::Order == 0;
146 static const bool IsValid = !SourceIsBool || OrderIsZero;
148 SamplerWrapper(
const SourceGridT& sourceGrid,
const SamplerT& sampler)
149 : mAccessor(sourceGrid.getConstAccessor())
150 , mSampler(sampler) { }
154 SamplerWrapper(
const SamplerWrapper& other)
155 : mAccessor(other.mAccessor.tree())
156 , mSampler(other.mSampler) { }
158 template <
bool IsVal
idT = IsVal
id>
159 inline typename std::enable_if<IsValidT, ValueT>::type
160 sample(
const Vec3d& position)
const {
161 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
162 mAccessor, position);
165 template <
bool IsVal
idT = IsVal
id>
166 inline typename std::enable_if<!IsValidT, ValueT>::type
167 sample(
const Vec3d& )
const {
168 OPENVDB_THROW(RuntimeError,
"Cannot sample bool grid with BoxSampler or QuadraticSampler.");
172 SourceAccessorT mAccessor;
173 const SamplerT& mSampler;
176 template <
typename SamplerWrapperT,
typename TransformerT>
177 inline void doSample(
const SamplerWrapperT& sampleWrapper,
const Index targetIndex,
178 const TransformerT& transformer)
180 using PointDataTreeT =
typename PointDataGridT::TreeType;
181 using LeafT =
typename PointDataTreeT::LeafNodeType;
182 using LeafManagerT =
typename tree::LeafManager<PointDataTreeT>;
184 const auto& filter(mFilter);
185 const auto& interrupter(mInterrupter);
187 auto sampleLambda = [targetIndex, &sampleWrapper, &transformer, &filter, &interrupter](
188 LeafT& leaf,
size_t )
190 using TargetHandleT = AttributeWriteHandle<typename SamplerWrapperT::ValueType>;
193 thread::cancelGroupExecution();
197 SamplerWrapperT newSampleWrapper(sampleWrapper);
198 auto positionHandle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray(
"P"));
199 auto targetHandle = TargetHandleT::create(leaf.attributeArray(targetIndex));
200 for (
auto iter = leaf.beginIndexOn(filter); iter; ++iter) {
201 const Vec3d position = transformer.transform(
202 positionHandle->get(*iter) + iter.getCoord().asVec3d());
203 targetHandle->set(*iter, newSampleWrapper.sample(position));
207 LeafManagerT leafManager(mPoints.tree());
209 if (mInterrupter) mInterrupter->start();
211 leafManager.foreach(sampleLambda, mThreaded);
213 if (mInterrupter) mInterrupter->end();
216 template <
typename SourceGr
idT,
typename SamplerWrapperT>
217 inline void resolveTransform(
const SourceGridT& sourceGrid,
const SamplerWrapperT& sampleWrapper,
218 const Index targetIndex)
220 const auto& sourceTransform = sourceGrid.constTransform();
221 const auto& pointsTransform = mPoints.constTransform();
223 if (sourceTransform == pointsTransform) {
224 AlignedTransform transformer;
225 doSample(sampleWrapper, targetIndex, transformer);
227 NonAlignedTransform transformer(sourceTransform, pointsTransform);
228 doSample(sampleWrapper, targetIndex, transformer);
232 template <
typename SourceGr
idT,
typename TargetValueT,
size_t Order>
233 inline void resolveStaggered(
const SourceGridT& sourceGrid,
const Index targetIndex)
235 using SamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, false>>;
236 using StaggeredSamplerWrapperT = SamplerWrapper<TargetValueT, SourceGridT, tools::Sampler<Order, true>>;
238 using SourceValueType =
typename SourceGridT::ValueType;
240 StaggeredSamplerWrapperT sampleWrapper(sourceGrid, mSampler);
241 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
243 SamplerWrapperT sampleWrapper(sourceGrid, mSampler);
244 resolveTransform(sourceGrid, sampleWrapper, targetIndex);
249 template <
typename SourceGr
idT,
typename TargetValueT =
typename SourceGr
idT::ValueType>
250 inline void sample(
const SourceGridT& sourceGrid, Index targetIndex)
252 using SourceValueType =
typename SourceGridT::ValueType;
253 static const bool SourceIsMask = std::is_same<SourceValueType, bool>::value ||
254 std::is_same<SourceValueType, ValueMask>::value;
256 if (SourceIsMask || mOrder == 0) {
257 resolveStaggered<SourceGridT, TargetValueT, 0>(sourceGrid, targetIndex);
258 }
else if (mOrder == 1) {
259 resolveStaggered<SourceGridT, TargetValueT, 1>(sourceGrid, targetIndex);
260 }
else if (mOrder == 2) {
261 resolveStaggered<SourceGridT, TargetValueT, 2>(sourceGrid, targetIndex);
267 PointDataGridT& mPoints;
268 const SamplerT& mSampler;
269 const FilterT& mFilter;
270 InterrupterT*
const mInterrupter;
271 const bool mThreaded;
275 template <
typename Po
intDataGr
idT,
typename ValueT>
276 struct AppendAttributeOp
278 static void append(PointDataGridT& points,
const Name& attribute)
280 appendAttribute<ValueT>(points.tree(), attribute);
284 template <
typename Po
intDataGr
idT>
285 struct AppendAttributeOp<PointDataGridT, DummySampleType>
287 static void append(PointDataGridT&,
const Name&) { }
297 template<
typename ValueT,
typename SamplerT,
typename AccessorT>
298 ValueT SampleWithRounding::sample(
const AccessorT& accessor,
const Vec3d& position)
const 300 using namespace point_sample_internal;
301 using SourceValueT =
typename AccessorT::ValueType;
302 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
303 static const bool compatible = CompatibleTypes<SourceValueT, ValueT>::value &&
305 static const bool round = std::is_floating_point<SourceValueT>::value &&
306 std::is_integral<ValueT>::value;
308 SampleWithRoundingOp<ValueT, SamplerT, AccessorT, round, compatible>::sample(
309 value, accessor, position);
317 template<
typename PointDataGridT,
typename SourceGridT,
typename TargetValueT,
318 typename SamplerT,
typename FilterT,
typename InterrupterT>
320 PointDataGridT& points,
321 const SourceGridT& sourceGrid,
322 const Name& targetAttribute,
323 const FilterT& filter,
324 const SamplerT& sampler,
325 InterrupterT*
const interrupter,
328 using point_sample_internal::AppendAttributeOp;
329 using point_sample_internal::PointDataSampler;
332 Name attribute(targetAttribute);
333 if (targetAttribute.empty()) {
334 attribute = sourceGrid.getName();
338 if (attribute ==
"P") {
342 auto leaf = points.tree().cbeginLeaf();
345 PointDataSampler<PointDataGridT, SamplerT, FilterT, InterrupterT> pointDataSampler(
346 order, points, sampler, filter, interrupter, threaded);
348 const auto& descriptor = leaf->attributeSet().descriptor();
349 size_t targetIndex = descriptor.find(attribute);
350 const bool attributeExists = targetIndex != AttributeSet::INVALID_POS;
352 if (std::is_same<TargetValueT, DummySampleType>::value) {
353 if (!attributeExists) {
355 appendAttribute<typename SourceGridT::ValueType>(points.tree(), attribute);
356 targetIndex = leaf->attributeSet().descriptor().find(attribute);
360 pointDataSampler.template sample<SourceGridT>(sourceGrid,
Index(targetIndex));
362 auto targetIdx =
static_cast<Index>(targetIndex);
364 const Name& targetType = descriptor.valueType(targetIndex);
366 pointDataSampler.template sample<SourceGridT, Vec3f>(sourceGrid, targetIdx);
368 pointDataSampler.template sample<SourceGridT, Vec3d>(sourceGrid, targetIdx);
370 pointDataSampler.template sample<SourceGridT, Vec3i>(sourceGrid, targetIdx);
372 pointDataSampler.template sample<SourceGridT, int8_t>(sourceGrid, targetIdx);
374 pointDataSampler.template sample<SourceGridT, int16_t>(sourceGrid, targetIdx);
376 pointDataSampler.template sample<SourceGridT, int32_t>(sourceGrid, targetIdx);
378 pointDataSampler.template sample<SourceGridT, int64_t>(sourceGrid, targetIdx);
380 pointDataSampler.template sample<SourceGridT, float>(sourceGrid, targetIdx);
382 pointDataSampler.template sample<SourceGridT, double>(sourceGrid, targetIdx);
384 pointDataSampler.template sample<SourceGridT, bool>(sourceGrid, targetIdx);
386 std::ostringstream ostr;
387 ostr <<
"Cannot sample attribute of type - " << targetType;
392 if (!attributeExists) {
395 AppendAttributeOp<PointDataGridT, TargetValueT>::append(points, attribute);
396 targetIndex = leaf->attributeSet().descriptor().find(attribute);
400 const Name targetType = typeNameAsString<TargetValueT>();
401 const Name attributeType = descriptor.valueType(targetIndex);
402 if (targetType != attributeType) {
403 std::ostringstream ostr;
404 ostr <<
"Requested attribute type " << targetType <<
" for sampling " 405 <<
" does not match existing attribute type " << attributeType;
411 pointDataSampler.template sample<SourceGridT, TargetValueT>(
412 sourceGrid,
static_cast<Index>(targetIndex));
416 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
418 const SourceGridT& sourceGrid,
419 const Name& targetAttribute,
420 const FilterT& filter,
421 InterrupterT*
const interrupter)
424 sampleGrid(0, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
427 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
429 const SourceGridT& sourceGrid,
430 const Name& targetAttribute,
431 const FilterT& filter,
432 InterrupterT*
const interrupter)
435 sampleGrid(1, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
438 template<
typename Po
intDataGr
idT,
typename SourceGr
idT,
typename FilterT,
typename InterrupterT>
440 const SourceGridT& sourceGrid,
441 const Name& targetAttribute,
442 const FilterT& filter,
443 InterrupterT*
const interrupter)
446 sampleGrid(2, points, sourceGrid, targetAttribute, filter, sampler, interrupter);
457 #endif // OPENVDB_POINTS_POINT_SAMPLE_IMPL_HAS_BEEN_INCLUDED const char * typeNameAsString< double >()
Definition: Types.h:521
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: PointSampleImpl.h:319
const char * typeNameAsString< Vec3i >()
Definition: Types.h:534
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: PointSampleImpl.h:439
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
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: PointSampleImpl.h:428
const char * typeNameAsString< int32_t >()
Definition: Types.h:526
const char * typeNameAsString< int64_t >()
Definition: Types.h:528
static const int Size
Definition: Types.h:246
Index32 Index
Definition: Types.h:54
Vec3< double > Vec3d
Definition: Vec3.h:665
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
const char * typeNameAsString< int8_t >()
Definition: Types.h:522
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: Exceptions.h:13
Definition: PointSample.h:85
const char * typeNameAsString< bool >()
Definition: Types.h:517
const char * typeNameAsString< float >()
Definition: Types.h:520
Definition: Exceptions.h:64
std::string Name
Definition: Name.h:19
const char * typeNameAsString< int16_t >()
Definition: Types.h:524
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:819
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
const char * typeNameAsString< Vec3d >()
Definition: Types.h:536
const char * typeNameAsString< Vec3f >()
Definition: Types.h:535
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: PointSampleImpl.h:417
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
Definition: Exceptions.h:63