OpenVDB: PoissonSolver.h Source File

OpenVDB 3.2.0

PoissonSolver.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
88
89 #ifndef OPENVDB_TOOLS_POISSONSOLVER_HAS_BEEN_INCLUDED
90 #define OPENVDB_TOOLS_POISSONSOLVER_HAS_BEEN_INCLUDED
91
92 #include <openvdb/Types.h>
93 #include <openvdb/math/ConjGradient.h>
94 #include <openvdb/tree/LeafManager.h>
95 #include <openvdb/tree/Tree.h>
96 #include <openvdb/util/NullInterrupter.h>
97
98 #include "Morphology.h" // for erodeVoxels
99
100 #include <boost/scoped_array.hpp>
101
102
103 namespace openvdb {
104 OPENVDB_USE_VERSION_NAMESPACE
105 namespace OPENVDB_VERSION_NAME {
106 namespace tools {
107 namespace poisson {
108
109 // This type should be at least as wide as math::pcg::SizeType.
110 typedef Int32 VIndex;
111
113 typedef math::pcg::SparseStencilMatrix<double, 7> LaplacianMatrix;
114
115
117 template<typename TreeType>
130 inline typename TreeType::Ptr
131 solve(const TreeType&, math::pcg::State&);
132
133 template<typename TreeType, typename Interrupter>
134 inline typename TreeType::Ptr
135 solve(const TreeType&, math::pcg::State&, Interrupter&);
137
138
140 template<typename TreeType, typename BoundaryOp, typename Interrupter>
171 inline typename TreeType::Ptr
172 solveWithBoundaryConditions(const TreeType&, const BoundaryOp&, math::pcg::State&, Interrupter&);
173
174 template<typename PreconditionerType, typename TreeType, typename BoundaryOp, typename Interrupter>
175 inline typename TreeType::Ptr
176 solveWithBoundaryConditionsAndPreconditioner(const TreeType&, const BoundaryOp&,
177 math::pcg::State&, Interrupter&);
178
179 template<typename PreconditionerType, typename TreeType, typename DomainTreeType, typename BoundaryOp, typename Interrupter>
180 inline typename TreeType::Ptr
181 solveWithBoundaryConditionsAndPreconditioner(const TreeType&, const DomainTreeType&, const BoundaryOp&,
182 math::pcg::State&, Interrupter&);
184
185
187
188 // The following are low-level routines that can be used to assemble custom solvers.
189
192 template<typename VIndexTreeType>
193 inline void populateIndexTree(VIndexTreeType&);
194
198 template<typename TreeType>
199 inline typename TreeType::template ValueConverter<VIndex>::Type::Ptr
200 createIndexTree(const TreeType&);
201
202
209 template<typename VectorValueType, typename SourceTreeType>
210 inline typename math::pcg::Vector<VectorValueType>::Ptr
211 createVectorFromTree(
212 const SourceTreeType& source,
213 const typename SourceTreeType::template ValueConverter<VIndex>::Type& index);
214
215
223 template<typename TreeValueType, typename VIndexTreeType, typename VectorValueType>
224 inline typename VIndexTreeType::template ValueConverter<TreeValueType>::Type::Ptr
225 createTreeFromVector(
226 const math::pcg::Vector<VectorValueType>& values,
227 const VIndexTreeType& index,
228 const TreeValueType& background);
229
230
235 template<typename BoolTreeType>
236 inline LaplacianMatrix::Ptr
237 createISLaplacian(
238 const typename BoolTreeType::template ValueConverter<VIndex>::Type& vectorIndexTree,
239 const BoolTreeType& interiorMask);
240
241
261 template<typename BoolTreeType, typename BoundaryOp>
262 inline LaplacianMatrix::Ptr
263 createISLaplacianWithBoundaryConditions(
264 const typename BoolTreeType::template ValueConverter<VIndex>::Type& vectorIndexTree,
265 const BoolTreeType& interiorMask,
266 const BoundaryOp& boundaryOp,
267 typename math::pcg::Vector<LaplacianMatrix::ValueType>& source);
268
270
271
273
274
275 namespace internal {
276
279 template<typename LeafType>
280 struct LeafCountOp
281 {
282 VIndex* count;
283 LeafCountOp(VIndex* count_): count(count_) {}
284 void operator()(const LeafType& leaf, size_t leafIdx) const {
285 count[leafIdx] = static_cast<VIndex>(leaf.onVoxelCount());
286 }
287 };
288
289
292 template<typename LeafType>
293 struct LeafIndexOp
294 {
295 const VIndex* count;
296 LeafIndexOp(const VIndex* count_): count(count_) {}
297 void operator()(LeafType& leaf, size_t leafIdx) const {
298 VIndex idx = (leafIdx == 0) ? 0 : count[leafIdx - 1];
299 for (typename LeafType::ValueOnIter it = leaf.beginValueOn(); it; ++it) {
300 it.setValue(idx++);
301 }
302 }
303 };
304
305 } // namespace internal
306
307
308 template<typename VIndexTreeType>
309 inline void
310 populateIndexTree(VIndexTreeType& result)
311 {
312 typedef typename VIndexTreeType::LeafNodeType LeafT;
313 typedef typename tree::LeafManager<VIndexTreeType> LeafMgrT;
314
315 // Linearize the tree.
316 LeafMgrT leafManager(result);
317 const size_t leafCount = leafManager.leafCount();
318
319 if(leafCount == 0) return;
320
321 // Count the number of active voxels in each leaf node.
322 boost::scoped_array<VIndex> perLeafCount(new VIndex[leafCount]);
323 VIndex* perLeafCountPtr = perLeafCount.get();
324 leafManager.foreach(internal::LeafCountOp<LeafT>(perLeafCountPtr));
325
326 // The starting index for each leaf node is the total number
327 // of active voxels in all preceding leaf nodes.
328 for (size_t i = 1; i < leafCount; ++i) {
329 perLeafCount[i] += perLeafCount[i - 1];
330 }
331
332 // The last accumulated value should be the total of all active voxels.
333 assert(Index64(perLeafCount[leafCount-1]) == result.activeVoxelCount());
334
335 // Parallelize over the leaf nodes of the tree, storing a unique index
336 // in each active voxel.
337 leafManager.foreach(internal::LeafIndexOp<LeafT>(perLeafCountPtr));
338 }
339
340
341 template<typename TreeType>
342 inline typename TreeType::template ValueConverter<VIndex>::Type::Ptr
343 createIndexTree(const TreeType& tree)
344 {
345 typedef typename TreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
346
347 // Construct an output tree with the same active voxel topology as the input tree.
348 const VIndex invalidIdx = -1;
349 typename VIdxTreeT::Ptr result(
350 new VIdxTreeT(tree, /*background=*/invalidIdx, TopologyCopy()));
351
352 // All active voxels are degrees of freedom, including voxels contained in active tiles.
353 result->voxelizeActiveTiles();
354
355 populateIndexTree(*result);
356
357 return result;
358 }
359
360
362
363
364 namespace internal {
365
368 template<typename VectorValueType, typename SourceTreeType>
369 struct CopyToVecOp
370 {
371 typedef typename SourceTreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
372 typedef typename VIdxTreeT::LeafNodeType VIdxLeafT;
373 typedef typename SourceTreeType::LeafNodeType LeafT;
374 typedef typename SourceTreeType::ValueType TreeValueT;
375 typedef typename math::pcg::Vector<VectorValueType> VectorT;
376
377 const SourceTreeType* tree;
378 VectorT* vector;
379
380 CopyToVecOp(const SourceTreeType& t, VectorT& v): tree(&t), vector(&v) {}
381
382 void operator()(const VIdxLeafT& idxLeaf, size_t /*leafIdx*/) const
383 {
384 VectorT& vec = *vector;
385 if (const LeafT* leaf = tree->probeLeaf(idxLeaf.origin())) {
386 // If a corresponding leaf node exists in the source tree,
387 // copy voxel values from the source node to the output vector.
388 for (typename VIdxLeafT::ValueOnCIter it = idxLeaf.cbeginValueOn(); it; ++it) {
389 vec[*it] = leaf->getValue(it.pos());
390 }
391 } else {
392 // If no corresponding leaf exists in the source tree,
393 // fill the vector with a uniform value.
394 const TreeValueT& value = tree->getValue(idxLeaf.origin());
395 for (typename VIdxLeafT::ValueOnCIter it = idxLeaf.cbeginValueOn(); it; ++it) {
396 vec[*it] = value;
397 }
398 }
399 }
400 };
401
402 } // namespace internal
403
404
405 template<typename VectorValueType, typename SourceTreeType>
406 inline typename math::pcg::Vector<VectorValueType>::Ptr
407 createVectorFromTree(const SourceTreeType& tree,
408 const typename SourceTreeType::template ValueConverter<VIndex>::Type& idxTree)
409 {
410 typedef typename SourceTreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
411 typedef tree::LeafManager<const VIdxTreeT> VIdxLeafMgrT;
412 typedef typename math::pcg::Vector<VectorValueType> VectorT;
413
414 // Allocate the vector.
415 const size_t numVoxels = idxTree.activeVoxelCount();
416 typename VectorT::Ptr result(new VectorT(static_cast<math::pcg::SizeType>(numVoxels)));
417
418 // Parallelize over the leaf nodes of the index tree, filling the output vector
419 // with values from corresponding voxels of the source tree.
420 VIdxLeafMgrT leafManager(idxTree);
421 leafManager.foreach(internal::CopyToVecOp<VectorValueType, SourceTreeType>(tree, *result));
422
423 return result;
424 }
425
426
428
429
430 namespace internal {
431
434 template<typename TreeValueType, typename VIndexTreeType, typename VectorValueType>
435 struct CopyFromVecOp
436 {
437 typedef typename VIndexTreeType::template ValueConverter<TreeValueType>::Type OutTreeT;
438 typedef typename OutTreeT::LeafNodeType OutLeafT;
439 typedef typename VIndexTreeType::LeafNodeType VIdxLeafT;
440 typedef typename math::pcg::Vector<VectorValueType> VectorT;
441
442 const VectorT* vector;
443 OutTreeT* tree;
444
445 CopyFromVecOp(const VectorT& v, OutTreeT& t): vector(&v), tree(&t) {}
446
447 void operator()(const VIdxLeafT& idxLeaf, size_t /*leafIdx*/) const
448 {
449 const VectorT& vec = *vector;
450 OutLeafT* leaf = tree->probeLeaf(idxLeaf.origin());
451 assert(leaf != NULL);
452 for (typename VIdxLeafT::ValueOnCIter it = idxLeaf.cbeginValueOn(); it; ++it) {
453 leaf->setValueOnly(it.pos(), static_cast<TreeValueType>(vec[*it]));
454 }
455 }
456 };
457
458 } // namespace internal
459
460
461 template<typename TreeValueType, typename VIndexTreeType, typename VectorValueType>
462 inline typename VIndexTreeType::template ValueConverter<TreeValueType>::Type::Ptr
463 createTreeFromVector(
464 const math::pcg::Vector<VectorValueType>& vector,
465 const VIndexTreeType& idxTree,
466 const TreeValueType& background)
467 {
468 typedef typename VIndexTreeType::template ValueConverter<TreeValueType>::Type OutTreeT;
469 typedef typename tree::LeafManager<const VIndexTreeType> VIdxLeafMgrT;
470
471 // Construct an output tree with the same active voxel topology as the index tree.
472 typename OutTreeT::Ptr result(new OutTreeT(idxTree, background, TopologyCopy()));
473 OutTreeT& tree = *result;
474
475 // Parallelize over the leaf nodes of the index tree, populating voxels
476 // of the output tree with values from the input vector.
477 VIdxLeafMgrT leafManager(idxTree);
478 leafManager.foreach(
479 internal::CopyFromVecOp<TreeValueType, VIndexTreeType, VectorValueType>(vector, tree));
480
481 return result;
482 }
483
484
486
487
488 namespace internal {
489
491 template<typename ValueType>
492 struct DirichletOp {
493 inline void operator()(
494 const Coord&, const Coord&, ValueType&, ValueType& diag) const { diag -= 1; }
495 };
496
497
499 template<typename BoolTreeType, typename BoundaryOp>
500 struct ISLaplacianOp
501 {
502 typedef typename BoolTreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
503 typedef typename VIdxTreeT::LeafNodeType VIdxLeafT;
504 typedef LaplacianMatrix::ValueType ValueT;
505 typedef typename math::pcg::Vector<ValueT> VectorT;
506
507 LaplacianMatrix* laplacian;
508 const VIdxTreeT* idxTree;
509 const BoolTreeType* interiorMask;
510 const BoundaryOp boundaryOp;
511 VectorT* source;
512
513 ISLaplacianOp(LaplacianMatrix& m, const VIdxTreeT& idx,
514 const BoolTreeType& mask, const BoundaryOp& op, VectorT& src):
515 laplacian(&m), idxTree(&idx), interiorMask(&mask), boundaryOp(op), source(&src) {}
516
517 void operator()(const VIdxLeafT& idxLeaf, size_t /*leafIdx*/) const
518 {
519 // Local accessors
520 typename tree::ValueAccessor<const BoolTreeType> interior(*interiorMask);
521 typename tree::ValueAccessor<const VIdxTreeT> vectorIdx(*idxTree);
522
523 Coord ijk;
524 VIndex column;
525 const ValueT diagonal = -6.f, offDiagonal = 1.f;
526
527 // Loop over active voxels in this leaf.
528 for (typename VIdxLeafT::ValueOnCIter it = idxLeaf.cbeginValueOn(); it; ++it) {
529 assert(it.getValue() > -1);
530 const math::pcg::SizeType rowNum = static_cast<math::pcg::SizeType>(it.getValue());
531
532 LaplacianMatrix::RowEditor row = laplacian->getRowEditor(rowNum);
533
534 ijk = it.getCoord();
535 if (interior.isValueOn(ijk)) {
536 // The current voxel is an interior voxel.
537 // All of its neighbors are in the solution domain.
538
539 // -x direction
540 row.setValue(vectorIdx.getValue(ijk.offsetBy(-1, 0, 0)), offDiagonal);
541 // -y direction
542 row.setValue(vectorIdx.getValue(ijk.offsetBy(0, -1, 0)), offDiagonal);
543 // -z direction
544 row.setValue(vectorIdx.getValue(ijk.offsetBy(0, 0, -1)), offDiagonal);
545 // diagonal
546 row.setValue(rowNum, diagonal);
547 // +z direction
548 row.setValue(vectorIdx.getValue(ijk.offsetBy(0, 0, 1)), offDiagonal);
549 // +y direction
550 row.setValue(vectorIdx.getValue(ijk.offsetBy(0, 1, 0)), offDiagonal);
551 // +x direction
552 row.setValue(vectorIdx.getValue(ijk.offsetBy(1, 0, 0)), offDiagonal);
553
554 } else {
555 // The current voxel is a boundary voxel.
556 // At least one of its neighbors is outside the solution domain.
557
558 ValueT modifiedDiagonal = 0.f;
559
560 // -x direction
561 if (vectorIdx.probeValue(ijk.offsetBy(-1, 0, 0), column)) {
562 row.setValue(column, offDiagonal);
563 modifiedDiagonal -= 1;
564 } else {
565 boundaryOp(ijk, ijk.offsetBy(-1, 0, 0), source->at(rowNum), modifiedDiagonal);
566 }
567 // -y direction
568 if (vectorIdx.probeValue(ijk.offsetBy(0, -1, 0), column)) {
569 row.setValue(column, offDiagonal);
570 modifiedDiagonal -= 1;
571 } else {
572 boundaryOp(ijk, ijk.offsetBy(0, -1, 0), source->at(rowNum), modifiedDiagonal);
573 }
574 // -z direction
575 if (vectorIdx.probeValue(ijk.offsetBy(0, 0, -1), column)) {
576 row.setValue(column, offDiagonal);
577 modifiedDiagonal -= 1;
578 } else {
579 boundaryOp(ijk, ijk.offsetBy(0, 0, -1), source->at(rowNum), modifiedDiagonal);
580 }
581 // +z direction
582 if (vectorIdx.probeValue(ijk.offsetBy(0, 0, 1), column)) {
583 row.setValue(column, offDiagonal);
584 modifiedDiagonal -= 1;
585 } else {
586 boundaryOp(ijk, ijk.offsetBy(0, 0, 1), source->at(rowNum), modifiedDiagonal);
587 }
588 // +y direction
589 if (vectorIdx.probeValue(ijk.offsetBy(0, 1, 0), column)) {
590 row.setValue(column, offDiagonal);
591 modifiedDiagonal -= 1;
592 } else {
593 boundaryOp(ijk, ijk.offsetBy(0, 1, 0), source->at(rowNum), modifiedDiagonal);
594 }
595 // +x direction
596 if (vectorIdx.probeValue(ijk.offsetBy(1, 0, 0), column)) {
597 row.setValue(column, offDiagonal);
598 modifiedDiagonal -= 1;
599 } else {
600 boundaryOp(ijk, ijk.offsetBy(1, 0, 0), source->at(rowNum), modifiedDiagonal);
601 }
602 // diagonal
603 row.setValue(rowNum, modifiedDiagonal);
604 }
605 } // end loop over voxels
606 }
607 };
608
609 } // namespace internal
610
611
612 template<typename BoolTreeType>
613 inline LaplacianMatrix::Ptr
614 createISLaplacian(const typename BoolTreeType::template ValueConverter<VIndex>::Type& idxTree,
615 const BoolTreeType& interiorMask)
616 {
617 typedef LaplacianMatrix::ValueType ValueT;
618 math::pcg::Vector<ValueT> unused(
619 static_cast<math::pcg::SizeType>(idxTree.activeVoxelCount()));
620 internal::DirichletOp<ValueT> op;
621 return createISLaplacianWithBoundaryConditions(idxTree, interiorMask, op, unused);
622 }
623
624
625 template<typename BoolTreeType, typename BoundaryOp>
626 inline LaplacianMatrix::Ptr
627 createISLaplacianWithBoundaryConditions(
628 const typename BoolTreeType::template ValueConverter<VIndex>::Type& idxTree,
629 const BoolTreeType& interiorMask,
630 const BoundaryOp& boundaryOp,
631 typename math::pcg::Vector<LaplacianMatrix::ValueType>& source)
632 {
633 typedef typename BoolTreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
634 typedef typename tree::LeafManager<const VIdxTreeT> VIdxLeafMgrT;
635
636 // The number of active voxels is the number of degrees of freedom.
637 const Index64 numDoF = idxTree.activeVoxelCount();
638
639 // Construct the matrix.
640 LaplacianMatrix::Ptr laplacianPtr(
641 new LaplacianMatrix(static_cast<math::pcg::SizeType>(numDoF)));
642 LaplacianMatrix& laplacian = *laplacianPtr;
643
644 // Populate the matrix using a second-order, 7-point CD stencil.
645 VIdxLeafMgrT idxLeafManager(idxTree);
646 idxLeafManager.foreach(internal::ISLaplacianOp<BoolTreeType, BoundaryOp>(
647 laplacian, idxTree, interiorMask, boundaryOp, source));
648
649 return laplacianPtr;
650 }
651
652
654
655
656 template<typename TreeType>
657 inline typename TreeType::Ptr
658 solve(const TreeType& inTree, math::pcg::State& state)
659 {
660 util::NullInterrupter interrupter;
661 return solve(inTree, state, interrupter);
662 }
663
664
665 template<typename TreeType, typename Interrupter>
666 inline typename TreeType::Ptr
667 solve(const TreeType& inTree, math::pcg::State& state, Interrupter& interrupter)
668 {
669 internal::DirichletOp<LaplacianMatrix::ValueType> boundaryOp;
670 return solveWithBoundaryConditions(inTree, boundaryOp, state, interrupter);
671 }
672
673
674 template<typename TreeType, typename BoundaryOp, typename Interrupter>
675 inline typename TreeType::Ptr
676 solveWithBoundaryConditions(const TreeType& inTree, const BoundaryOp& boundaryOp,
677 math::pcg::State& state, Interrupter& interrupter)
678 {
679 typedef math::pcg::IncompleteCholeskyPreconditioner<LaplacianMatrix> DefaultPrecondT;
680 return solveWithBoundaryConditionsAndPreconditioner<DefaultPrecondT>(
681 inTree, boundaryOp, state, interrupter);
682 }
683
684
685 template<typename PreconditionerType, typename TreeType, typename BoundaryOp, typename Interrupter>
686 inline typename TreeType::Ptr
687 solveWithBoundaryConditionsAndPreconditioner(const TreeType& inTree,
688 const BoundaryOp& boundaryOp, math::pcg::State& state, Interrupter& interrupter)
689 {
690
691 return solveWithBoundaryConditionsAndPreconditioner<PreconditionerType>(inTree /*source*/, inTree /*domain mask*/,
692 boundaryOp, state, interrupter);
693 }
694
695 template<typename PreconditionerType, typename TreeType, typename DomainTreeType, typename BoundaryOp, typename Interrupter>
696 inline typename TreeType::Ptr
697 solveWithBoundaryConditionsAndPreconditioner(const TreeType& inTree,
698 const DomainTreeType& domainMask,
699 const BoundaryOp& boundaryOp,
700 math::pcg::State& state, Interrupter& interrupter)
701 {
702
703 typedef typename TreeType::ValueType TreeValueT;
704 typedef LaplacianMatrix::ValueType VecValueT;
705 typedef typename math::pcg::Vector<VecValueT> VectorT;
706 typedef typename TreeType::template ValueConverter<VIndex>::Type VIdxTreeT;
707 typedef typename TreeType::template ValueConverter<bool>::Type MaskTreeT;
708
709 // 1. Create a mapping from active voxels of the input tree to elements of a vector.
710 typename VIdxTreeT::ConstPtr idxTree = createIndexTree(domainMask);
711
712 // 2. Populate a vector with values from the input tree.
713 typename VectorT::Ptr b = createVectorFromTree<VecValueT>(inTree, *idxTree);
714
715 // 3. Create a mask of the interior voxels of the input tree (from the densified index tree).
716 typename MaskTreeT::Ptr interiorMask(
717 new MaskTreeT(*idxTree, /*background=*/false, TopologyCopy()));
718 tools::erodeVoxels(*interiorMask, /*iterations=*/1, tools::NN_FACE);
719
720 // 4. Create the Laplacian matrix.
721 LaplacianMatrix::Ptr laplacian = createISLaplacianWithBoundaryConditions(
722 *idxTree, *interiorMask, boundaryOp, *b);
723
724 // 5. Solve the Poisson equation.
725 laplacian->scale(-1.0); // matrix is negative-definite; solve -M x = -b
726 b->scale(-1.0);
727 typename VectorT::Ptr x(new VectorT(b->size(), zeroVal<VecValueT>()));
728 typename math::pcg::Preconditioner<VecValueT>::Ptr precond(
729 new PreconditionerType(*laplacian));
730 if (!precond->isValid()) {
731 precond.reset(new math::pcg::JacobiPreconditioner<LaplacianMatrix>(*laplacian));
732 }
733
734 state = math::pcg::solve(*laplacian, *b, *x, *precond, interrupter, state);
735
736 // 6. Populate the output tree with values from the solution vector.
738 return createTreeFromVector<TreeValueT>(*x, *idxTree, /*background=*/zeroVal<TreeValueT>());
739 }
740
741 } // namespace poisson
742 } // namespace tools
743 } // namespace OPENVDB_VERSION_NAME
744 } // namespace openvdb
745
746 #endif // OPENVDB_TOOLS_POISSONSOLVER_HAS_BEEN_INCLUDED
747
749 //
750 // Copyright (c) 2012-2016 DreamWorks Animation LLC
751 //
752 // All rights reserved. This software is distributed under the
753 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
754 //
755 // Redistributions of source code must retain the above copyright
756 // and license notice and the following restrictions and disclaimer.
757 //
758 // * Neither the name of DreamWorks Animation nor the names of
759 // its contributors may be used to endorse or promote products derived
760 // from this software without specific prior written permission.
761 //
762 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
763 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
764 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
765 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
766 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
767 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
768 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
769 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
770 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
771 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
772 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
773 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
774 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
775 //
openvdb::v3_2_0::tools::NN_FACE
Definition: Morphology.h:87
openvdb::v3_2_0::math::pcg::Preconditioner::Ptr
boost::shared_ptr< Preconditioner > Ptr
Definition: ConjGradient.h:497
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::tree
const SourceTreeType * tree
Definition: PoissonSolver.h:377
openvdb::v3_2_0::math::pcg::SparseStencilMatrix::Ptr
boost::shared_ptr< SparseStencilMatrix > Ptr
Definition: ConjGradient.h:271
openvdb::v3_2_0::tools::poisson::internal::LeafIndexOp
Functor for use with LeafManager::foreach() to populate active leaf voxels with sequential indices...
Definition: PoissonSolver.h:293
Types.h
openvdb::v3_2_0::tools::poisson::internal::LeafCountOp::operator()
void operator()(const LeafType &leaf, size_t leafIdx) const
Definition: PoissonSolver.h:284
openvdb::v3_2_0::math::pcg::Vector
Lightweight, variable-length vector.
Definition: ConjGradient.h:65
openvdb::v3_2_0::tools::poisson::solveWithBoundaryConditionsAndPreconditioner
TreeType::Ptr solveWithBoundaryConditionsAndPreconditioner(const TreeType &, const DomainTreeType &, const BoundaryOp &, math::pcg::State &, Interrupter &)
Solve ∇2x = b for x with user-specified boundary conditions, where b is a vector comprising the val...
Definition: PoissonSolver.h:697
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::CopyToVecOp
CopyToVecOp(const SourceTreeType &t, VectorT &v)
Definition: PoissonSolver.h:380
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::VIdxLeafT
VIndexTreeType::LeafNodeType VIdxLeafT
Definition: PoissonSolver.h:439
NullInterrupter.h
openvdb::v3_2_0::tools::poisson::LaplacianMatrix
math::pcg::SparseStencilMatrix< double, 7 > LaplacianMatrix
The type of a matrix used to represent a three-dimensional Laplacian operator.
Definition: PoissonSolver.h:113
openvdb::v3_2_0::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v3_2_0::tools::erodeVoxels
OPENVDB_STATIC_SPECIALIZATION void erodeVoxels(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically erode all leaf-level active voxels in the given tree.
Definition: Morphology.h:872
openvdb::v3_2_0::TopologyCopy
Definition: Types.h:442
openvdb::v3_2_0::math::pcg::SparseStencilMatrix::RowEditor::setValue
SizeType setValue(SizeType column, const ValueType &value)
Set the value of the entry in the specified column.
Definition: ConjGradient.h:1265
openvdb::v3_2_0::tree::ValueAccessor::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:266
openvdb::v3_2_0::tools::poisson::VIndex
Int32 VIndex
Definition: PoissonSolver.h:110
openvdb::v3_2_0::tools::poisson::solve
TreeType::Ptr solve(const TreeType &, math::pcg::State &, Interrupter &)
Solve ∇2x = b for x, where b is a vector comprising the values of all of the active voxels in the i...
Definition: PoissonSolver.h:667
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::source
VectorT * source
Definition: PoissonSolver.h:511
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp
Functor for use with LeafManager::foreach() to populate a vector with the values of a tree&#39;s active v...
Definition: PoissonSolver.h:369
ConjGradient.h
Preconditioned conjugate gradient solver (solves Ax = b using the conjugate gradient method with one ...
openvdb::v3_2_0::tree::LeafManager
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:115
openvdb::v3_2_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
openvdb::v3_2_0::tools::poisson::internal::LeafCountOp::count
VIndex * count
Definition: PoissonSolver.h:282
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::CopyFromVecOp
CopyFromVecOp(const VectorT &v, OutTreeT &t)
Definition: PoissonSolver.h:445
openvdb::v3_2_0::tools::poisson::createISLaplacian
LaplacianMatrix::Ptr createISLaplacian(const typename BoolTreeType::template ValueConverter< VIndex >::Type &vectorIndexTree, const BoolTreeType &interiorMask)
Generate a sparse matrix of the index-space (Δx = 1) Laplacian operator using second-order finite di...
Definition: PoissonSolver.h:614
openvdb::v3_2_0::math::pcg::SparseStencilMatrix::ValueType
ValueType_ ValueType
Definition: ConjGradient.h:269
openvdb::v3_2_0::tools::poisson::createTreeFromVector
VIndexTreeType::template ValueConverter< TreeValueType >::Type::Ptr createTreeFromVector(const math::pcg::Vector< VectorValueType > &values, const VIndexTreeType &index, const TreeValueType &background)
Return a tree with the same active voxel topology as the index tree but whose voxel values are taken ...
Definition: PoissonSolver.h:463
openvdb::v3_2_0::math::pcg::State
Information about the state of a conjugate gradient solution.
Definition: ConjGradient.h:74
openvdb::v3_2_0::tools::poisson::internal::LeafIndexOp::LeafIndexOp
LeafIndexOp(const VIndex *count_)
Definition: PoissonSolver.h:296
Tree.h
openvdb::v3_2_0::tree::ValueAccessor
Definition: ValueAccessor.h:219
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::vector
VectorT * vector
Definition: PoissonSolver.h:378
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::idxTree
const VIdxTreeT * idxTree
Definition: PoissonSolver.h:508
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::VectorT
math::pcg::Vector< VectorValueType > VectorT
Definition: PoissonSolver.h:440
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::VectorT
math::pcg::Vector< ValueT > VectorT
Definition: PoissonSolver.h:505
openvdb::v3_2_0::tools::poisson::solveWithBoundaryConditions
TreeType::Ptr solveWithBoundaryConditions(const TreeType &, const BoundaryOp &, math::pcg::State &, Interrupter &)
Solve ∇2x = b for x with user-specified boundary conditions, where b is a vector comprising the val...
Definition: PoissonSolver.h:676
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::VIdxLeafT
VIdxTreeT::LeafNodeType VIdxLeafT
Definition: PoissonSolver.h:503
openvdb::v3_2_0::tools::poisson::createIndexTree
TreeType::template ValueConverter< VIndex >::Type::Ptr createIndexTree(const TreeType &)
Iterate over the active voxels of the input tree and for each one assign its index in the iteration s...
Definition: PoissonSolver.h:343
openvdb::v3_2_0::Int32
int32_t Int32
Definition: Types.h:60
openvdb::v3_2_0::Index64
uint64_t Index64
Definition: Types.h:57
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::laplacian
LaplacianMatrix * laplacian
Definition: PoissonSolver.h:507
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::tools::poisson::createISLaplacianWithBoundaryConditions
LaplacianMatrix::Ptr createISLaplacianWithBoundaryConditions(const typename BoolTreeType::template ValueConverter< VIndex >::Type &vectorIndexTree, const BoolTreeType &interiorMask, const BoundaryOp &boundaryOp, typename math::pcg::Vector< LaplacianMatrix::ValueType > &source)
Generate a sparse matrix of the index-space (Δx = 1) Laplacian operator with user-specified boundary...
Definition: PoissonSolver.h:627
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::ISLaplacianOp
ISLaplacianOp(LaplacianMatrix &m, const VIdxTreeT &idx, const BoolTreeType &mask, const BoundaryOp &op, VectorT &src)
Definition: PoissonSolver.h:513
openvdb::v3_2_0::math::pcg::JacobiPreconditioner
Diagonal preconditioner.
Definition: ConjGradient.h:70
openvdb::v3_2_0::tree::ValueAccessor::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
openvdb::v3_2_0::math::pcg::SparseStencilMatrix::getRowEditor
RowEditor getRowEditor(SizeType row)
Return a read/write view onto the given row of this matrix.
Definition: ConjGradient.h:1109
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::boundaryOp
const BoundaryOp boundaryOp
Definition: PoissonSolver.h:510
openvdb::v3_2_0::tools::laplacian
GridType::Ptr laplacian(const GridType &grid, bool threaded, InterruptT *interrupt)
Compute the Laplacian of the given scalar grid.
Definition: GridOperators.h:1016
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::TreeValueT
SourceTreeType::ValueType TreeValueT
Definition: PoissonSolver.h:374
Morphology.h
Implementation of morphological dilation and erosion.
openvdb::v3_2_0::math::Coord::offsetBy
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:111
openvdb::v3_2_0::math::pcg::Vector::at
T & at(SizeType i)
Return the value of this vector&#39;s ith element.
Definition: ConjGradient.h:229
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::tree::ValueAccessor::isValueOn
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:263
openvdb::v3_2_0::tools::poisson::internal::LeafIndexOp::count
const VIndex * count
Definition: PoissonSolver.h:295
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::operator()
void operator()(const VIdxLeafT &idxLeaf, size_t) const
Definition: PoissonSolver.h:382
openvdb::v3_2_0::math::pcg::SizeType
Index32 SizeType
Definition: ConjGradient.h:61
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::interiorMask
const BoolTreeType * interiorMask
Definition: PoissonSolver.h:509
openvdb::v3_2_0::tools::poisson::internal::LeafCountOp
Functor for use with LeafManager::foreach() to populate an array with per-leaf active voxel counts...
Definition: PoissonSolver.h:280
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::LeafT
SourceTreeType::LeafNodeType LeafT
Definition: PoissonSolver.h:373
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::ValueT
LaplacianMatrix::ValueType ValueT
Definition: PoissonSolver.h:504
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::operator()
void operator()(const VIdxLeafT &idxLeaf, size_t) const
Definition: PoissonSolver.h:447
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::tree
OutTreeT * tree
Definition: PoissonSolver.h:443
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::OutTreeT
VIndexTreeType::template ValueConverter< TreeValueType >::Type OutTreeT
Definition: PoissonSolver.h:437
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::VIdxTreeT
SourceTreeType::template ValueConverter< VIndex >::Type VIdxTreeT
Definition: PoissonSolver.h:371
openvdb::v3_2_0::math::pcg::Vector::Ptr
boost::shared_ptr< Vector > Ptr
Definition: ConjGradient.h:170
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::VIdxLeafT
VIdxTreeT::LeafNodeType VIdxLeafT
Definition: PoissonSolver.h:372
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::vector
const VectorT * vector
Definition: PoissonSolver.h:442
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::operator()
void operator()(const VIdxLeafT &idxLeaf, size_t) const
Definition: PoissonSolver.h:517
openvdb::v3_2_0::tools::poisson::populateIndexTree
void populateIndexTree(VIndexTreeType &)
Overwrite each active voxel in the given scalar tree with a sequential index, starting from zero...
Definition: PoissonSolver.h:310
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp
Functor for use with LeafManager::foreach() to populate a sparse Laplacian matrix.
Definition: PoissonSolver.h:500
openvdb::v3_2_0::math::pcg::SparseStencilMatrix
Sparse, square matrix representing a 3D stencil operator of size STENCIL_SIZE.
Definition: ConjGradient.h:67
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp
Functor for use with LeafManager::foreach() to populate a tree with values from a vector...
Definition: PoissonSolver.h:435
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tools::poisson::internal::DirichletOp
Constant boundary condition functor.
Definition: PoissonSolver.h:492
openvdb::v3_2_0::tools::poisson::internal::CopyFromVecOp::OutLeafT
OutTreeT::LeafNodeType OutLeafT
Definition: PoissonSolver.h:438
LeafManager.h
A LeafManager manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional au...
openvdb::v3_2_0::tools::poisson::internal::LeafIndexOp::operator()
void operator()(LeafType &leaf, size_t leafIdx) const
Definition: PoissonSolver.h:297
openvdb::v3_2_0::tools::poisson::internal::DirichletOp::operator()
void operator()(const Coord &, const Coord &, ValueType &, ValueType &diag) const
Definition: PoissonSolver.h:493
openvdb::v3_2_0::tools::poisson::createVectorFromTree
math::pcg::Vector< VectorValueType >::Ptr createVectorFromTree(const SourceTreeType &source, const typename SourceTreeType::template ValueConverter< VIndex >::Type &index)
Return a vector of the active voxel values of the scalar-valued source tree.
Definition: PoissonSolver.h:407
openvdb::v3_2_0::tools::poisson::internal::ISLaplacianOp::VIdxTreeT
BoolTreeType::template ValueConverter< VIndex >::Type VIdxTreeT
Definition: PoissonSolver.h:502
openvdb::v3_2_0::math::pcg::SparseStencilMatrix::RowEditor
Read/write accessor to a row of this matrix.
Definition: ConjGradient.h:448
openvdb::v3_2_0::tools::poisson::internal::LeafCountOp::LeafCountOp
LeafCountOp(VIndex *count_)
Definition: PoissonSolver.h:283
openvdb::v3_2_0::math::pcg::IncompleteCholeskyPreconditioner
Preconditioner using incomplete Cholesky factorization.
Definition: ConjGradient.h:71
openvdb::v3_2_0::tools::poisson::internal::CopyToVecOp::VectorT
math::pcg::Vector< VectorValueType > VectorT
Definition: PoissonSolver.h:375