OpenVDB 10.0.0
MultiResGrid.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @file MultiResGrid.h
5///
6/// @author Ken Museth
7///
8/// @warning This class is fairly new and as such has not seen a lot of
9/// use in production. Please report any issues or request for new
10/// features directly to ken.museth@dreamworks.com.
11///
12/// @brief Multi-resolution grid that contains LoD sequences of trees
13/// with powers of two refinements.
14///
15/// @note While this class can arguably be used to implement a sparse
16/// Multi-Grid solver it is currently intended as a means to
17/// efficiently compute LoD levels for applications like rendering
18///
19/// @note Prolongation means interpolation from coarse -> fine
20/// @note Restriction means interpolation (or remapping) from fine -> coarse
21///
22/// @todo Add option to define the level of the input grid (currenlty
23/// 0) so as to allow for super-sampling.
24
25#ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
26#define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
27
28#include <openvdb/openvdb.h>
29#include <openvdb/Grid.h>
31#include <openvdb/math/Math.h>
34#include <openvdb/Metadata.h>
37
38#include "Interpolation.h"
39#include "Morphology.h"
40#include "Prune.h"
41#include "SignedFloodFill.h"
42#include "ValueTransformer.h"
43
44#include <tbb/blocked_range.h>
45#include <tbb/enumerable_thread_specific.h>
46#include <tbb/parallel_for.h>
47
48#include <iostream>
49#include <sstream>
50#include <string>
51#include <vector>
52
53
54namespace openvdb {
56namespace OPENVDB_VERSION_NAME {
57namespace tools {
58
59template<typename TreeType>
60class MultiResGrid: public MetaMap
61{
62public:
65
66 using ValueType = typename TreeType::ValueType;
67 using ValueOnCIter = typename TreeType::ValueOnCIter;
68 using ValueOnIter = typename TreeType::ValueOnIter;
69 using TreePtr = typename TreeType::Ptr;
70 using ConstTreePtr = typename TreeType::ConstPtr;
71 using GridPtr = typename Grid<TreeType>::Ptr;
73
74 //////////////////////////////////////////////////////////////////////
75
76 /// @brief Constructor of empty grids
77 /// @param levels The number of trees in this MultiResGrid
78 /// @param background Background value
79 /// @param voxelSize Size of a (uniform voxel). Defaults to one.
80 /// @note The multiple grids are all empty.
81 MultiResGrid(size_t levels, ValueType background, double voxelSize = 1.0);
82
83 /// @brief Given an initial high-resolution grid this constructor
84 /// generates all the coarser grids by means of restriction.
85 /// @param levels The number of trees in this MultiResGrid
86 /// @param grid High-resolution input grid
87 /// @param useInjection Use restriction by injection, vs
88 /// full-weighting. It defaults to false and should rarely be used.
89 /// @note This constructor will perform a deep copy of the input
90 /// grid and use it as the highest level grid.
91 MultiResGrid(size_t levels, const Grid<TreeType> &grid, bool useInjection = false);
92
93 /// @brief Given an initial high-resolution grid this constructor
94 /// generates all the coarser grids by means of restriction.
95 /// @param levels The number of trees in this MultiResGrid
96 /// @param grid High-resolution input grid
97 /// @param useInjection Use restriction by injection, vs
98 /// full-weighting. It defaults to false and should rarely be used.
99 /// @note This constructor will steal the input grid and use it
100 /// as the highest level grid. On output the grid is empty.
101 MultiResGrid(size_t levels, GridPtr grid, bool useInjection = false);
102
103 //////////////////////////////////////////////////////////////////////
104
105 /// @brief Return the number of levels, i.e. trees, in this MultiResGrid
106 /// @note level 0 is the finest level and numLevels()-1 is the coarsest
107 /// level.
108 size_t numLevels() const { return mTrees.size(); }
109
110 /// @brief Return the level of the finest grid (always 0)
111 static size_t finestLevel() { return 0; }
112
113 /// @brief Return the level of the coarsest grid, i.e. numLevels()-1
114 size_t coarsestLevel() const { return mTrees.size()-1; }
115
116 //////////////////////////////////////////////////////////////////////
117
118 /// @brief Return a reference to the tree at the specified level
119 /// @param level The level of the tree to be returned
120 /// @note Level 0 is by definition the finest tree.
121 TreeType& tree(size_t level);
122
123 /// @brief Return a const reference to the tree at the specified level
124 /// @param level The level of the tree to be returned
125 /// @note Level 0 is by definition the finest tree.
126 const TreeType& constTree(size_t level) const;
127
128 /// @brief Return a shared pointer to the tree at the specified level
129 /// @param level The level of the tree to be returned
130 /// @note Level 0 is by definition the finest tree.
131 TreePtr treePtr(size_t level);
132
133 /// @brief Return a const shared pointer to the tree at the specified level
134 /// @param level The level of the tree to be returned
135 /// @note Level 0 is by definition the finest tree.
136 ConstTreePtr constTreePtr(size_t level) const;
137
138 /// @brief Return a reference to the tree at the finest level
139 TreeType& finestTree() { return *mTrees.front(); }
140
141 /// @brief Return a const reference to the tree at the finest level
142 const TreeType& finestConstTree() const { return *mTrees.front(); }
143
144 /// @brief Return a shared pointer to the tree at the finest level
145 TreePtr finestTreePtr() { return mTrees.front(); }
146
147 /// @brief Return a const shared pointer to the tree at the finest level
148 ConstTreePtr finestConstTreePtr() const { return mTrees.front(); }
149
150 /// @brief Return a reference to the tree at the coarsest level
151 TreeType& coarsestTree() { return *mTrees.back(); }
152
153 /// @brief Return a const reference to the tree at the coarsest level
154 const TreeType& coarsestConstTree() const { return *mTrees.back(); }
155
156 /// @brief Return a shared pointer to the tree at the coarsest level
157 TreePtr coarsestTreePtr() { return mTrees.back(); }
158
159 /// @brief Return a const shared pointer to the tree at the coarsest level
160 ConstTreePtr coarsestConstTreePtr() const { return mTrees.back(); }
161
162 //////////////////////////////////////////////////////////////////////
163
164 /// @brief Return a shared pointer to the grid at the specified integer level
165 /// @param level Integer level of the grid to be returned
166 /// @note Level 0 is by definition the finest grid.
167 GridPtr grid(size_t level);
168
169 /// @brief Return a const shared pointer to the grid at the specified level
170 /// @param level The level of the grid to be returned
171 /// @note Level 0 is by definition the finest grid.
172 ConstGridPtr grid(size_t level) const;
173
174 /// @brief Return a shared pointer to a new grid at the specified
175 /// floating-point level.
176 /// @param level Floating-point level of the grid to be returned
177 /// @param grainSize Grain size for the multi-threading
178 /// @details Interpolation of the specified order is performed
179 /// between the bracketing integer levels.
180 /// @note Level 0 is by definition the finest grid.
181 template<Index Order>
182 GridPtr createGrid(float level, size_t grainSize = 1) const;
183
184 /// @brief Return a shared pointer to a vector of all the base
185 /// grids in this instance of the MultiResGrid.
186 /// @brief This method is useful for I/O
187 GridPtrVecPtr grids();
188
189 /// @brief Return a const shared pointer to a vector of all the base
190 /// grids in this instance of the MultiResGrid.
191 /// @brief This method is useful for I/O
192 GridCPtrVecPtr grids() const;
193
194 //////////////////////////////////////////////////////////////////////
195
196 //@{
197 /// @brief Return a reference to the finest grid's transform, which might be
198 /// shared with other grids.
199 /// @note Calling setTransform() on this grid invalidates all references
200 /// previously returned by this method.
201 /// @warning The transform is relative to the finest level (=0) grid!
202 math::Transform& transform() { return *mTransform; }
203 const math::Transform& transform() const { return *mTransform; }
204 const math::Transform& constTransform() const { return *mTransform; }
205 //@}
206
207 //////////////////////////////////////////////////////////////////////
208
209 //@{
210 /// @brief Return the floating-point index coordinate at out_level given
211 /// the index coordinate in_xyz at in_level.
212 static Vec3R xyz(const Coord& in_ijk, size_t in_level, size_t out_level);
213 static Vec3R xyz(const Vec3R& in_xyz, size_t in_level, size_t out_level);
214 static Vec3R xyz(const Vec3R& in_xyz, double in_level, double out_level);
215 //@}
216
217 //////////////////////////////////////////////////////////////////////
218
219
220
221 //@{
222 /// @brief Return the value at the specified coordinate position using
223 /// interpolation of the specified order into the tree at the out_level.
224 ///
225 /// @details First in_ijk is mapped from index space at in_level to
226 /// out_level, and then a value is interpolated from the tree at out_level.
227 ///
228 /// @param in_ijk Index coordinate position relative to tree at in_level
229 /// @param in_level Integer level of the input coordinate in_ijk
230 /// @param out_level Integer level of the interpolated value
231 template<Index Order>
232 ValueType sampleValue(const Coord& in_ijk, size_t in_level, size_t out_level) const;
233 template<Index Order>
234 ValueType sampleValue(const Vec3R& in_ijk, size_t in_level, size_t out_level) const;
235 //@}
236
237 /// @brief Return the value at the specified integer coordinate position
238 /// and level using interpolation of the specified order.
239 /// @param ijk Integer coordinate position relative to the highest level (=0) grid
240 /// @param level Floating-point level from which to interpolate the value.
241 /// @brief Non-integer values of the level will use linear-interpolation
242 /// between the neighboring integer levels.
243 template<Index Order>
244 ValueType sampleValue(const Coord& ijk, double level) const;
245
246 /// @brief Return the value at the specified floating-point coordinate position
247 /// and level using interpolation of the specified order.
248 /// @param xyz Floating-point coordinate position relative to the highest level grid
249 /// @param level Floating-point level from which to interpolate
250 /// the value.
251 /// @brief Non-integer values of the level will use linear-interpolation
252 /// between the neighboring integer levels.
253 template<Index Order>
254 ValueType sampleValue(const Vec3R& xyz, double level) const;
255
256 //////////////////////////////////////////////////////////////////////
257
258 /// @brief Return the value at coordinate location in @a level tree
259 /// from the coarser tree at @a level+1 using trilinear interpolation
260 /// @param coords input coords relative to the fine tree at level
261 /// @param level The fine level to receive values from the coarser
262 /// level-1
263 /// @note Prolongation means to interpolation from coarse -> fine
264 ValueType prolongateVoxel(const Coord& coords, const size_t level) const;
265
266
267 /// (coarse->fine) Populates all the active voxel values in a fine (@a level) tree
268 /// from the coarse (@a level+1) tree using linear interpolation
269 /// This transforms multiple values of the tree in parallel
270 void prolongateActiveVoxels(size_t destlevel, size_t grainSize = 1);
271
272 //////////////////////////////////////////////////////////////////////
273
274 /// Populate a coordinate location in @a level (coarse) tree
275 /// from the @a level-1 (fine) tree using trilinear interpolation
276 /// input coords are relative to the mTree[level] (coarse)
277 /// @note Restriction means remapping from fine -> coarse
278 ValueType restrictVoxel(Coord ijk, const size_t level, bool useInjection = false) const;
279
280 /// (fine->coarse) Populates all the active voxel values in the coarse (@a level) tree
281 /// from the fine (@a level-1) tree using trilinear interpolation.
282 /// For cell-centered data, this is equivalent to an average
283 /// For vertex-centered data this is equivalent to transferring the data
284 /// from the fine vertex directly above the coarse vertex.
285 /// This transforms multiple values of the tree in parallel
286 void restrictActiveVoxels(size_t destlevel, size_t grainSize = 1);
287
288 /// Output a human-readable description of this MultiResGrid
289 void print(std::ostream& = std::cout, int verboseLevel = 1) const;
290
291 /// @brief Return a string with the name of this MultiResGrid
292 std::string getName() const
293 {
294 if (Metadata::ConstPtr meta = (*this)[GridBase::META_GRID_NAME]) return meta->str();
295 return "";
296 }
297
298 /// @brief Set the name of this MultiResGrid
299 void setName(const std::string& name)
300 {
301 this->removeMeta(GridBase::META_GRID_NAME);
302 this->insertMeta(GridBase::META_GRID_NAME, StringMetadata(name));
303 }
304
305 /// Return the class of volumetric data (level set, fog volume, etc.) stored in this grid.
307 {
308 typename StringMetadata::ConstPtr s =
309 this->getMetadata<StringMetadata>(GridBase::META_GRID_CLASS);
310 return s ? GridBase::stringToGridClass(s->value()) : GRID_UNKNOWN;
311 }
312
313 /// Specify the class of volumetric data (level set, fog volume, etc.) stored in this grid.
315 {
317 }
318
319 /// Remove the setting specifying the class of this grid's volumetric data.
320 void clearGridClass() { this->removeMeta(GridBase::META_GRID_CLASS); }
321
322private:
323
324 MultiResGrid(const MultiResGrid& other);//disallow copy construction
325 MultiResGrid& operator=(const MultiResGrid& other);//disallow copy assignment
326
327 // For optimal performance we disable registration of the ValueAccessor
329 using ConstAccessor = tree::ValueAccessor<const TreeType, false>;
330
331 void topDownRestrict(bool useInjection);
332
333 inline void initMeta();
334
335 // Private struct that concurrently creates a mask of active voxel
336 // in a coarse tree from the active voxels in a fine tree
337 struct MaskOp;
338
339 /// Private struct that performs multi-threaded restriction
340 struct RestrictOp;
341
342 /// Private struct that performs multi-threaded prolongation
343 struct ProlongateOp;
344
345 // Private struct that performs multi-threaded computation of grids a fraction levels
346 template<Index Order>
347 struct FractionOp;
348
349 /// Private template struct that performs the actual multi-threading
350 template<typename OpType> struct CookOp;
351
352 // Array of shared pointer to trees, level 0 has the highest resolution.
353 std::vector<TreePtr> mTrees;
354 // Shared pointer to a transform associated with the finest level grid
355 typename math::Transform::Ptr mTransform;
356};// MultiResGrid
357
358template<typename TreeType>
360MultiResGrid(size_t levels, ValueType background, double voxelSize)
361 : mTrees(levels)
362 , mTransform(math::Transform::createLinearTransform( voxelSize ))
363{
364 this->initMeta();
365 for (size_t i=0; i<levels; ++i) mTrees[i] = TreePtr(new TreeType(background));
366}
367
368template<typename TreeType>
370MultiResGrid(size_t levels, const Grid<TreeType> &grid, bool useInjection)
371 : MetaMap(grid)
372 , mTrees(levels)
373 , mTransform( grid.transform().copy() )
374{
375 this->initMeta();
376 mTrees[0].reset( new TreeType( grid.tree() ) );// deep copy input tree
377 mTrees[0]->voxelizeActiveTiles();
378 this->topDownRestrict(useInjection);
379}
380
381template<typename TreeType>
383MultiResGrid(size_t levels, GridPtr grid, bool useInjection)
384 : MetaMap(*grid)
385 , mTrees(levels)
386 , mTransform( grid->transform().copy() )
387{
388 this->initMeta();
389 mTrees[0] = grid->treePtr();// steal tree from input grid
390 mTrees[0]->voxelizeActiveTiles();
391 grid->newTree();
392 this->topDownRestrict(useInjection);
393}
394
395template<typename TreeType>
397tree(size_t level)
398{
399 assert( level < mTrees.size() );
400 return *mTrees[level];
401}
402
403template<typename TreeType>
404inline const TreeType& MultiResGrid<TreeType>::
405constTree(size_t level) const
406{
407 assert( level < mTrees.size() );
408 return *mTrees[level];
409}
410
411template<typename TreeType>
412inline typename TreeType::Ptr MultiResGrid<TreeType>::
413treePtr(size_t level)
414{
415 assert( level < mTrees.size() );
416 return mTrees[level];
417}
418
419template<typename TreeType>
420inline typename TreeType::ConstPtr MultiResGrid<TreeType>::
421constTreePtr(size_t level) const
422{
423 assert( level < mTrees.size() );
424 return mTrees[level];
425}
426
427template<typename TreeType>
429grid(size_t level)
430{
431 typename Grid<TreeType>::Ptr grid = Grid<TreeType>::create(this->treePtr(level));
432 math::Transform::Ptr xform = mTransform->copy();
433 if (level>0) xform->preScale( Real(1 << level) );
434 grid->setTransform( xform );
435 grid->insertMeta( *this->copyMeta() );
436 grid->insertMeta( "MultiResGrid_Level", Int64Metadata(level));
437 std::stringstream ss;
438 ss << this->getName() << "_level_" << level;
439 grid->setName( ss.str() );
440 return grid;
441}
442
443template<typename TreeType>
445grid(size_t level) const
446{
447 return const_cast<MultiResGrid*>(this)->grid(level);
448}
449
450template<typename TreeType>
451template<Index Order>
453createGrid(float level, size_t grainSize) const
454{
455 assert( level >= 0.0f && level <= float(mTrees.size()-1) );
456
457 typename Grid<TreeType>::Ptr grid(new Grid<TreeType>(this->constTree(0).background()));
458 math::Transform::Ptr xform = mTransform->copy();
459 xform->preScale( math::Pow(2.0f, level) );
460 grid->setTransform( xform );
461 grid->insertMeta( *(this->copyMeta()) );
462 grid->insertMeta( "MultiResGrid_Level", FloatMetadata(level) );
463 std::stringstream ss;
464 ss << this->getName() << "_level_" << level;
465 grid->setName( ss.str() );
466
467 if ( size_t(floorf(level)) == size_t(ceilf(level)) ) {
468 grid->setTree( this->constTree( size_t(floorf(level))).copy() );
469 } else {
470 FractionOp<Order> tmp(*this, grid->tree(), level, grainSize);
471 if ( grid->getGridClass() == GRID_LEVEL_SET ) {
472 signedFloodFill( grid->tree() );
473 pruneLevelSet( grid->tree() );//only creates inactive tiles
474 }
475 }
476
477 return grid;
478}
479
480template<typename TreeType>
482grids()
483{
484 GridPtrVecPtr grids( new GridPtrVec );
485 for (size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
486 return grids;
487}
488
489template<typename TreeType>
491grids() const
492{
493 GridCPtrVecPtr grids( new GridCPtrVec );
494 for (size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
495 return grids;
496}
497
498template<typename TreeType>
500xyz(const Coord& in_ijk, size_t in_level, size_t out_level)
501{
502 return Vec3R( in_ijk.data() ) * Real(1 << in_level) / Real(1 << out_level);
503}
504
505template<typename TreeType>
507xyz(const Vec3R& in_xyz, size_t in_level, size_t out_level)
508{
509 return in_xyz * Real(1 << in_level) / Real(1 << out_level);
510}
511
512template<typename TreeType>
514xyz(const Vec3R& in_xyz, double in_level, double out_level)
515{
516 return in_xyz * math::Pow(2.0, in_level - out_level);
517
518}
519
520template<typename TreeType>
521template<Index Order>
522typename TreeType::ValueType MultiResGrid<TreeType>::
523sampleValue(const Coord& in_ijk, size_t in_level, size_t out_level) const
524{
525 assert( in_level >= 0 && in_level < mTrees.size() );
526 assert( out_level >= 0 && out_level < mTrees.size() );
527 const ConstAccessor acc(*mTrees[out_level]);// has disabled registration!
528 return tools::Sampler<Order>::sample( acc, this->xyz(in_ijk, in_level, out_level) );
529}
530
531template<typename TreeType>
532template<Index Order>
533typename TreeType::ValueType MultiResGrid<TreeType>::
534sampleValue(const Vec3R& in_xyz, size_t in_level, size_t out_level) const
535{
536 assert( in_level >= 0 && in_level < mTrees.size() );
537 assert( out_level >= 0 && out_level < mTrees.size() );
538 const ConstAccessor acc(*mTrees[out_level]);// has disabled registration!
539 return tools::Sampler<Order>::sample( acc, this->xyz(in_xyz, in_level, out_level) );
540}
541
542template<typename TreeType>
543template<Index Order>
544typename TreeType::ValueType MultiResGrid<TreeType>::
545sampleValue(const Coord& ijk, double level) const
546{
547 assert( level >= 0.0 && level <= double(mTrees.size()-1) );
548 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
549 const ValueType v0 = this->template sampleValue<Order>( ijk, 0, level0 );
550 if ( level0 == level1 ) return v0;
551 assert( level1 - level0 == 1 );
552 const ValueType v1 = this->template sampleValue<Order>( ijk, 0, level1 );
554 const ValueType a = ValueType(level1 - level);
556 return a * v0 + (ValueType(1) - a) * v1;
557}
558
559template<typename TreeType>
560template<Index Order>
561typename TreeType::ValueType MultiResGrid<TreeType>::
562sampleValue(const Vec3R& xyz, double level) const
563{
564 assert( level >= 0.0 && level <= double(mTrees.size()-1) );
565 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
566 const ValueType v0 = this->template sampleValue<Order>( xyz, 0, level0 );
567 if ( level0 == level1 ) return v0;
568 assert( level1 - level0 == 1 );
569 const ValueType v1 = this->template sampleValue<Order>( xyz, 0, level1 );
571 const ValueType a = ValueType(level1 - level);
573 return a * v0 + (ValueType(1) - a) * v1;
574}
575
576template<typename TreeType>
577typename TreeType::ValueType MultiResGrid<TreeType>::
578prolongateVoxel(const Coord& ijk, const size_t level) const
579{
580 assert( level+1 < mTrees.size() );
581 const ConstAccessor acc(*mTrees[level + 1]);// has disabled registration!
582 return ProlongateOp::run(ijk, acc);
583}
584
585template<typename TreeType>
587prolongateActiveVoxels(size_t destlevel, size_t grainSize)
588{
589 assert( destlevel < mTrees.size()-1 );
590 TreeType &fineTree = *mTrees[ destlevel ];
591 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
592 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
593}
594
595template<typename TreeType>
596typename TreeType::ValueType MultiResGrid<TreeType>::
597restrictVoxel(Coord ijk, const size_t destlevel, bool useInjection) const
598{
599 assert( destlevel > 0 && destlevel < mTrees.size() );
600 const TreeType &fineTree = *mTrees[ destlevel-1 ];
601 if ( useInjection ) return fineTree.getValue(ijk<<1);
602 const ConstAccessor acc( fineTree );// has disabled registration!
603 return RestrictOp::run( ijk, acc);
604}
605
606template<typename TreeType>
608restrictActiveVoxels(size_t destlevel, size_t grainSize)
609{
610 assert( destlevel > 0 && destlevel < mTrees.size() );
611 const TreeType &fineTree = *mTrees[ destlevel-1 ];
612 TreeType &coarseTree = *mTrees[ destlevel ];
613 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
614}
615
616template<typename TreeType>
618print(std::ostream& os, int verboseLevel) const
619{
620 os << "MultiResGrid with " << mTrees.size() << " levels\n";
621 for (size_t i=0; i<mTrees.size(); ++i) {
622 os << "Level " << i << ": ";
623 mTrees[i]->print(os, verboseLevel);
624 }
625
626 if ( MetaMap::metaCount() > 0) {
627 os << "Additional metadata:" << std::endl;
628 for (ConstMetaIterator it = beginMeta(), end = endMeta(); it != end; ++it) {
629 os << " " << it->first;
630 if (it->second) {
631 const std::string value = it->second->str();
632 if (!value.empty()) os << ": " << value;
633 }
634 os << "\n";
635 }
636 }
637
638 os << "Transform:" << std::endl;
639 transform().print(os, /*indent=*/" ");
640 os << std::endl;
641}
642
643template<typename TreeType>
645initMeta()
646{
647 const size_t levels = this->numLevels();
648 if (levels < 2) {
649 OPENVDB_THROW(ValueError, "MultiResGrid: at least two levels are required");
650 }
651 this->insertMeta("MultiResGrid_Levels", Int64Metadata( levels ) );
652}
653
654template<typename TreeType>
655void MultiResGrid<TreeType>::
656topDownRestrict(bool useInjection)
657{
658 const bool isLevelSet = this->getGridClass() == GRID_LEVEL_SET;
659 for (size_t n=1; n<mTrees.size(); ++n) {
660 const TreeType &fineTree = *mTrees[n-1];
661 mTrees[n] = TreePtr(new TreeType( fineTree.background() ) );// empty tree
662 TreeType &coarseTree = *mTrees[n];
663 if (useInjection) {// Restriction by injection
664 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
665 const Coord ijk = it.getCoord();
666 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) ) continue;
667 coarseTree.setValue( ijk >> 1, *it );
668 }
669 } else {// Restriction by full-weighting
670 MaskOp tmp(fineTree, coarseTree, 128);
671 this->restrictActiveVoxels(n, 64);
672 }
673 if ( isLevelSet ) {
674 tools::signedFloodFill( coarseTree );
675 tools::pruneLevelSet( coarseTree );//only creates inactive tiles
676 }
677 }// loop over grid levels
678}
679
680template<typename TreeType>
682{
683 using MaskT = typename TreeType::template ValueConverter<ValueMask>::Type;
684 using PoolType = tbb::enumerable_thread_specific<TreeType>;
686 using RangeT = typename ManagerT::LeafRange;
687 using VoxelIterT = typename ManagerT::LeafNodeType::ValueOnCIter;
688
689 MaskOp(const TreeType& fineTree, TreeType& coarseTree, size_t grainSize = 1)
690 : mPool(new PoolType( coarseTree ) )// empty coarse tree acts as examplar
691 {
692 assert( coarseTree.empty() );
693
694 // Create Mask of restruction performed on fineTree
695 MaskT mask(fineTree, false, true, TopologyCopy() );
696
697 // Multi-threaded dilation which also linearizes the tree to leaf nodes
699
700 // Restriction by injection using thread-local storage of coarse tree masks
701 ManagerT leafs( mask );
702 tbb::parallel_for(leafs.leafRange( grainSize ), *this);
703
704 // multithreaded union of thread-local coarse tree masks with the coarse tree
705 using IterT = typename PoolType::const_iterator;
706 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
707 delete mPool;
708 }
709 void operator()(const RangeT& range) const
710 {
711 Accessor coarseAcc( mPool->local() );// disabled registration
712 for (typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
713 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
714 Coord ijk = voxelIter.getCoord();
715 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) ) continue;//no overlap
716 coarseAcc.setValueOn( ijk >> 1 );//injection from fine to coarse level
717 }//loop over active voxels in the fine tree
718 }// loop over leaf nodes in the fine tree
719 }
721};// MaskOp
722
723template<typename TreeType>
724template<Index Order>
726{
727 using MaskT = typename TreeType::template ValueConverter<ValueMask>::Type;
728 using PoolType = tbb::enumerable_thread_specific<MaskT>;
729 using PoolIterT = typename PoolType::iterator;
730 using Manager1 = tree::LeafManager<const TreeType>;
731 using Manager2 = tree::LeafManager<TreeType>;
732 using Range1 = typename Manager1::LeafRange;
733 using Range2 = typename Manager2::LeafRange;
734
735 FractionOp(const MultiResGrid& parent,
736 TreeType& midTree,
737 float level,
738 size_t grainSize = 1)
739 : mLevel( level )
740 , mPool(nullptr)
741 , mTree0( &*(parent.mTrees[size_t(floorf(level))]) )//high-resolution
742 , mTree1( &*(parent.mTrees[size_t(ceilf(level))]) ) //low-resolution
743 {
744 assert( midTree.empty() );
745 assert( mTree0 != mTree1 );
746
747 // Create a pool of thread-local masks
748 MaskT examplar( false );
749 mPool = new PoolType( examplar );
750
751 {// create mask from re-mapping coarse tree to mid-level tree
752 tree::LeafManager<const TreeType> manager( *mTree1 );
753 tbb::parallel_for( manager.leafRange(grainSize), *this );
754 }
755
756 // Multi-threaded dilation of mask
757 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *this);
758
759 // Union thread-local coarse tree masks into the coarse tree
760 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
761 delete mPool;
762
763 {// Interpolate values into the static mid level tree
764 Manager2 manager( midTree );
765 tbb::parallel_for(manager.leafRange(grainSize), *this);
766 }
767 }
768 void operator()(const Range1& range) const
769 {
770 using VoxelIter = typename Manager1::LeafNodeType::ValueOnCIter;
771 // Let mLevel = level + frac, where
772 // level is integer part of mLevel and frac is the fractional part
773 // low-res voxel size in world units = dx1 = 2^(level + 1)
774 // mid-res voxel size in world units = dx = 2^(mLevel) = 2^(level + frac)
775 // low-res index -> world: ijk * dx1
776 // world -> mid-res index: world / dx
777 // low-res index -> mid-res index: (ijk * dx1) / dx = ijk * scale where
778 // scale = dx1/dx = 2^(level+1)/2^(level+frac) = 2^(1-frac)
779 const float scale = math::Pow(2.0f, 1.0f - math::FractionalPart(mLevel));
780 tree::ValueAccessor<MaskT, false> acc( mPool->local() );// disabled registration
781 for (typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
782 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
783 Coord ijk = voxelIter.getCoord();
785 const auto value0 = ijk[0] * scale;
786 const auto value1 = ijk[1] * scale;
787 const auto value2 = ijk[2] * scale;
789 ijk[0] = int(math::Round(value0));
790 ijk[1] = int(math::Round(value1));
791 ijk[2] = int(math::Round(value2));
792
793 acc.setValueOn( ijk );
794 }//loop over active voxels in the fine tree
795 }// loop over leaf nodes in the fine tree
796 }
797 void operator()(const tbb::blocked_range<PoolIterT>& range) const
798 {
799 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
801 }
802 }
803 void operator()(const Range2 &r) const
804 {
805 using VoxelIter = typename TreeType::LeafNodeType::ValueOnIter;
806 // Let mLevel = level + frac, where
807 // level is integer part of mLevel and frac is the fractional part
808 // high-res voxel size in world units = dx0 = 2^(level)
809 // low-res voxel size in world units = dx1 = 2^(level+1)
810 // mid-res voxel size in world units = dx = 2^(mLevel) = 2^(level + frac)
811 // mid-res index -> world: ijk * dx
812 // world -> high-res index: world / dx0
813 // world -> low-res index: world / dx1
814 // mid-res index -> high-res index: (ijk * dx) / dx0 = ijk * scale0 where
815 // scale0 = dx/dx0 = 2^(level+frac)/2^(level) = 2^(frac)
816 // mid-res index -> low-res index: (ijk * dx) / dx1 = ijk * scale1 where
817 // scale1 = dx/dx1 = 2^(level+frac)/2^(level+1) = 2^(frac-1)
818 const float b = math::FractionalPart(mLevel), a = 1.0f - b;
819 const float scale0 = math::Pow( 2.0f, b );
820 const float scale1 = math::Pow( 2.0f,-a );
821 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
822 for (typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
823 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
824 const Vec3R xyz = Vec3R( voxelIter.getCoord().data() );// mid level coord
825 const ValueType v0 = tools::Sampler<Order>::sample( acc0, xyz * scale0 );
826 const ValueType v1 = tools::Sampler<Order>::sample( acc1, xyz * scale1 );
828 const auto value0 = a*v0;
829 const auto value1 = b*v1;
831 voxelIter.setValue( ValueType(value0 + value1) );
832 }
833 }
834 }
835 const float mLevel;
836 PoolType* mPool;
837 const TreeType *mTree0, *mTree1;
838};// FractionOp
839
840
841template<typename TreeType>
842template<typename OperatorType>
843struct MultiResGrid<TreeType>::CookOp
844{
845 using ManagerT = tree::LeafManager<TreeType>;
846 using RangeT = typename ManagerT::LeafRange;
847
848 CookOp(const TreeType& srcTree, TreeType& dstTree, size_t grainSize): acc(srcTree)
849 {
850 ManagerT leafs(dstTree);
851 tbb::parallel_for(leafs.leafRange(grainSize), *this);
852 }
853 CookOp(const CookOp &other): acc(other.acc.tree()) {}
854
855 void operator()(const RangeT& range) const
856 {
857 for (auto leafIt = range.begin(); leafIt; ++leafIt) {
858 auto& phi = leafIt.buffer(0);
859 for (auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
860 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
861 }
862 }
863 }
864
865 const ConstAccessor acc;
866};// CookOp
867
868
869template<typename TreeType>
871{
872 /// @brief Static method that performs restriction by full weighting
873 /// @param ijk Coordinate location on the coarse tree
874 /// @param acc ValueAccessor to the fine tree
875 static ValueType run(Coord ijk, const ConstAccessor &acc)
876 {
877 ijk <<= 1;
878 // Overlapping grid point
879 ValueType v = 8*acc.getValue(ijk);
880 // neighbors in one axial direction
881 v += 4*(acc.getValue(ijk.offsetBy(-1, 0, 0)) + acc.getValue(ijk.offsetBy( 1, 0, 0)) +// x
882 acc.getValue(ijk.offsetBy( 0,-1, 0)) + acc.getValue(ijk.offsetBy( 0, 1, 0)) +// y
883 acc.getValue(ijk.offsetBy( 0, 0,-1)) + acc.getValue(ijk.offsetBy( 0, 0, 1)));// z
884 // neighbors in two axial directions
885 v += 2*(acc.getValue(ijk.offsetBy(-1,-1, 0)) + acc.getValue(ijk.offsetBy(-1, 1, 0)) +// xy
886 acc.getValue(ijk.offsetBy( 1,-1, 0)) + acc.getValue(ijk.offsetBy( 1, 1, 0)) +// xy
887 acc.getValue(ijk.offsetBy(-1, 0,-1)) + acc.getValue(ijk.offsetBy(-1, 0, 1)) +// xz
888 acc.getValue(ijk.offsetBy( 1, 0,-1)) + acc.getValue(ijk.offsetBy( 1, 0, 1)) +// xz
889 acc.getValue(ijk.offsetBy( 0,-1,-1)) + acc.getValue(ijk.offsetBy( 0,-1, 1)) +// yz
890 acc.getValue(ijk.offsetBy( 0, 1,-1)) + acc.getValue(ijk.offsetBy( 0, 1, 1)));// yz
891 // neighbors in three axial directions
892 for (int i=-1; i<=1; i+=2) {
893 for (int j=-1; j<=1; j+=2) {
894 for (int k=-1; k<=1; k+=2) v += acc.getValue(ijk.offsetBy(i,j,k));// xyz
895 }
896 }
897 v *= ValueType(1.0f/64.0f);
898 return v;
899 }
900};// RestrictOp
901
902template<typename TreeType>
904{
905 /// @brief Interpolate values from a coarse grid (acc) into the index space (ijk) of a fine grid
906 /// @param ijk Coordinate location on the fine tree
907 /// @param acc ValueAccessor to the coarse tree
908 static ValueType run(const Coord& ijk, const ConstAccessor &acc)
909 {
910 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
911 case 0:// all even
912 return acc.getValue(ijk>>1);
913 case 1:// x is odd
914 return ValueType(0.5)*(acc.getValue(ijk.offsetBy(-1,0,0)>>1) +
915 acc.getValue(ijk.offsetBy( 1,0,0)>>1));
916 case 2:// y is odd
917 return ValueType(0.5)*(acc.getValue(ijk.offsetBy(0,-1,0)>>1) +
918 acc.getValue(ijk.offsetBy(0, 1,0)>>1));
919 case 3:// x&y are odd
920 return ValueType(0.25)*(acc.getValue(ijk.offsetBy(-1,-1,0)>>1) +
921 acc.getValue(ijk.offsetBy(-1, 1,0)>>1) +
922 acc.getValue(ijk.offsetBy( 1,-1,0)>>1) +
923 acc.getValue(ijk.offsetBy( 1, 1,0)>>1));
924 case 4:// z is odd
925 return ValueType(0.5)*(acc.getValue(ijk.offsetBy(0,0,-1)>>1) +
926 acc.getValue(ijk.offsetBy(0,0, 1)>>1));
927 case 5:// x&z are odd
928 return ValueType(0.25)*(acc.getValue(ijk.offsetBy(-1,0,-1)>>1) +
929 acc.getValue(ijk.offsetBy(-1,0, 1)>>1) +
930 acc.getValue(ijk.offsetBy( 1,0,-1)>>1) +
931 acc.getValue(ijk.offsetBy( 1,0, 1)>>1));
932 case 6:// y&z are odd
933 return ValueType(0.25)*(acc.getValue(ijk.offsetBy(0,-1,-1)>>1) +
934 acc.getValue(ijk.offsetBy(0,-1, 1)>>1) +
935 acc.getValue(ijk.offsetBy(0, 1,-1)>>1) +
936 acc.getValue(ijk.offsetBy(0, 1, 1)>>1));
937 }
938 // all are odd
939 ValueType v = zeroVal<ValueType>();
940 for (int i=-1; i<=1; i+=2) {
941 for (int j=-1; j<=1; j+=2) {
942 for (int k=-1; k<=1; k+=2) v += acc.getValue(ijk.offsetBy(i,j,k)>>1);// xyz
943 }
944 }
945 return ValueType(0.125) * v;
946 }
947};// ProlongateOp
948
949
950////////////////////////////////////////
951
952
953// Explicit Template Instantiation
954
955#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
956
957#ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
959#endif
960
963
964#endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
965
966
967} // namespace tools
968} // namespace OPENVDB_VERSION_NAME
969} // namespace openvdb
970
971#endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
ValueT value
Definition: GridBuilder.h:1290
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Implementation of morphological dilation and erosion.
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
Bracket code with OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN/_END, to inhibit warnings about type conve...
Definition: Platform.h:204
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition: Platform.h:205
Defined various multi-threaded utility functions for trees.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
void setName(const std::string &)
Specify a name for this grid.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition: Grid.h:1234
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid.
static const char *const META_GRID_NAME
Definition: Grid.h:353
static const char *const META_GRID_CLASS
Definition: Grid.h:351
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:571
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:908
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1454
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:574
SharedPtr< Grid > Ptr
Definition: Grid.h:573
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1308
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:20
SharedPtr< const MetaMap > ConstPtr
Definition: MetaMap.h:23
size_t metaCount() const
Definition: MetaMap.h:91
MetadataMap::const_iterator ConstMetaIterator
Definition: MetaMap.h:28
SharedPtr< MetaMap > Ptr
Definition: MetaMap.h:22
void insertMeta(const Name &, const Metadata &value)
Insert a new metadata field or overwrite the value of an existing field.
SharedPtr< const Metadata > ConstPtr
Definition: Metadata.h:27
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
SharedPtr< const TypedMetadata< T > > ConstPtr
Definition: Metadata.h:125
Definition: Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
const Int32 * data() const
Definition: Coord.h:139
Definition: Transform.h:40
SharedPtr< Transform > Ptr
Definition: Transform.h:42
Definition: MultiResGrid.h:61
ValueType restrictVoxel(Coord ijk, const size_t level, bool useInjection=false) const
Definition: MultiResGrid.h:597
void setGridClass(GridClass cls)
Specify the class of volumetric data (level set, fog volume, etc.) stored in this grid.
Definition: MultiResGrid.h:314
typename TreeType::ValueOnIter ValueOnIter
Definition: MultiResGrid.h:68
void prolongateActiveVoxels(size_t destlevel, size_t grainSize=1)
Definition: MultiResGrid.h:587
ValueType sampleValue(const Coord &in_ijk, size_t in_level, size_t out_level) const
Return the value at the specified coordinate position using interpolation of the specified order into...
ConstTreePtr coarsestConstTreePtr() const
Return a const shared pointer to the tree at the coarsest level.
Definition: MultiResGrid.h:160
typename TreeType::ValueType ValueType
Definition: MultiResGrid.h:66
void print(std::ostream &=std::cout, int verboseLevel=1) const
Output a human-readable description of this MultiResGrid.
Definition: MultiResGrid.h:618
const math::Transform & constTransform() const
Definition: MultiResGrid.h:204
GridPtr grid(size_t level)
Return a shared pointer to the grid at the specified integer level.
Definition: MultiResGrid.h:429
void clearGridClass()
Remove the setting specifying the class of this grid's volumetric data.
Definition: MultiResGrid.h:320
TreeType & tree(size_t level)
Return a reference to the tree at the specified level.
Definition: MultiResGrid.h:397
GridPtrVecPtr grids()
Return a shared pointer to a vector of all the base grids in this instance of the MultiResGrid.
Definition: MultiResGrid.h:482
MultiResGrid(size_t levels, ValueType background, double voxelSize=1.0)
Constructor of empty grids.
Definition: MultiResGrid.h:360
math::Transform & transform()
Return a reference to the finest grid's transform, which might be shared with other grids.
Definition: MultiResGrid.h:202
TreeType & coarsestTree()
Return a reference to the tree at the coarsest level.
Definition: MultiResGrid.h:151
static size_t finestLevel()
Return the level of the finest grid (always 0)
Definition: MultiResGrid.h:111
size_t coarsestLevel() const
Return the level of the coarsest grid, i.e. numLevels()-1.
Definition: MultiResGrid.h:114
size_t numLevels() const
Return the number of levels, i.e. trees, in this MultiResGrid.
Definition: MultiResGrid.h:108
ConstTreePtr constTreePtr(size_t level) const
Return a const shared pointer to the tree at the specified level.
Definition: MultiResGrid.h:421
ValueType sampleValue(const Vec3R &in_ijk, size_t in_level, size_t out_level) const
std::string getName() const
Return a string with the name of this MultiResGrid.
Definition: MultiResGrid.h:292
ValueType sampleValue(const Coord &ijk, double level) const
Return the value at the specified integer coordinate position and level using interpolation of the sp...
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) stored in this grid.
Definition: MultiResGrid.h:306
typename TreeType::ValueOnCIter ValueOnCIter
Definition: MultiResGrid.h:67
void setName(const std::string &name)
Set the name of this MultiResGrid.
Definition: MultiResGrid.h:299
typename Grid< TreeType >::Ptr GridPtr
Definition: MultiResGrid.h:71
ValueType prolongateVoxel(const Coord &coords, const size_t level) const
Return the value at coordinate location in level tree from the coarser tree at level+1 using trilinea...
Definition: MultiResGrid.h:578
typename Grid< TreeType >::ConstPtr ConstGridPtr
Definition: MultiResGrid.h:72
const math::Transform & transform() const
Definition: MultiResGrid.h:203
void restrictActiveVoxels(size_t destlevel, size_t grainSize=1)
Definition: MultiResGrid.h:608
const TreeType & constTree(size_t level) const
Return a const reference to the tree at the specified level.
Definition: MultiResGrid.h:405
ConstTreePtr finestConstTreePtr() const
Return a const shared pointer to the tree at the finest level.
Definition: MultiResGrid.h:148
TreePtr finestTreePtr()
Return a shared pointer to the tree at the finest level.
Definition: MultiResGrid.h:145
typename TreeType::Ptr TreePtr
Definition: MultiResGrid.h:69
GridPtr createGrid(float level, size_t grainSize=1) const
Return a shared pointer to a new grid at the specified floating-point level.
const TreeType & finestConstTree() const
Return a const reference to the tree at the finest level.
Definition: MultiResGrid.h:142
ValueType sampleValue(const Vec3R &xyz, double level) const
Return the value at the specified floating-point coordinate position and level using interpolation of...
TreePtr treePtr(size_t level)
Return a shared pointer to the tree at the specified level.
Definition: MultiResGrid.h:413
typename TreeType::ConstPtr ConstTreePtr
Definition: MultiResGrid.h:70
const TreeType & coarsestConstTree() const
Return a const reference to the tree at the coarsest level.
Definition: MultiResGrid.h:154
static Vec3R xyz(const Coord &in_ijk, size_t in_level, size_t out_level)
Return the floating-point index coordinate at out_level given the index coordinate in_xyz at in_level...
Definition: MultiResGrid.h:500
TreePtr coarsestTreePtr()
Return a shared pointer to the tree at the coarsest level.
Definition: MultiResGrid.h:157
TreeType & finestTree()
Return a reference to the tree at the finest level.
Definition: MultiResGrid.h:139
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
Definition: ValueAccessor.h:191
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:271
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:235
OPENVDB_AX_API void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
OPENVDB_AX_API void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
OPENVDB_API uint32_t getGridClass(std::ios_base &)
Return the class (GRID_LEVEL_SET, GRID_UNKNOWN, etc.) of the grid currently being read from or writte...
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:561
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:615
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:819
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:843
@ NN_FACE_EDGE_VERTEX
Definition: Morphology.h:59
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:390
void dilateActiveValues(TreeOrLeafManagerT &tree, const int iterations=1, const NearestNeighbors nn=NN_FACE, const TilePolicy mode=PRESERVE_TILES, const bool threaded=true)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1056
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:267
@ EXPAND_TILES
Definition: Morphology.h:81
@ IGNORE_TILES
Definition: Morphology.h:81
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
double Real
Definition: Types.h:60
GridClass
Definition: Types.h:414
@ GRID_LEVEL_SET
Definition: Types.h:416
@ GRID_UNKNOWN
Definition: Types.h:415
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:516
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:511
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:363
math::Vec3< Real > Vec3R
Definition: Types.h:72
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:513
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:35
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
Definition: MultiResGrid.h:682
typename ManagerT::LeafNodeType::ValueOnCIter VoxelIterT
Definition: MultiResGrid.h:687
MaskOp(const TreeType &fineTree, TreeType &coarseTree, size_t grainSize=1)
Definition: MultiResGrid.h:689
tbb::enumerable_thread_specific< TreeType > PoolType
Definition: MultiResGrid.h:684
PoolType * mPool
Definition: MultiResGrid.h:720
void operator()(const RangeT &range) const
Definition: MultiResGrid.h:709
typename ManagerT::LeafRange RangeT
Definition: MultiResGrid.h:686
typename TreeType::template ValueConverter< ValueMask >::Type MaskT
Definition: MultiResGrid.h:683
static ValueType run(const Coord &ijk, const ConstAccessor &acc)
Interpolate values from a coarse grid (acc) into the index space (ijk) of a fine grid.
Definition: MultiResGrid.h:908
static ValueType run(Coord ijk, const ConstAccessor &acc)
Static method that performs restriction by full weighting.
Definition: MultiResGrid.h:875
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the floating-point index coordinate inCoord and store the result in result.
#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
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:153