Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorSebastián Barschkis <sebbas@sebbas.org>2020-10-06 19:17:20 +0300
committerSebastián Barschkis <sebbas@sebbas.org>2020-10-06 19:35:12 +0300
commita0ebfab4f3a31f08da651cf129982cbb419e0603 (patch)
treeb3a4dd58a0d09ccca9dcb61860243c8515bf8ae3 /extern
parent2b72860ff4473255ac73519e5a66c085c0c1fbe8 (diff)
Fluid: Updated Mantaflow source files
Among code cleanups, this update includes a new flood-fill helper function for levelsets.
Diffstat (limited to 'extern')
-rw-r--r--extern/mantaflow/helper/util/randomstream.h39
-rw-r--r--extern/mantaflow/preprocessed/fileio/iovdb.cpp2
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--extern/mantaflow/preprocessed/grid.h2
-rw-r--r--extern/mantaflow/preprocessed/levelset.cpp199
-rw-r--r--extern/mantaflow/preprocessed/levelset.h29
-rw-r--r--extern/mantaflow/preprocessed/levelset.h.reg.cpp2
-rw-r--r--extern/mantaflow/preprocessed/plugin/initplugins.cpp7
8 files changed, 265 insertions, 17 deletions
diff --git a/extern/mantaflow/helper/util/randomstream.h b/extern/mantaflow/helper/util/randomstream.h
index 6c20ddc6a14..5b477326f6f 100644
--- a/extern/mantaflow/helper/util/randomstream.h
+++ b/extern/mantaflow/helper/util/randomstream.h
@@ -377,19 +377,6 @@ class RandomStream {
}
/*! get a random number from the stream */
- inline double getDouble(void)
- {
- return mtr.rand();
- };
- inline float getFloat(void)
- {
- return (float)mtr.rand();
- };
-
- inline float getFloat(float min, float max)
- {
- return mtr.rand(max - min) + min;
- };
inline float getRandNorm(float mean, float var)
{
return mtr.randNorm(mean, var);
@@ -400,12 +387,20 @@ class RandomStream {
{
return getFloat();
}
+ inline Real getReal(float min, float max)
+ {
+ return getFloat(min, max);
+ }
#else
inline Real getReal()
{
return getDouble();
}
+ inline Real getReal(double min, double max)
+ {
+ return getDouble(min, max);
+ }
#endif
inline Vec3 getVec3()
@@ -422,6 +417,24 @@ class RandomStream {
private:
MTRand mtr;
+
+ inline double getDouble(void)
+ {
+ return mtr.rand();
+ };
+ inline float getFloat(void)
+ {
+ return (float)mtr.rand();
+ };
+
+ inline double getDouble(double min, double max)
+ {
+ return mtr.rand(max - min) + min;
+ };
+ inline float getFloat(float min, float max)
+ {
+ return (float)(mtr.rand(max - min) + min);
+ };
};
} // namespace Manta
diff --git a/extern/mantaflow/preprocessed/fileio/iovdb.cpp b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
index b31f7e0e760..b990274e1c4 100644
--- a/extern/mantaflow/preprocessed/fileio/iovdb.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
@@ -405,6 +405,7 @@ int writeObjectsVDB(const string &filename,
vdb_flags = openvdb::io::COMPRESS_NONE;
break;
}
+ default:
case COMPRESSION_ZIP: {
vdb_flags |= openvdb::io::COMPRESS_ZIP;
break;
@@ -445,6 +446,7 @@ int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, floa
(void)metadata; // Unused for now
}
catch (const openvdb::IoError &e) {
+ (void)e; // Unused for now
debMsg("readObjectsVDB: Could not open vdb file " << filename, 1);
file.close();
return 0;
diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h
index e87c8739cf4..64367e0e096 100644
--- a/extern/mantaflow/preprocessed/gitinfo.h
+++ b/extern/mantaflow/preprocessed/gitinfo.h
@@ -1,3 +1,3 @@
-#define MANTA_GIT_VERSION "commit e2f6e59e3679f88e5100ae2145410cca4971b9df"
+#define MANTA_GIT_VERSION "commit b8e557707805720ff00a8eb946db2ee5b9361b5a"
diff --git a/extern/mantaflow/preprocessed/grid.h b/extern/mantaflow/preprocessed/grid.h
index 9bd4e5d72d9..ec70cc953ff 100644
--- a/extern/mantaflow/preprocessed/grid.h
+++ b/extern/mantaflow/preprocessed/grid.h
@@ -355,7 +355,6 @@ class GridBase : public PbClass {
return isInBounds(Vec3i(i, j, k), bnd);
}
-#ifdef BLENDER
//! expose name field to Python for Blender
void setName(const std::string &name)
{
@@ -386,7 +385,6 @@ class GridBase : public PbClass {
}
}
-#endif
protected:
GridType mType;
Vec3i mSize;
diff --git a/extern/mantaflow/preprocessed/levelset.cpp b/extern/mantaflow/preprocessed/levelset.cpp
index a6f9fb40f3f..122f71917eb 100644
--- a/extern/mantaflow/preprocessed/levelset.cpp
+++ b/extern/mantaflow/preprocessed/levelset.cpp
@@ -639,8 +639,207 @@ void LevelsetGrid::initFromFlags(const FlagGrid &flags, bool ignoreWalls)
}
}
+/* Helper variables that are used in flood-fill functions. */
+static const int ID_UNKNOWN = 0;
+static const int ID_VISITED = 1;
+
+/* Fills all cells in the target grid that have not been marked during a flood-fill. */
+
+struct KnFillApply : public KernelBase {
+ KnFillApply(Grid<Real> &target,
+ Grid<int> &visited,
+ const Real value,
+ const int boundaryWidth,
+ const bool outside)
+ : KernelBase(&target, boundaryWidth),
+ target(target),
+ visited(visited),
+ value(value),
+ boundaryWidth(boundaryWidth),
+ outside(outside)
+ {
+ runMessage();
+ run();
+ }
+ inline void op(int i,
+ int j,
+ int k,
+ Grid<Real> &target,
+ Grid<int> &visited,
+ const Real value,
+ const int boundaryWidth,
+ const bool outside) const
+ {
+
+ if (visited(i, j, k) == ID_VISITED)
+ return;
+ if (outside && target(i, j, k) < 0)
+ return;
+ if (!outside && target(i, j, k) >= 0)
+ return;
+
+ /* Actual flood-fill override. */
+ target(i, j, k) = value;
+ }
+ inline Grid<Real> &getArg0()
+ {
+ return target;
+ }
+ typedef Grid<Real> type0;
+ inline Grid<int> &getArg1()
+ {
+ return visited;
+ }
+ typedef Grid<int> type1;
+ inline const Real &getArg2()
+ {
+ return value;
+ }
+ typedef Real type2;
+ inline const int &getArg3()
+ {
+ return boundaryWidth;
+ }
+ typedef int type3;
+ inline const bool &getArg4()
+ {
+ return outside;
+ }
+ typedef bool type4;
+ void runMessage()
+ {
+ debMsg("Executing kernel KnFillApply ", 3);
+ debMsg("Kernel range"
+ << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
+ 4);
+ };
+ void operator()(const tbb::blocked_range<IndexInt> &__r) const
+ {
+ const int _maxX = maxX;
+ const int _maxY = maxY;
+ if (maxZ > 1) {
+ for (int k = __r.begin(); k != (int)__r.end(); k++)
+ for (int j = boundaryWidth; j < _maxY; j++)
+ for (int i = boundaryWidth; i < _maxX; i++)
+ op(i, j, k, target, visited, value, boundaryWidth, outside);
+ }
+ else {
+ const int k = 0;
+ for (int j = __r.begin(); j != (int)__r.end(); j++)
+ for (int i = boundaryWidth; i < _maxX; i++)
+ op(i, j, k, target, visited, value, boundaryWidth, outside);
+ }
+ }
+ void run()
+ {
+ if (maxZ > 1)
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
+ else
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(boundaryWidth, maxY), *this);
+ }
+ Grid<Real> &target;
+ Grid<int> &visited;
+ const Real value;
+ const int boundaryWidth;
+ const bool outside;
+};
+
+/* Basic flood fill implementation used to fill inside / outside areas of levelset.
+ * Calling this function will ensure that there are no fluid cells inside obstacles.
+ * I.e. starting from walls, cells will be tagged in flood-fill fashion, stopping at 0 borders.
+ * All remaining cells will be filled with the fill value. Outside mode inverts search behavior. */
+void LevelsetGrid::floodFill(const Real value, const bool outside, const int boundaryWidth)
+{
+
+ /* Sanity check: Filling mode and filling value need to "match". */
+ if (outside) {
+ assertMsg(value < 0, "Cannot fill outside with (positive) value " << value);
+ }
+ else {
+ assertMsg(value >= 0, "Cannot fill inside with (negative) value " << value);
+ }
+
+ Grid<Real> levelsetCopy(this->getParent());
+ Grid<int> visited(this->getParent());
+ std::stack<Vec3i> todoPos;
+
+ const int maxNeighbors = this->is3D() ? 6 : 4;
+ const Vec3i maxSize(this->getSize() - 1);
+
+ Vec3i bnd(2 * boundaryWidth);
+ if (!this->is3D())
+ bnd.z = 0;
+ const int cellCntNoBnd = (this->getSizeX() - bnd.x) * (this->getSizeY() - bnd.y) *
+ (this->getSizeZ() - bnd.z);
+
+ /* Initialize temporary helper grids. */
+ levelsetCopy.copyFrom(*this);
+ visited.setConst(ID_UNKNOWN);
+
+ FOR_IJK_BND(visited, boundaryWidth)
+ {
+
+ /* Skip inside / outside cells depending on search mode. */
+ if (outside && levelsetCopy(i, j, k) < 0)
+ continue;
+ if (!outside && levelsetCopy(i, j, k) >= 0)
+ continue;
+ /* Skip cell if it already has been visited. */
+ if (visited(i, j, k) == ID_VISITED)
+ continue;
+
+ Vec3i c(i, j, k);
+
+ bool isWallCell = (c.x - boundaryWidth == 0 || c.x == maxSize.x - boundaryWidth);
+ isWallCell |= (c.y - boundaryWidth == 0 || c.y == maxSize.y - boundaryWidth);
+ if (this->is3D())
+ isWallCell |= (c.z - boundaryWidth == 0 || c.z == maxSize.z - boundaryWidth);
+
+ /* Only start searching from borders. */
+ if (!isWallCell)
+ continue;
+
+ /* Start flood-fill loop by initializing todo stack with current cell. */
+ todoPos.push(c);
+ visited(c) = ID_VISITED;
+
+ while (!todoPos.empty()) {
+ c = todoPos.top();
+ todoPos.pop();
+
+ /* Add all neighbor cells to search stack. */
+ for (int nb = 0; nb < maxNeighbors; nb++) {
+ const Vec3i neigh(c + neighbors[nb]);
+
+ if (!visited.isInBounds(neigh, boundaryWidth))
+ continue;
+ /* Skip inside / outside area depening on what we search for. */
+ if (outside && levelsetCopy(neigh) < 0)
+ continue;
+ if (!outside && levelsetCopy(neigh) >= 0)
+ continue;
+ /* Skip neighbor if it already has been visited. */
+ if (visited(neigh) == ID_VISITED)
+ continue;
+
+ assertMsg(visited(neigh) == ID_UNKNOWN,
+ "Cell must be of type 'unknown' at this point in the loop");
+ todoPos.push(neigh);
+ visited(neigh) = ID_VISITED;
+ }
+ assertMsg(todoPos.size() <= cellCntNoBnd,
+ "Flood-fill todo stack cannot be greater than domain cell count - "
+ << todoPos.size() << " vs " << cellCntNoBnd);
+ }
+ }
+ KnFillApply(*this, visited, value, boundaryWidth, outside);
+}
+
+/* Deprecated: Use floodFill() function instead. */
void LevelsetGrid::fillHoles(int maxDepth, int boundaryWidth)
{
+ debMsg("Deprecated - do not use fillHoles() ... use floodFill() instead", 1);
+
Real curVal, i1, i2, j1, j2, k1, k2;
Vec3i c, cTmp;
std::stack<Vec3i> undoPos;
diff --git a/extern/mantaflow/preprocessed/levelset.h b/extern/mantaflow/preprocessed/levelset.h
index ab36ac24903..ff47cf7c8d2 100644
--- a/extern/mantaflow/preprocessed/levelset.h
+++ b/extern/mantaflow/preprocessed/levelset.h
@@ -234,6 +234,35 @@ class LevelsetGrid : public Grid<Real> {
}
}
+ //! flood-fill the levelset to ensure that closed obstacles are filled inside
+ void floodFill(const Real value = -0.5, const bool outside = true, const int boundaryWidth = 1);
+ static PyObject *_W_7(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+ {
+ try {
+ PbArgs _args(_linargs, _kwds);
+ LevelsetGrid *pbo = dynamic_cast<LevelsetGrid *>(Pb::objFromPy(_self));
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(pbo->getParent(), "LevelsetGrid::floodFill", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ const Real value = _args.getOpt<Real>("value", 0, -0.5, &_lock);
+ const bool outside = _args.getOpt<bool>("outside", 1, true, &_lock);
+ const int boundaryWidth = _args.getOpt<int>("boundaryWidth", 2, 1, &_lock);
+ pbo->_args.copy(_args);
+ _retval = getPyNone();
+ pbo->floodFill(value, outside, boundaryWidth);
+ pbo->_args.check();
+ }
+ pbFinalizePlugin(pbo->getParent(), "LevelsetGrid::floodFill", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("LevelsetGrid::floodFill", e.what());
+ return 0;
+ }
+ }
+
static Real invalidTimeValue();
public:
PbArgs _args;
diff --git a/extern/mantaflow/preprocessed/levelset.h.reg.cpp b/extern/mantaflow/preprocessed/levelset.h.reg.cpp
index dc6669b5da3..f780e0933f9 100644
--- a/extern/mantaflow/preprocessed/levelset.h.reg.cpp
+++ b/extern/mantaflow/preprocessed/levelset.h.reg.cpp
@@ -15,6 +15,7 @@ static const Pb::Register _R_15("LevelsetGrid", "join", LevelsetGrid::_W_3);
static const Pb::Register _R_16("LevelsetGrid", "subtract", LevelsetGrid::_W_4);
static const Pb::Register _R_17("LevelsetGrid", "initFromFlags", LevelsetGrid::_W_5);
static const Pb::Register _R_18("LevelsetGrid", "fillHoles", LevelsetGrid::_W_6);
+static const Pb::Register _R_19("LevelsetGrid", "floodFill", LevelsetGrid::_W_7);
#endif
extern "C" {
void PbRegister_file_11()
@@ -27,6 +28,7 @@ void PbRegister_file_11()
KEEP_UNUSED(_R_16);
KEEP_UNUSED(_R_17);
KEEP_UNUSED(_R_18);
+ KEEP_UNUSED(_R_19);
}
}
} // namespace Manta \ No newline at end of file
diff --git a/extern/mantaflow/preprocessed/plugin/initplugins.cpp b/extern/mantaflow/preprocessed/plugin/initplugins.cpp
index 6ccd3afc8d1..6e8a3580d93 100644
--- a/extern/mantaflow/preprocessed/plugin/initplugins.cpp
+++ b/extern/mantaflow/preprocessed/plugin/initplugins.cpp
@@ -695,7 +695,12 @@ struct KnApplyEmission : public KernelBase {
// (important for emit from particles)
bool isInflow = (type & FlagGrid::TypeInflow && flags.isInflow(i, j, k));
bool isOutflow = (type & FlagGrid::TypeOutflow && flags.isOutflow(i, j, k));
- if ((type && !isInflow && !isOutflow) && (emissionTexture && !(*emissionTexture)(i, j, k)))
+
+ if (type && !isInflow)
+ return;
+ if (type && isOutflow)
+ return;
+ if (emissionTexture && !(*emissionTexture)(i, j, k))
return;
if (isAbsolute)