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