Fluid: Updated Mantaflow source files
This update introduces two improvements from the Mantaflow repository: (1) Improved particle sampling: - Liquid and secondary particles are sampled more predictably. With all parameters being equal, baked particles will be computed at the exact same position during every bake. - Before, this was not guaranteed. (2) Sparse grid caching: - While saving grid data to disk, grids will from now on be saved in a sparse structure whenever possible (e.g. density, flame but not levelsets). - With the sparse optimization grid cells with a value under the 'Empty Space' value (already present in domain settings) will not be cached. - The main benefits of this optimization are: Smaller cache sizes and faster playback of simulation data in the viewport. - This optimization works 'out-of-the-box'. There is no option in the UI to enable it. - For now, only smoke simulation grids will take advantage of this optimization.
This commit is contained in:
parent
f7223d5f72
commit
e09d0c0d07
118
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
118
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
@ -31,6 +31,8 @@
|
||||
# include "openvdb/openvdb.h"
|
||||
# include <openvdb/points/PointConversion.h>
|
||||
# include <openvdb/points/PointCount.h>
|
||||
# include <openvdb/tools/Clip.h>
|
||||
# include <openvdb/tools/Dense.h>
|
||||
#endif
|
||||
|
||||
#define POSITION_NAME "P"
|
||||
@ -45,15 +47,29 @@ namespace Manta {
|
||||
template<class GridType, class T> void importVDB(typename GridType::Ptr from, Grid<T> *to)
|
||||
{
|
||||
using ValueT = typename GridType::ValueType;
|
||||
typename GridType::Accessor accessor = from->getAccessor();
|
||||
|
||||
FOR_IJK(*to)
|
||||
{
|
||||
openvdb::Coord xyz(i, j, k);
|
||||
ValueT vdbValue = accessor.getValue(xyz);
|
||||
T toMantaValue;
|
||||
convertFrom(vdbValue, &toMantaValue);
|
||||
to->set(i, j, k, toMantaValue);
|
||||
// Check if current grid is to be read as a sparse grid, active voxels (only) will be copied
|
||||
if (to->saveSparse()) {
|
||||
to->clear(); // Ensure that destination grid is empty before writing
|
||||
for (typename GridType::ValueOnCIter iter = from->cbeginValueOn(); iter.test(); ++iter) {
|
||||
ValueT vdbValue = *iter;
|
||||
openvdb::Coord coord = iter.getCoord();
|
||||
T toMantaValue;
|
||||
convertFrom(vdbValue, &toMantaValue);
|
||||
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
|
||||
}
|
||||
}
|
||||
// When importing all grid cells, using a grid accessor is usually faster than a value iterator
|
||||
else {
|
||||
typename GridType::Accessor accessor = from->getAccessor();
|
||||
FOR_IJK(*to)
|
||||
{
|
||||
openvdb::Coord xyz(i, j, k);
|
||||
ValueT vdbValue = accessor.getValue(xyz);
|
||||
T toMantaValue;
|
||||
convertFrom(vdbValue, &toMantaValue);
|
||||
to->set(i, j, k, toMantaValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,19 +189,43 @@ static void setGridOptions(typename GridType::Ptr grid,
|
||||
grid->setSaveFloatAsHalf(precision == PRECISION_MINI || precision == PRECISION_HALF);
|
||||
}
|
||||
|
||||
template<class T, class GridType> typename GridType::Ptr exportVDB(Grid<T> *from)
|
||||
template<class T, class GridType>
|
||||
typename GridType::Ptr exportVDB(Grid<T> *from, float clip, openvdb::FloatGrid::Ptr clipGrid)
|
||||
{
|
||||
using ValueT = typename GridType::ValueType;
|
||||
typename GridType::Ptr to = GridType::create();
|
||||
typename GridType::Accessor accessor = to->getAccessor();
|
||||
typename GridType::Ptr to = GridType::create(ValueT(0));
|
||||
|
||||
FOR_IJK(*from)
|
||||
{
|
||||
openvdb::Coord xyz(i, j, k);
|
||||
T fromMantaValue = (*from)(i, j, k);
|
||||
ValueT vdbValue;
|
||||
convertTo(&vdbValue, fromMantaValue);
|
||||
accessor.setValue(xyz, vdbValue);
|
||||
// Copy data from grid by creating a vdb dense structure and then copying that into a vdb grid
|
||||
// This is the fastest way to copy data for both dense and sparse grids -> if (true)
|
||||
if (true) {
|
||||
ValueT *data = (ValueT *)from->getData();
|
||||
openvdb::math::CoordBBox bbox(
|
||||
openvdb::Coord(0),
|
||||
openvdb::Coord(from->getSizeX() - 1, from->getSizeY() - 1, from->getSizeZ() - 1));
|
||||
openvdb::tools::Dense<ValueT, openvdb::tools::MemoryLayout::LayoutXYZ> dense(bbox, data);
|
||||
|
||||
// Trick: Set clip value to very small / negative value in order to copy all values of dense
|
||||
// grids
|
||||
float tmpClip = (from->saveSparse()) ? clip : -std::numeric_limits<Real>::max();
|
||||
// Copy from dense to sparse grid structure considering clip value
|
||||
openvdb::tools::copyFromDense(dense, *to, ValueT(tmpClip));
|
||||
|
||||
// If present, use clip grid to trim down current vdb grid even more
|
||||
if (from->saveSparse() && clipGrid && !clipGrid->empty()) {
|
||||
to = openvdb::tools::clip(*to, *clipGrid);
|
||||
}
|
||||
}
|
||||
// Alternatively, reading all grid cells with an accessor (slightly slower) is possible like this
|
||||
else {
|
||||
typename GridType::Accessor accessor = to->getAccessor();
|
||||
FOR_IJK(*from)
|
||||
{
|
||||
openvdb::Coord xyz(i, j, k);
|
||||
T fromMantaValue = (*from)(i, j, k);
|
||||
ValueT vdbValue;
|
||||
convertTo(&vdbValue, fromMantaValue);
|
||||
accessor.setValue(xyz, vdbValue);
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
@ -346,7 +386,9 @@ int writeObjectsVDB(const string &filename,
|
||||
float worldSize,
|
||||
bool skipDeletedParts,
|
||||
int compression,
|
||||
int precision)
|
||||
int precision,
|
||||
float clip,
|
||||
const Grid<Real> *clipGrid)
|
||||
{
|
||||
openvdb::initialize();
|
||||
openvdb::io::File file(filename);
|
||||
@ -357,6 +399,19 @@ int writeObjectsVDB(const string &filename,
|
||||
|
||||
std::vector<ParticleDataBase *> pdbBuffer;
|
||||
|
||||
// Convert given clip grid to vdb clip grid
|
||||
openvdb::FloatGrid::Ptr vdbClipGrid = nullptr;
|
||||
if (clipGrid) {
|
||||
vdbClipGrid = openvdb::FloatGrid::create();
|
||||
Real *data = (Real *)clipGrid->getData();
|
||||
openvdb::math::CoordBBox bbox(openvdb::Coord(0),
|
||||
openvdb::Coord(clipGrid->getSizeX() - 1,
|
||||
clipGrid->getSizeY() - 1,
|
||||
clipGrid->getSizeZ() - 1));
|
||||
openvdb::tools::Dense<float, openvdb::tools::MemoryLayout::LayoutXYZ> dense(bbox, data);
|
||||
openvdb::tools::copyFromDense(dense, *vdbClipGrid, clip);
|
||||
}
|
||||
|
||||
for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
|
||||
openvdb::GridClass gClass = openvdb::GRID_UNKNOWN;
|
||||
openvdb::GridBase::Ptr vdbGrid;
|
||||
@ -368,10 +423,14 @@ int writeObjectsVDB(const string &filename,
|
||||
|
||||
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
|
||||
|
||||
if (clipGrid) {
|
||||
assertMsg(clipGrid->getSize() == mantaGrid->getSize(),
|
||||
"writeObjectsVDB: Clip grid and exported grid must have the same size");
|
||||
}
|
||||
if (mantaGrid->getType() & GridBase::TypeInt) {
|
||||
debMsg("Writing int grid '" << mantaGrid->getName() << "' to vdb file " << filename, 1);
|
||||
Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
|
||||
vdbGrid = exportVDB<int, openvdb::Int32Grid>(mantaIntGrid);
|
||||
vdbGrid = exportVDB<int, openvdb::Int32Grid>(mantaIntGrid, clip, vdbClipGrid);
|
||||
gridsVDB.push_back(vdbGrid);
|
||||
}
|
||||
else if (mantaGrid->getType() & GridBase::TypeReal) {
|
||||
@ -379,7 +438,9 @@ int writeObjectsVDB(const string &filename,
|
||||
gClass = (mantaGrid->getType() & GridBase::TypeLevelset) ? openvdb::GRID_LEVEL_SET :
|
||||
openvdb::GRID_FOG_VOLUME;
|
||||
Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
|
||||
vdbGrid = exportVDB<Real, openvdb::FloatGrid>(mantaRealGrid);
|
||||
// Only supply clip grid if real grid is not equal to the clip grid
|
||||
openvdb::FloatGrid::Ptr tmpClipGrid = (mantaRealGrid == clipGrid) ? nullptr : vdbClipGrid;
|
||||
vdbGrid = exportVDB<Real, openvdb::FloatGrid>(mantaRealGrid, clip, tmpClipGrid);
|
||||
gridsVDB.push_back(vdbGrid);
|
||||
}
|
||||
else if (mantaGrid->getType() & GridBase::TypeVec3) {
|
||||
@ -387,7 +448,7 @@ int writeObjectsVDB(const string &filename,
|
||||
gClass = (mantaGrid->getType() & GridBase::TypeMAC) ? openvdb::GRID_STAGGERED :
|
||||
openvdb::GRID_UNKNOWN;
|
||||
Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
|
||||
vdbGrid = exportVDB<Vec3, openvdb::Vec3SGrid>(mantaVec3Grid);
|
||||
vdbGrid = exportVDB<Vec3, openvdb::Vec3SGrid>(mantaVec3Grid, clip, vdbClipGrid);
|
||||
gridsVDB.push_back(vdbGrid);
|
||||
}
|
||||
else {
|
||||
@ -620,9 +681,12 @@ template void importVDB<openvdb::Int32Grid, int>(openvdb::Int32Grid::Ptr from, G
|
||||
template void importVDB<openvdb::FloatGrid, Real>(openvdb::FloatGrid::Ptr from, Grid<Real> *to);
|
||||
template void importVDB<openvdb::Vec3SGrid, Vec3>(openvdb::Vec3SGrid::Ptr from, Grid<Vec3> *to);
|
||||
|
||||
template openvdb::Int32Grid::Ptr exportVDB<int, openvdb::Int32Grid>(Grid<int> *from);
|
||||
template openvdb::FloatGrid::Ptr exportVDB<Real, openvdb::FloatGrid>(Grid<Real> *from);
|
||||
template openvdb::Vec3SGrid::Ptr exportVDB<Vec3, openvdb::Vec3SGrid>(Grid<Vec3> *from);
|
||||
template openvdb::Int32Grid::Ptr exportVDB<int, openvdb::Int32Grid>(
|
||||
Grid<int> *from, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
|
||||
template openvdb::FloatGrid::Ptr exportVDB<Real, openvdb::FloatGrid>(
|
||||
Grid<Real> *from, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
|
||||
template openvdb::Vec3SGrid::Ptr exportVDB<Vec3, openvdb::Vec3SGrid>(
|
||||
Grid<Vec3> *from, float clip = 1e-4, openvdb::FloatGrid::Ptr clipGrid = nullptr);
|
||||
|
||||
openvdb::points::PointDataGrid::Ptr exportVDB(BasicParticleSystem *from,
|
||||
std::vector<ParticleDataBase *> &fromPData,
|
||||
@ -652,7 +716,9 @@ int writeObjectsVDB(const string &filename,
|
||||
float worldSize,
|
||||
bool skipDeletedParts,
|
||||
int compression,
|
||||
int precision)
|
||||
int precision,
|
||||
float clip,
|
||||
const Grid<Real> *clipGrid)
|
||||
{
|
||||
errMsg("Cannot save to .vdb file. Mantaflow has not been built with OpenVDB support.");
|
||||
return 0;
|
||||
|
20
extern/mantaflow/preprocessed/fileio/mantaio.cpp
vendored
20
extern/mantaflow/preprocessed/fileio/mantaio.cpp
vendored
@ -83,7 +83,9 @@ int save(const string &name,
|
||||
bool skipDeletedParts = false,
|
||||
int compression = COMPRESSION_ZIP,
|
||||
bool precisionHalf = true,
|
||||
int precision = PRECISION_HALF)
|
||||
int precision = PRECISION_HALF,
|
||||
float clip = 1e-4,
|
||||
const Grid<Real> *clipGrid = nullptr)
|
||||
{
|
||||
|
||||
if (!precisionHalf) {
|
||||
@ -102,7 +104,8 @@ int save(const string &name,
|
||||
else if (ext == ".vol")
|
||||
return writeGridsVol(name, &objects);
|
||||
if (ext == ".vdb")
|
||||
return writeObjectsVDB(name, &objects, worldSize, skipDeletedParts, compression, precision);
|
||||
return writeObjectsVDB(
|
||||
name, &objects, worldSize, skipDeletedParts, compression, precision, clip, clipGrid);
|
||||
else if (ext == ".npz")
|
||||
return writeGridsNumpy(name, &objects);
|
||||
else if (ext == ".txt")
|
||||
@ -129,8 +132,17 @@ static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
int compression = _args.getOpt<int>("compression", 4, COMPRESSION_ZIP, &_lock);
|
||||
bool precisionHalf = _args.getOpt<bool>("precisionHalf", 5, true, &_lock);
|
||||
int precision = _args.getOpt<int>("precision", 6, PRECISION_HALF, &_lock);
|
||||
_retval = toPy(
|
||||
save(name, objects, worldSize, skipDeletedParts, compression, precisionHalf, precision));
|
||||
float clip = _args.getOpt<float>("clip", 7, 1e-4, &_lock);
|
||||
const Grid<Real> *clipGrid = _args.getPtrOpt<Grid<Real>>("clipGrid", 8, nullptr, &_lock);
|
||||
_retval = toPy(save(name,
|
||||
objects,
|
||||
worldSize,
|
||||
skipDeletedParts,
|
||||
compression,
|
||||
precisionHalf,
|
||||
precision,
|
||||
clip,
|
||||
clipGrid));
|
||||
_args.check();
|
||||
}
|
||||
pbFinalizePlugin(parent, "save", !noTiming);
|
||||
|
@ -75,7 +75,9 @@ int writeObjectsVDB(const std::string &filename,
|
||||
float scale = 1.0,
|
||||
bool skipDeletedParts = false,
|
||||
int compression = COMPRESSION_ZIP,
|
||||
int precision = PRECISION_HALF);
|
||||
int precision = PRECISION_HALF,
|
||||
float clip = 1e-4,
|
||||
const Grid<Real> *clipGrid = nullptr);
|
||||
int readObjectsVDB(const std::string &filename,
|
||||
std::vector<PbClass *> *objects,
|
||||
float scale = 1.0);
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit 73990a8a5b876e2b136a646258f714c08c5828da"
|
||||
#define MANTA_GIT_VERSION "commit bb7cde47b6e04fa62815c70775dc70f02065599f"
|
||||
|
29
extern/mantaflow/preprocessed/grid.cpp
vendored
29
extern/mantaflow/preprocessed/grid.cpp
vendored
@ -60,7 +60,7 @@ template<> inline GridBase::GridType typeList<Vec3>()
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Grid<T>::Grid(FluidSolver *parent, bool show) : GridBase(parent), externalData(false)
|
||||
Grid<T>::Grid(FluidSolver *parent, bool show, bool sparse) : GridBase(parent), mExternalData(false)
|
||||
{
|
||||
mType = typeList<T>();
|
||||
mSize = parent->getGridSize();
|
||||
@ -70,22 +70,23 @@ Grid<T>::Grid(FluidSolver *parent, bool show) : GridBase(parent), externalData(f
|
||||
mDx = 1.0 / mSize.max();
|
||||
clear();
|
||||
setHidden(!show);
|
||||
|
||||
#if OPENVDB == 1
|
||||
mSaveSparse = sparse;
|
||||
#else
|
||||
if (sparse)
|
||||
debMsg("Cannot enable sparse save option without OpenVDB", 1);
|
||||
mSaveSparse = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Grid<T>::Grid(FluidSolver *parent, T *data, bool show)
|
||||
: GridBase(parent), mData(data), externalData(true)
|
||||
Grid<T>::Grid(FluidSolver *parent, T *data, bool show) : Grid<T>::Grid(parent, show)
|
||||
{
|
||||
mType = typeList<T>();
|
||||
mSize = parent->getGridSize();
|
||||
|
||||
mStrideZ = parent->is2D() ? 0 : (mSize.x * mSize.y);
|
||||
mDx = 1.0 / mSize.max();
|
||||
|
||||
setHidden(!show);
|
||||
mData = data;
|
||||
}
|
||||
|
||||
template<class T> Grid<T>::Grid(const Grid<T> &a) : GridBase(a.getParent()), externalData(false)
|
||||
template<class T> Grid<T>::Grid(const Grid<T> &a) : GridBase(a.getParent()), mExternalData(false)
|
||||
{
|
||||
mSize = a.mSize;
|
||||
mType = a.mType;
|
||||
@ -98,7 +99,7 @@ template<class T> Grid<T>::Grid(const Grid<T> &a) : GridBase(a.getParent()), ext
|
||||
|
||||
template<class T> Grid<T>::~Grid()
|
||||
{
|
||||
if (!externalData) {
|
||||
if (!mExternalData) {
|
||||
mParent->freeGridPointer<T>(mData);
|
||||
}
|
||||
}
|
||||
@ -114,8 +115,8 @@ template<class T> void Grid<T>::swap(Grid<T> &other)
|
||||
other.getSizeZ() != getSizeZ())
|
||||
errMsg("Grid::swap(): Grid dimensions mismatch.");
|
||||
|
||||
if (externalData || other.externalData)
|
||||
errMsg("Grid::swap(): Cannot swap if one grid stores externalData.");
|
||||
if (mExternalData || other.mExternalData)
|
||||
errMsg("Grid::swap(): Cannot swap if one grid stores mExternalData.");
|
||||
|
||||
T *dswap = other.mData;
|
||||
other.mData = mData;
|
||||
|
30
extern/mantaflow/preprocessed/grid.h
vendored
30
extern/mantaflow/preprocessed/grid.h
vendored
@ -402,7 +402,7 @@ class GridBase : public PbClass {
|
||||
template<class T> class Grid : public GridBase {
|
||||
public:
|
||||
//! init new grid, values are set to zero
|
||||
Grid(FluidSolver *parent, bool show = true);
|
||||
Grid(FluidSolver *parent, bool show = true, bool sparse = false);
|
||||
static int _W_10(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
{
|
||||
PbClass *obj = Pb::objFromPy(_self);
|
||||
@ -416,7 +416,8 @@ template<class T> class Grid : public GridBase {
|
||||
ArgLocker _lock;
|
||||
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
|
||||
bool show = _args.getOpt<bool>("show", 1, true, &_lock);
|
||||
obj = new Grid(parent, show);
|
||||
bool sparse = _args.getOpt<bool>("sparse", 2, false, &_lock);
|
||||
obj = new Grid(parent, show, sparse);
|
||||
obj->registerObject(_self, &_args);
|
||||
_args.check();
|
||||
}
|
||||
@ -581,6 +582,16 @@ template<class T> class Grid : public GridBase {
|
||||
DEBUG_ONLY(checkIndex(idx));
|
||||
return mData[idx];
|
||||
}
|
||||
//! raw data access
|
||||
inline T *getData() const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
//! query if this grid should be saved as a sparse grid
|
||||
inline bool saveSparse()
|
||||
{
|
||||
return mSaveSparse;
|
||||
}
|
||||
|
||||
//! set data
|
||||
inline void set(int i, int j, int k, T &val)
|
||||
@ -1290,7 +1301,8 @@ template<class T> class Grid : public GridBase {
|
||||
|
||||
protected:
|
||||
T *mData;
|
||||
bool externalData; // True if mData is managed outside of the Fluidsolver
|
||||
bool mExternalData; // True if mData is managed outside of the Fluidsolver
|
||||
bool mSaveSparse; // True if this grid may be cached in a sparse structure
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@ -1302,7 +1314,8 @@ template<class T> class Grid : public GridBase {
|
||||
//! Special function for staggered grids
|
||||
class MACGrid : public Grid<Vec3> {
|
||||
public:
|
||||
MACGrid(FluidSolver *parent, bool show = true) : Grid<Vec3>(parent, show)
|
||||
MACGrid(FluidSolver *parent, bool show = true, bool sparse = false)
|
||||
: Grid<Vec3>(parent, show, sparse)
|
||||
{
|
||||
mType = (GridType)(TypeMAC | TypeVec3);
|
||||
}
|
||||
@ -1319,7 +1332,8 @@ class MACGrid : public Grid<Vec3> {
|
||||
ArgLocker _lock;
|
||||
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
|
||||
bool show = _args.getOpt<bool>("show", 1, true, &_lock);
|
||||
obj = new MACGrid(parent, show);
|
||||
bool sparse = _args.getOpt<bool>("sparse", 2, false, &_lock);
|
||||
obj = new MACGrid(parent, show, sparse);
|
||||
obj->registerObject(_self, &_args);
|
||||
_args.check();
|
||||
}
|
||||
@ -1425,7 +1439,8 @@ class MACGrid : public Grid<Vec3> {
|
||||
//! Special functions for FlagGrid
|
||||
class FlagGrid : public Grid<int> {
|
||||
public:
|
||||
FlagGrid(FluidSolver *parent, int dim = 3, bool show = true) : Grid<int>(parent, show)
|
||||
FlagGrid(FluidSolver *parent, int dim = 3, bool show = true, bool sparse = false)
|
||||
: Grid<int>(parent, show, sparse)
|
||||
{
|
||||
mType = (GridType)(TypeFlags | TypeInt);
|
||||
}
|
||||
@ -1443,7 +1458,8 @@ class FlagGrid : public Grid<int> {
|
||||
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
|
||||
int dim = _args.getOpt<int>("dim", 1, 3, &_lock);
|
||||
bool show = _args.getOpt<bool>("show", 2, true, &_lock);
|
||||
obj = new FlagGrid(parent, dim, show);
|
||||
bool sparse = _args.getOpt<bool>("sparse", 3, false, &_lock);
|
||||
obj = new FlagGrid(parent, dim, show, sparse);
|
||||
obj->registerObject(_self, &_args);
|
||||
_args.check();
|
||||
}
|
||||
|
10
extern/mantaflow/preprocessed/particle.cpp
vendored
10
extern/mantaflow/preprocessed/particle.cpp
vendored
@ -28,9 +28,15 @@
|
||||
using namespace std;
|
||||
namespace Manta {
|
||||
|
||||
ParticleBase::ParticleBase(FluidSolver *parent)
|
||||
: PbClass(parent), mMaxParticles(0), mAllowCompress(true), mFreePdata(false)
|
||||
int ParticleBase::globalSeed = 9832;
|
||||
|
||||
ParticleBase::ParticleBase(FluidSolver *parent, int fixedSeed)
|
||||
: PbClass(parent), mMaxParticles(0), mAllowCompress(true), mFreePdata(false), mSeed(fixedSeed)
|
||||
{
|
||||
// use global random seed if none is given
|
||||
if (fixedSeed == -1) {
|
||||
mSeed = globalSeed;
|
||||
}
|
||||
}
|
||||
|
||||
ParticleBase::~ParticleBase()
|
||||
|
40
extern/mantaflow/preprocessed/particle.h
vendored
40
extern/mantaflow/preprocessed/particle.h
vendored
@ -47,7 +47,7 @@ class ParticleBase : public PbClass {
|
||||
PINVALID = (1 << 30), // unused
|
||||
};
|
||||
|
||||
ParticleBase(FluidSolver *parent);
|
||||
ParticleBase(FluidSolver *parent, int fixedSeed = -1);
|
||||
static int _W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
{
|
||||
PbClass *obj = Pb::objFromPy(_self);
|
||||
@ -60,7 +60,8 @@ class ParticleBase : public PbClass {
|
||||
{
|
||||
ArgLocker _lock;
|
||||
FluidSolver *parent = _args.getPtr<FluidSolver>("parent", 0, &_lock);
|
||||
obj = new ParticleBase(parent);
|
||||
int fixedSeed = _args.getOpt<int>("fixedSeed", 1, -1, &_lock);
|
||||
obj = new ParticleBase(parent, fixedSeed);
|
||||
obj->registerObject(_self, &_args);
|
||||
_args.check();
|
||||
}
|
||||
@ -111,6 +112,11 @@ class ParticleBase : public PbClass {
|
||||
return;
|
||||
}
|
||||
|
||||
inline int getSeed()
|
||||
{
|
||||
return mSeed;
|
||||
}
|
||||
|
||||
//! particle data functions
|
||||
|
||||
//! create a particle data object
|
||||
@ -192,9 +198,13 @@ class ParticleBase : public PbClass {
|
||||
//! per particle)
|
||||
std::vector<ParticleDataImpl<Real> *> mPdataReal;
|
||||
std::vector<ParticleDataImpl<Vec3> *> mPdataVec3;
|
||||
std::vector<ParticleDataImpl<int> *>
|
||||
mPdataInt; //! indicate that pdata of this particle system is copied, and needs to be freed
|
||||
std::vector<ParticleDataImpl<int> *> mPdataInt;
|
||||
//! indicate that pdata of this particle system is copied, and needs to be freed
|
||||
bool mFreePdata;
|
||||
|
||||
//! custom seed for particle systems, used by plugins
|
||||
int mSeed; //! fix global random seed storage, used mainly by functions in this class
|
||||
static int globalSeed;
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@ -2285,15 +2295,14 @@ void ParticleSystem<S>::advectInGrid(const FlagGrid &flags,
|
||||
}
|
||||
|
||||
template<class S> struct KnProjectParticles : public KernelBase {
|
||||
KnProjectParticles(ParticleSystem<S> &part, Grid<Vec3> &gradient)
|
||||
: KernelBase(part.size()), part(part), gradient(gradient)
|
||||
KnProjectParticles(ParticleSystem<S> &part, Grid<Vec3> &gradient, RandomStream &rand)
|
||||
: KernelBase(part.size()), part(part), gradient(gradient), rand(rand)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
}
|
||||
inline void op(IndexInt idx, ParticleSystem<S> &part, Grid<Vec3> &gradient)
|
||||
inline void op(IndexInt idx, ParticleSystem<S> &part, Grid<Vec3> &gradient, RandomStream &rand)
|
||||
{
|
||||
static RandomStream rand(3123984);
|
||||
const double jlen = 0.1;
|
||||
|
||||
if (part.isActive(idx)) {
|
||||
@ -2321,6 +2330,11 @@ template<class S> struct KnProjectParticles : public KernelBase {
|
||||
return gradient;
|
||||
}
|
||||
typedef Grid<Vec3> type1;
|
||||
inline RandomStream &getArg2()
|
||||
{
|
||||
return rand;
|
||||
}
|
||||
typedef RandomStream type2;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel KnProjectParticles ", 3);
|
||||
@ -2332,15 +2346,17 @@ template<class S> struct KnProjectParticles : public KernelBase {
|
||||
{
|
||||
const IndexInt _sz = size;
|
||||
for (IndexInt i = 0; i < _sz; i++)
|
||||
op(i, part, gradient);
|
||||
op(i, part, gradient, rand);
|
||||
}
|
||||
ParticleSystem<S> ∂
|
||||
Grid<Vec3> &gradient;
|
||||
RandomStream &rand;
|
||||
};
|
||||
|
||||
template<class S> void ParticleSystem<S>::projectOutside(Grid<Vec3> &gradient)
|
||||
{
|
||||
KnProjectParticles<S>(*this, gradient);
|
||||
RandomStream rand(globalSeed);
|
||||
KnProjectParticles<S>(*this, gradient, rand);
|
||||
}
|
||||
|
||||
template<class S> struct KnProjectOutOfBnd : public KernelBase {
|
||||
@ -2531,14 +2547,14 @@ template<class S> void ParticleSystem<S>::insertBufferedParticles()
|
||||
|
||||
int insertFlag;
|
||||
Vec3 insertPos;
|
||||
static RandomStream mRand(9832);
|
||||
RandomStream rand(globalSeed);
|
||||
for (IndexInt i = 0; i < numNewParts; ++i) {
|
||||
|
||||
// get random index in newBuffer vector
|
||||
// we are inserting particles randomly so that they are sampled uniformly in the fluid region
|
||||
// otherwise, regions of fluid can remain completely empty once mData.size() == maxParticles is
|
||||
// reached.
|
||||
int randIndex = floor(mRand.getReal() * mNewBufferPos.size());
|
||||
int randIndex = floor(rand.getReal() * mNewBufferPos.size());
|
||||
|
||||
// get elements from new buffers with random index
|
||||
std::swap(mNewBufferPos[randIndex], mNewBufferPos.back());
|
||||
|
16
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
16
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
@ -41,7 +41,7 @@ void sampleFlagsWithParticles(const FlagGrid &flags,
|
||||
const bool is3D = flags.is3D();
|
||||
const Real jlen = randomness / discretization;
|
||||
const Vec3 disp(1.0 / discretization, 1.0 / discretization, 1.0 / discretization);
|
||||
RandomStream mRand(9832);
|
||||
RandomStream rand(parts.getSeed());
|
||||
|
||||
FOR_IJK_BND(flags, 0)
|
||||
{
|
||||
@ -53,7 +53,7 @@ void sampleFlagsWithParticles(const FlagGrid &flags,
|
||||
for (int dj = 0; dj < discretization; dj++)
|
||||
for (int di = 0; di < discretization; di++) {
|
||||
Vec3 subpos = pos + disp * Vec3(0.5 + di, 0.5 + dj, 0.5 + dk);
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * mRand.getVec3());
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * rand.getVec3());
|
||||
if (!is3D)
|
||||
subpos[2] = 0.5;
|
||||
parts.addBuffered(subpos);
|
||||
@ -113,7 +113,7 @@ void sampleLevelsetWithParticles(const LevelsetGrid &phi,
|
||||
const bool is3D = phi.is3D();
|
||||
const Real jlen = randomness / discretization;
|
||||
const Vec3 disp(1.0 / discretization, 1.0 / discretization, 1.0 / discretization);
|
||||
RandomStream mRand(9832);
|
||||
RandomStream rand(parts.getSeed());
|
||||
|
||||
if (reset) {
|
||||
parts.clear();
|
||||
@ -132,7 +132,7 @@ void sampleLevelsetWithParticles(const LevelsetGrid &phi,
|
||||
for (int dj = 0; dj < discretization; dj++)
|
||||
for (int di = 0; di < discretization; di++) {
|
||||
Vec3 subpos = pos + disp * Vec3(0.5 + di, 0.5 + dj, 0.5 + dk);
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * mRand.getVec3());
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * rand.getVec3());
|
||||
if (!is3D)
|
||||
subpos[2] = 0.5;
|
||||
if (phi.getInterpolated(subpos) > 0.)
|
||||
@ -205,7 +205,7 @@ void sampleShapeWithParticles(const Shape &shape,
|
||||
const bool is3D = flags.is3D();
|
||||
const Real jlen = randomness / discretization;
|
||||
const Vec3 disp(1.0 / discretization, 1.0 / discretization, 1.0 / discretization);
|
||||
RandomStream mRand(9832);
|
||||
RandomStream rand(parts.getSeed());
|
||||
|
||||
if (reset) {
|
||||
parts.clear();
|
||||
@ -223,7 +223,7 @@ void sampleShapeWithParticles(const Shape &shape,
|
||||
for (int dj = 0; dj < discretization; dj++)
|
||||
for (int di = 0; di < discretization; di++) {
|
||||
Vec3 subpos = pos + disp * Vec3(0.5 + di, 0.5 + dj, 0.5 + dk);
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * mRand.getVec3());
|
||||
subpos += jlen * (Vec3(1, 1, 1) - 2.0 * rand.getVec3());
|
||||
if (!is3D)
|
||||
subpos[2] = 0.5;
|
||||
if (exclude && exclude->getInterpolated(subpos) <= 0.)
|
||||
@ -576,7 +576,7 @@ void adjustNumber(BasicParticleSystem &parts,
|
||||
}
|
||||
|
||||
// seed new particles
|
||||
RandomStream mRand(9832);
|
||||
RandomStream rand(parts.getSeed());
|
||||
FOR_IJK(tmp)
|
||||
{
|
||||
int cnt = tmp(i, j, k);
|
||||
@ -593,7 +593,7 @@ void adjustNumber(BasicParticleSystem &parts,
|
||||
|
||||
if (flags.isFluid(i, j, k) && cnt < minParticles) {
|
||||
for (int m = cnt; m < minParticles; m++) {
|
||||
Vec3 pos = Vec3(i, j, k) + mRand.getVec3();
|
||||
Vec3 pos = Vec3(i, j, k) + rand.getVec3();
|
||||
// Vec3 pos (i + 0.5, j + 0.5, k + 0.5); // cell center
|
||||
parts.addBuffered(pos);
|
||||
}
|
||||
|
@ -479,7 +479,8 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
const Real k_ta,
|
||||
const Real k_wc,
|
||||
const Real dt,
|
||||
const int itype = FlagGrid::TypeFluid)
|
||||
const int itype,
|
||||
RandomStream &rand)
|
||||
: KernelBase(&flags, 0),
|
||||
flags(flags),
|
||||
v(v),
|
||||
@ -497,7 +498,8 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
k_ta(k_ta),
|
||||
k_wc(k_wc),
|
||||
dt(dt),
|
||||
itype(itype)
|
||||
itype(itype),
|
||||
rand(rand)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
@ -521,13 +523,13 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
const Real k_ta,
|
||||
const Real k_wc,
|
||||
const Real dt,
|
||||
const int itype = FlagGrid::TypeFluid)
|
||||
const int itype,
|
||||
RandomStream &rand)
|
||||
{
|
||||
|
||||
if (!(flags(i, j, k) & itype))
|
||||
return;
|
||||
|
||||
static RandomStream mRand(9832);
|
||||
Real radius =
|
||||
0.25; // diameter=0.5 => sampling with two cylinders in each dimension since cell size=1
|
||||
for (Real x = i - radius; x <= i + radius; x += 2 * radius) {
|
||||
@ -549,9 +551,9 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
cross(e1, dir)); // perpendicular to dir and e1, so e1 and e1 create reference plane
|
||||
|
||||
for (int di = 0; di < n; di++) {
|
||||
const Real r = radius * sqrt(mRand.getReal()); // distance to cylinder axis
|
||||
const Real theta = mRand.getReal() * Real(2) * M_PI; // azimuth
|
||||
const Real h = mRand.getReal() * norm(dt * vi); // distance to reference plane
|
||||
const Real r = radius * sqrt(rand.getReal()); // distance to cylinder axis
|
||||
const Real theta = rand.getReal() * Real(2) * M_PI; // azimuth
|
||||
const Real h = rand.getReal() * norm(dt * vi); // distance to reference plane
|
||||
Vec3 xd = xi + r * cos(theta) * e1 + r * sin(theta) * e2 + h * getNormalized(vi);
|
||||
if (!flags.is3D())
|
||||
xd.z = 0;
|
||||
@ -561,7 +563,7 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
vi; // init velocity of new particle
|
||||
Real temp = (KE + TA + WC) / 3;
|
||||
l_sec[l_sec.size() - 1] = ((lMax - lMin) * temp) + lMin +
|
||||
mRand.getReal() * 0.1; // init lifetime of new particle
|
||||
rand.getReal() * 0.1; // init lifetime of new particle
|
||||
|
||||
// init type of new particle
|
||||
if (neighborRatio(i, j, k) < c_s) {
|
||||
@ -663,6 +665,11 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
return itype;
|
||||
}
|
||||
typedef int type16;
|
||||
inline RandomStream &getArg17()
|
||||
{
|
||||
return rand;
|
||||
}
|
||||
typedef RandomStream type17;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel knFlipSampleSecondaryParticlesMoreCylinders ", 3);
|
||||
@ -696,7 +703,8 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
k_ta,
|
||||
k_wc,
|
||||
dt,
|
||||
itype);
|
||||
itype,
|
||||
rand);
|
||||
}
|
||||
const FlagGrid &flags;
|
||||
const MACGrid &v;
|
||||
@ -715,6 +723,7 @@ struct knFlipSampleSecondaryParticlesMoreCylinders : public KernelBase {
|
||||
const Real k_wc;
|
||||
const Real dt;
|
||||
const int itype;
|
||||
RandomStream &rand;
|
||||
};
|
||||
|
||||
// adds secondary particles to &pts_sec for every fluid cell in &flags according to the potential
|
||||
@ -738,7 +747,8 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
const Real k_ta,
|
||||
const Real k_wc,
|
||||
const Real dt,
|
||||
const int itype = FlagGrid::TypeFluid)
|
||||
const int itype,
|
||||
RandomStream &rand)
|
||||
: KernelBase(&flags, 0),
|
||||
flags(flags),
|
||||
v(v),
|
||||
@ -756,7 +766,8 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
k_ta(k_ta),
|
||||
k_wc(k_wc),
|
||||
dt(dt),
|
||||
itype(itype)
|
||||
itype(itype),
|
||||
rand(rand)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
@ -780,7 +791,8 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
const Real k_ta,
|
||||
const Real k_wc,
|
||||
const Real dt,
|
||||
const int itype = FlagGrid::TypeFluid)
|
||||
const int itype,
|
||||
RandomStream &rand)
|
||||
{
|
||||
|
||||
if (!(flags(i, j, k) & itype))
|
||||
@ -793,9 +805,8 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
const int n = KE * (k_ta * TA + k_wc * WC) * dt; // number of secondary particles
|
||||
if (n == 0)
|
||||
return;
|
||||
static RandomStream mRand(9832);
|
||||
|
||||
Vec3 xi = Vec3(i, j, k) + mRand.getVec3(); // randomized offset uniform in cell
|
||||
Vec3 xi = Vec3(i, j, k) + rand.getVec3(); // randomized offset uniform in cell
|
||||
Vec3 vi = v.getInterpolated(xi);
|
||||
Vec3 dir = dt * vi; // direction of movement of current particle
|
||||
Vec3 e1 = getNormalized(Vec3(dir.z, 0, -dir.x)); // perpendicular to dir
|
||||
@ -803,9 +814,9 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
cross(e1, dir)); // perpendicular to dir and e1, so e1 and e1 create reference plane
|
||||
|
||||
for (int di = 0; di < n; di++) {
|
||||
const Real r = Real(0.5) * sqrt(mRand.getReal()); // distance to cylinder axis
|
||||
const Real theta = mRand.getReal() * Real(2) * M_PI; // azimuth
|
||||
const Real h = mRand.getReal() * norm(dt * vi); // distance to reference plane
|
||||
const Real r = Real(0.5) * sqrt(rand.getReal()); // distance to cylinder axis
|
||||
const Real theta = rand.getReal() * Real(2) * M_PI; // azimuth
|
||||
const Real h = rand.getReal() * norm(dt * vi); // distance to reference plane
|
||||
Vec3 xd = xi + r * cos(theta) * e1 + r * sin(theta) * e2 + h * getNormalized(vi);
|
||||
if (!flags.is3D())
|
||||
xd.z = 0;
|
||||
@ -815,7 +826,7 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
vi; // init velocity of new particle
|
||||
Real temp = (KE + TA + WC) / 3;
|
||||
l_sec[l_sec.size() - 1] = ((lMax - lMin) * temp) + lMin +
|
||||
mRand.getReal() * 0.1; // init lifetime of new particle
|
||||
rand.getReal() * 0.1; // init lifetime of new particle
|
||||
|
||||
// init type of new particle
|
||||
if (neighborRatio(i, j, k) < c_s) {
|
||||
@ -914,6 +925,11 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
return itype;
|
||||
}
|
||||
typedef int type16;
|
||||
inline RandomStream &getArg17()
|
||||
{
|
||||
return rand;
|
||||
}
|
||||
typedef RandomStream type17;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel knFlipSampleSecondaryParticles ", 3);
|
||||
@ -947,7 +963,8 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
k_ta,
|
||||
k_wc,
|
||||
dt,
|
||||
itype);
|
||||
itype,
|
||||
rand);
|
||||
}
|
||||
const FlagGrid &flags;
|
||||
const MACGrid &v;
|
||||
@ -966,6 +983,7 @@ struct knFlipSampleSecondaryParticles : public KernelBase {
|
||||
const Real k_wc;
|
||||
const Real dt;
|
||||
const int itype;
|
||||
RandomStream &rand;
|
||||
};
|
||||
|
||||
void flipSampleSecondaryParticles(const std::string mode,
|
||||
@ -992,6 +1010,9 @@ void flipSampleSecondaryParticles(const std::string mode,
|
||||
if (dt <= 0)
|
||||
timestep = flags.getParent()->getDt();
|
||||
|
||||
/* Every particle needs to get a different random offset. */
|
||||
RandomStream rand(pts_sec.getSeed());
|
||||
|
||||
if (mode == "single") {
|
||||
knFlipSampleSecondaryParticles(flags,
|
||||
v,
|
||||
@ -1009,7 +1030,8 @@ void flipSampleSecondaryParticles(const std::string mode,
|
||||
k_ta,
|
||||
k_wc,
|
||||
timestep,
|
||||
itype);
|
||||
itype,
|
||||
rand);
|
||||
}
|
||||
else if (mode == "multiple") {
|
||||
knFlipSampleSecondaryParticlesMoreCylinders(flags,
|
||||
@ -1028,7 +1050,8 @@ void flipSampleSecondaryParticles(const std::string mode,
|
||||
k_ta,
|
||||
k_wc,
|
||||
timestep,
|
||||
itype);
|
||||
itype,
|
||||
rand);
|
||||
}
|
||||
else {
|
||||
throw std::invalid_argument("Unknown mode: use \"single\" or \"multiple\" instead!");
|
||||
|
@ -871,6 +871,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
|
||||
mRNAMap["CACHE_DIR"] = cacheDirectory;
|
||||
mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod;
|
||||
mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf;
|
||||
mRNAMap["CLIP_OPENVDB"] = to_string(fds->clipping);
|
||||
mRNAMap["PP_PARTICLE_MAXIMUM"] = to_string(fds->sys_particle_maximum);
|
||||
|
||||
/* Fluid object names. */
|
||||
|
@ -159,6 +159,7 @@ gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell
|
||||
# OpenVDB options\n\
|
||||
vdbCompression_s$ID$ = $COMPRESSION_OPENVDB$\n\
|
||||
vdbPrecision_s$ID$ = $PRECISION_OPENVDB$\n\
|
||||
vdbClip_s$ID$ = $CLIP_OPENVDB$\n\
|
||||
\n\
|
||||
# Cache file names\n\
|
||||
file_data_s$ID$ = '$NAME_DATA$'\n\
|
||||
@ -264,8 +265,8 @@ const std::string fluid_alloc =
|
||||
"\n\
|
||||
mantaMsg('Fluid alloc data')\n\
|
||||
flags_s$ID$ = s$ID$.create(FlagGrid, name='$NAME_FLAGS$')\n\
|
||||
vel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITY$')\n\
|
||||
velTmp_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITYTMP$')\n\
|
||||
vel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITY$', sparse=True)\n\
|
||||
velTmp_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITYTMP$', sparse=True)\n\
|
||||
x_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_X$')\n\
|
||||
y_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_Y$')\n\
|
||||
z_vel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_VELOCITY_Z$')\n\
|
||||
@ -682,7 +683,7 @@ def fluid_load_vel_$ID$(path, framenr, file_format):\n\
|
||||
|
||||
const std::string fluid_file_export =
|
||||
"\n\
|
||||
def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mode_override=True, skip_subframes=True):\n\
|
||||
def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mode_override=True, skip_subframes=True, clipGrid=None):\n\
|
||||
if skip_subframes and ((timePerFrame_s$ID$ + dt0_s$ID$) < frameLength_s$ID$):\n\
|
||||
return\n\
|
||||
mantaMsg('Fluid file export, frame: ' + str(framenr))\n\
|
||||
@ -697,7 +698,7 @@ def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mo
|
||||
file = os.path.join(path, file_name + '_' + framenr + file_format)\n\
|
||||
if not os.path.isfile(file) or mode_override:\n\
|
||||
if file_format == '.vdb':\n\
|
||||
saveCombined = save(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$, skipDeletedParts=True, compression=vdbCompression_s$ID$, precision=vdbPrecision_s$ID$)\n\
|
||||
saveCombined = save(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$, skipDeletedParts=True, compression=vdbCompression_s$ID$, precision=vdbPrecision_s$ID$, clip=vdbClip_s$ID$, clipGrid=clipGrid)\n\
|
||||
elif file_format == '.bobj.gz' or file_format == '.obj':\n\
|
||||
for name, object in dict.items():\n\
|
||||
if not os.path.isfile(file) or mode_override:\n\
|
||||
|
@ -81,11 +81,11 @@ using_fire_s$ID$ = True\n";
|
||||
const std::string smoke_alloc =
|
||||
"\n\
|
||||
mantaMsg('Smoke alloc')\n\
|
||||
shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$')\n\
|
||||
emission_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSION$')\n\
|
||||
shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$', sparse=False)\n\
|
||||
emission_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSION$', sparse=True)\n\
|
||||
emissionIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSIONIN$')\n\
|
||||
density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$')\n\
|
||||
densityIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITYIN$')\n\
|
||||
density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$', sparse=True)\n\
|
||||
densityIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITYIN$', sparse=True)\n\
|
||||
heat_s$ID$ = None # allocated dynamically\n\
|
||||
heatIn_s$ID$ = None\n\
|
||||
flame_s$ID$ = None\n\
|
||||
@ -111,7 +111,7 @@ const std::string smoke_alloc_noise =
|
||||
"\n\
|
||||
mantaMsg('Smoke alloc noise')\n\
|
||||
vel_sn$ID$ = sn$ID$.create(MACGrid, name='$NAME_VELOCITY_NOISE$')\n\
|
||||
density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITY_NOISE$')\n\
|
||||
density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITY_NOISE$', sparse=True)\n\
|
||||
phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIIN_NOISE$')\n\
|
||||
phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_NOISE$')\n\
|
||||
phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_NOISE$')\n\
|
||||
@ -135,8 +135,8 @@ color_b_sn$ID$ = None\n\
|
||||
wltnoise_sn$ID$ = sn$ID$.create(NoiseField, fixedSeed=265, loadFromFile=True)\n\
|
||||
\n\
|
||||
mantaMsg('Initializing UV Grids')\n\
|
||||
uvGrid0_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV0$')\n\
|
||||
uvGrid1_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV1$')\n\
|
||||
uvGrid0_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV0$', sparse=False)\n\
|
||||
uvGrid1_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV1$', sparse=False)\n\
|
||||
resetUvGrid(target=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
|
||||
resetUvGrid(target=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
|
||||
\n\
|
||||
@ -145,8 +145,8 @@ copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_
|
||||
copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
|
||||
\n\
|
||||
# Keep track of important objects in dict to load them later on\n\
|
||||
smoke_noise_dict_final_s$ID$ = dict(density_noise=density_sn$ID$)\n\
|
||||
smoke_noise_dict_resume_s$ID$ = dict(uv0_noise=uvGrid0_s$ID$, uv1_noise=uvGrid1_s$ID$)\n";
|
||||
smoke_noise_dict_final_s$ID$ = { 'density_noise' : density_sn$ID$ }\n\
|
||||
smoke_noise_dict_resume_s$ID$ = { 'uv0_noise' : uvGrid0_s$ID$, 'uv1_noise' : uvGrid1_s$ID$ }\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ADDITIONAL GRIDS
|
||||
@ -160,12 +160,12 @@ if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
|
||||
if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating colors')\n\
|
||||
color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$')\n\
|
||||
color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$')\n\
|
||||
color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$')\n\
|
||||
color_r_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORRIN$')\n\
|
||||
color_g_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORGIN$')\n\
|
||||
color_b_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORBIN$')\n\
|
||||
color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$', sparse=True)\n\
|
||||
color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$', sparse=True)\n\
|
||||
color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$', sparse=True)\n\
|
||||
color_r_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORRIN$', sparse=True)\n\
|
||||
color_g_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORGIN$', sparse=True)\n\
|
||||
color_b_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORBIN$', sparse=True)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_data_dict_final_s$ID$' in globals():\n\
|
||||
@ -181,9 +181,9 @@ if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
|
||||
if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating colors noise')\n\
|
||||
color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORR_NOISE$')\n\
|
||||
color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORG_NOISE$')\n\
|
||||
color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORB_NOISE$')\n\
|
||||
color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORR_NOISE$', sparse=True)\n\
|
||||
color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORG_NOISE$', sparse=True)\n\
|
||||
color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORB_NOISE$', sparse=True)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
|
||||
@ -216,8 +216,8 @@ if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
|
||||
if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating heat')\n\
|
||||
heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$')\n\
|
||||
heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$')\n\
|
||||
heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$', sparse=True)\n\
|
||||
heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$', sparse=True)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_data_dict_final_s$ID$' in globals():\n\
|
||||
@ -235,11 +235,11 @@ if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
|
||||
if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating fire')\n\
|
||||
flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$')\n\
|
||||
fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$')\n\
|
||||
react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$')\n\
|
||||
fuelIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUELIN$')\n\
|
||||
reactIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACTIN$')\n\
|
||||
flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$', sparse=True)\n\
|
||||
fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$', sparse=True)\n\
|
||||
react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$', sparse=True)\n\
|
||||
fuelIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUELIN$', sparse=True)\n\
|
||||
reactIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACTIN$', sparse=True)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_data_dict_final_s$ID$' in globals():\n\
|
||||
@ -255,9 +255,9 @@ if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
|
||||
if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating fire noise')\n\
|
||||
flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAME_NOISE$')\n\
|
||||
fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUEL_NOISE$')\n\
|
||||
react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACT_NOISE$')\n\
|
||||
flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAME_NOISE$', sparse=True)\n\
|
||||
fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUEL_NOISE$', sparse=True)\n\
|
||||
react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACT_NOISE$', sparse=True)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
|
||||
@ -575,7 +575,7 @@ def smoke_save_data_$ID$(path, framenr, file_format, resumable):\n\
|
||||
start_time = time.time()\n\
|
||||
dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ } \n\
|
||||
if not withMPSave or isWindows:\n\
|
||||
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
|
||||
fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$, clipGrid=density_s$ID$)\n\
|
||||
else:\n\
|
||||
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\
|
||||
mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n";
|
||||
@ -586,7 +586,7 @@ def smoke_save_noise_$ID$(path, framenr, file_format, resumable):\n\
|
||||
mantaMsg('Smoke save noise')\n\
|
||||
dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
|
||||
if not withMPSave or isWindows:\n\
|
||||
fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_noise_s$ID$)\n\
|
||||
fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_noise_s$ID$, clipGrid=density_sn$ID$)\n\
|
||||
else:\n\
|
||||
fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_noise_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user