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>
26 template<
typename T>
struct CompatibleTypes<
27 T,
T> {
enum {
value =
true }; };
28 template<
typename T>
struct CompatibleTypes<
30 template<
typename T>
struct CompatibleTypes<
32 template<
typename T>
struct CompatibleTypes<
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<
42 template<
typename T0,
typename T1>
struct CompatibleTypes<
44 template<
typename T0,
typename T1>
struct CompatibleTypes<
46 template<
typename T>
struct CompatibleTypes<
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,
101 InterrupterT*
const interrupter,
107 , mInterrupter(interrupter)
108 , mThreaded(threaded) { }
112 struct AlignedTransform
118 struct NonAlignedTransform
120 NonAlignedTransform(
const math::Transform&
source,
const math::Transform&
target)
122 , mTarget(target) { }
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
140 using SourceAccessorT =
typename SourceGridT::ConstAccessor;
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>
160 sample(
const Vec3d& position)
const {
161 return mSampler.template sample<ValueT, GridSamplerT, SourceAccessorT>(
165 template <
bool IsVal
idT = IsVal
id>
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);
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>>;
239 if (VecTraits<SourceValueType>::Size == 3 && sourceGrid.getGridClass() ==
GRID_STAGGERED) {
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)
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
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>
300 using namespace point_sample_internal;
302 static const bool staggered = SamplerTraits<SamplerT>::Staggered;
303 static const bool compatible = CompatibleTypes<SourceValueT, 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>
321 const SourceGridT& sourceGrid,
322 const Name& targetAttribute,
323 const FilterT& filter,
325 InterrupterT*
const interrupter,
328 using point_sample_internal::AppendAttributeOp;
329 using point_sample_internal::PointDataSampler;
333 if (targetAttribute.empty()) {
334 attribute = sourceGrid.getName();
338 if (attribute ==
"P") {
339 OPENVDB_THROW(RuntimeError,
"Cannot sample onto the \"P\" attribute");
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);
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
GLdouble GLdouble GLint GLint const GLdouble * points
const char * typeNameAsString< int32_t >()
const char * typeNameAsString< Vec3i >()
GLsizei const GLfloat * value
const char * typeNameAsString< int8_t >()
const char * typeNameAsString< int16_t >()
#define OPENVDB_USE_VERSION_NAMESPACE
void pointSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute, const FilterT &filter, InterrupterT *const interrupter)
Performs closest point sampling from a VDB grid onto a VDB Points attribute.
const char * typeNameAsString< Vec3d >()
const char * typeNameAsString< Vec3f >()
void boxSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute, const FilterT &filter, InterrupterT *const interrupter)
Performs tri-linear sampling from a VDB grid onto a VDB Points attribute.
float Round(float x)
Return x rounded to the nearest integer.
const char * typeNameAsString< float >()
GLsizei GLsizei GLchar * source
GLdouble GLdouble GLint GLint order
const char * typeNameAsString< int64_t >()
void sampleGrid(size_t order, PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute, const FilterT &filter, const SamplerT &sampler, InterrupterT *const interrupter, const bool threaded)
Performs sampling and conversion from a VDB grid onto a VDB Points attribute.
vfloat4 round(const vfloat4 &a)
GA_API const UT_StringHolder transform
const char * typeNameAsString< double >()
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
const char * typeNameAsString< bool >()
SIM_API const UT_StringHolder position
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
void quadraticSample(PointDataGridT &points, const SourceGridT &sourceGrid, const Name &targetAttribute, const FilterT &filter, InterrupterT *const interrupter)
Performs tri-quadratic sampling from a VDB grid onto a VDB Points attribute.
bool wasInterrupted(T *i, int percent=-1)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
ValueT sample(const AccessorT &accessor, const Vec3d &position) const
#define OPENVDB_THROW(exception, message)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter